!11 follow后端发布

* docs: readme
* fix: missing formPath
* chore: 去除锁定的esbuild版本
* perf: 去除debug组件
* perf: 参数键值 自动高度
* refactor: 代码生成配置页面重构 去除步骤条
* perf: 移除文件
* docs: 文件夹说明
* chore: 移除一些配置项
* chore: 注释优化
* refactor: 移除ele和naive目录
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* perf: request support to set how to return response (#5436)
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* refactor: 登录超时的i18n
* fix: requestClient缺失i18n内容
* refactor: 优化oss下载进度提示
* feat: 下载进度loading
* fix: antd button icon style (#5421)
* feat: oss下载进度(已下载的KB 无法作为进度显示 total返回为null)
* fix: 下载文件时(responseType === 'blob')需要判断下载失败(返回json而非二进制)的情况
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* refactor: 新增后跳转到未发布流程
* fix: same name route
* chore: 调整为部署json类型
* fix: mouse events ignored on modal loading (#5409)
* docs: update docs (#5408)
* refactor: 移除已经弃用的方法
* refactor: follow官方handleRangeTimeValue更新
* chore: 删除文件夹(前端路由需要的)
* chore: 修改本地路由写法(新版)/新增本地菜单图标
* fix: form update state error before form mounted (#5406)
* fix: demos route fixed (#5405)
* chore: 不使用基础布局(仅在顶级生效)
* feat: modal state locked on submitting (#5401)
* chore: 修改zIndex
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* refactor: fix popup component zIndex (#5397)
* style: element plus loading style fixed (#5393)
* perf: improve fieldMappingTime to support format function (#5392)
* fix: hide root route in breadcrumb
* feat: support set default props for drawer and modal (#5390)
* fix: root router config fixed (#5389)
* fix: 修改Vxe默认zIndex为995 解决右上角全屏后modal/drawer(zIndex: 1000)被遮挡
* feat: add `noBasicLayout` in route meta (#5386)
* chore: wechat image
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* chore: 改为全局参数配置 去除局部参数
* fix: spinner may stop playing animation after dismiss (#5365)
* style: popover bgColor is too close to common (#5364)
* docs: version update
* docs: changelog
* chore: 文件上传 描述
* ci: retry deploy while faild
* feat: 文件上传 进度条+提示文字
* feat: 文件上传 进度条
* feat: 上传文件格式说明
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into warmflow
* fix: useEcharts return invalid instance (#5360)
* feat: popup component support overlay blur effect (#5359)
* feat: improve `tippy` demo (#5357)
* feat: integrate new component `Tippy` with demo (#5355)
* chore: 优化表格图片显示
* perf: add nested modal demo (#5353)
* chore: 默认显示右边的滚动条 防止出现滚动条被挤压
* perf: modal and drawer api support chain calls (#5351)
* feat: allow close tab when mouse middle button click (#5347)
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into warmflow
* refactor: 重构显示total的逻辑
* chore: 调整高度自适应代码
* chore: vxe升级4.10.0版本(锁定)
* fix: 添加失效的option
* fix: 需要为数组
* fix: locale switching logic correction (#5344)
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into warmflow
* chore: 导入类型优化 解决eslint报红
* refactor: type/注释优化 去除大量any
* fix: vxeGrid init without search form (#5342)
* chore: 锁屏默认false  关闭该功能
* chore: 调整接口
* chore: update deps
* fix: primaryColor calculation (#5337)
* fix: form valid-error style in naive (#5336)
* fix: form `fieldMappingTime` improve and `modelPropName` support (#5335)
* fix: code lint
* fix: form `fieldMappingTime` is not working (#5333)
* chore: 选人组件样式
* fix: download from url triggered twice sometimes (#5319)
* chore: 优化代码
* chore: 动态类名(无效)改为style
* refactor: 字典相关功能重构 采用一个Map储存字典(之前为两个Map)
* feat: 字典支持number类型存储
* chore: 调整样式
* chore: 修改选中border为1px
* chore: 字段
* chore: 改为新窗口打开(适用于pdf/图片)而非直接下载
* chore: 更新样式
* chore: 更新字段
* chore: 改为computed
* chore: 跳转到未发布流程tab
* chore: 优化样式
* docs: readme
* fix: name重复导致的404
* Merge branch 'dev' of https://gitee.com/dapppp/ruoyi-plus-vben5 into warmflow
* chore: 使用legacy来保证copy的兼容性
* chore: 去除log 添加说明
* chore: 优化代码
* feat: 节点关联/节点独立的切换逻辑
* chore: remove logic
* chore: vxe可编辑表格demo
* chore: 不允许在按钮下添加数据
* docs: changelog
* fix: wrong code
* chore: 移除测试菜单
* chore: 优化代码
* refactor: 租户套餐菜单替换为新版
* refactor: 使用新版菜单勾选
* chore: 点行会勾选/取消全部权限  点权限不会勾选行
* chore: 全屏引导+样式优化
* chore: 调整间距
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* feat: useEcharts exports echarts instance#5294 (#5299)
* chore: update quick-start.md (#5303)
* chore: updateCheckedNumber
* refactor: 优化代码
* chore: 优化代码
* chore: 优化样式
* chore: keys依赖于menu 需要先加载menu
* chore: 菜单加载完毕再显示
* feat: 新的菜单选择组件(beta)
* chore: $t
* chore: 测试菜单页面
* chore: 优化代码
* feat: 对ossId回显的支持
* chore: 只获取一次默认密码而非每次打开modal都获取
* fix: vben select placeholder color (#5286)
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* perf: format code with better style (#5283)
* chore: 工作流演示站
* fix: sidebar preferences fixed (#5276)
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* fix: breadcrumb setting not valid for `header-sidebar-nav` layout (#5275)
* fix: header logo may not be collapsed in `header-sidebar-nav` layout (#5274)
* feat: new layout `sidebar nav with full header` (#5270)
* feat: drawer close icon placement (#5269)
* docs: update dialog and drawer docs
* feat: drawer support destroy on close
* feat: drawer support `onOpened` & `onClosed`
* feat: modal support destroy on close
* fix: wrong boolean
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* chore: 调整tab位置
* chore: 删除历史流程 改为tab切换
* fix: header-mixed layout side-menu active (#5265)
* feat: header mixed layout (#5263)
* chore: release 5.5.2
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* chore: downgrade vue-tsc version
* feat: header menu align support (#5256)
* chore: update deps
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* chore: add apiSelect remote search demo (#5246)
* chore: 审批改为description而非disabled的表单
* chore: 改为ts
* chore: 错误的conetnt
* refactor: 终止/转办/委托支持填写意见
* chore: 第一次拿到的是readonly的数据 如果需要修改 需要cloneDeep
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* fix: grid form submit button locale switch (#5205)
* chore: 调整驳回
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* fix: build error (#5199)
* fix: esbuild自动升级导致运行/打包报错
* fix: esbuild自动升级导致运行/打包报错
* chore: 流程定义 激活改为switch
* chore: 流程申请支持上传文件
* chore: title 审批通过
* fix: vxeGrid top padding (#5193)
* fix: 表格排序翻页会丢失排序参数
* chore: 去除log打印
* chore: 流程监控 待办任务
* chore: 我发起的
* chore: 去除已经移除的菜单页面
* chore: 我的已办
* chore: 页面优化
* chore: 重置tooltip
* feat: 我的抄送搜索/优化重复触发的接口
* feat: 流程定义 历史
* chore: 修改分类
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* fix: grid tools in toolbar config not working as expected (#5190)
* feat: add `resizable` and `ColPage` component (#5188)
* chore: 条件
* chore: break-all
* feat: 流程分类 搜索
* chore: 弹窗关闭后仍然显示表单浮层
* chore: 选人组件的样式
* chore: 搜索的样式
* chore: 漏掉的导入
* chore: 最大显示的头像数量 超过显示为省略号头像
* fix: 选人的一些问题
* Merge branch 'warmflow' of https://gitee.com/dapppp/ruoyi-plus-vben5 i…
* chore: 没有更多数据了
* fix: sidebar header height (#5183)
* chore: 搜索表单布局+申请人
* fix: remove the overlap caused by border-b (#5160)
* docs: fix typos (#5169)
* fix: resolve eslint errors as well as TS type errors (#5172)
* chore: enter提交表单
* chore: 修改文案
* chore: 默认全部展开
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* feat: page content class override (#5179)
* fix: sidebar style on focus (#5178)
* fix: 抄送选人 最右侧已选中删除item无效
* feat: 复制
* chore: 昵称过长的显示
* chore: 默认选中第一个
* chore: 修改relative位置
* chore: 搜索
* feat: 我的待办 - 搜索条件
* chore: 流程监控 - 待办任务页面的id不唯一 改为前端处理
* feat: 修改办理人
* chore: 流程干预 - 加签/减签
* chore: avatar大小
* chore: 抄送需要手动添加createByName
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* chore: 审批通过 抄送
* feat: 流程实例-流程预览
* chore: spell
* chore: clientid
* chore: 分类条件
* chore: 修改办理人
* chore: 更改postMessage参数
* chore: 内嵌iframe高度根据表单高度调整
* chore: 流程详情
* feat: 抄送选择
* chore: 调整分类树
* fix: user homePath no effect sometimes (#5166)
* feat: form compact mode support (#5165)
* fix: form auto submit no effect when showDefaultActions is false (#5163)
* chore: 修改width
* feat: 待办任务
* feat: 我的抄送
* chore: 流程定义 样式
* chore: 退回后重新申请
* chore: 请假申请布局
* chore: 请假申请-并行会签网关
* chore: 分类去除根目录
* chore: 详情modal(未完成)
* chore: 请假申请根据不同状态显示按钮
* chore: 流程删除/撤销
* chore: 审批完成后刷新当前页
* feat: 选人组件(未完成) 加签减签
* docs: fix docs-link and add `EllipsisText` docs (#5158)
* chore: 新窗口打开文件
* chore: 审批通过
* chore: 使用useEventListener替换原生
* chore: 字段错误
* chore: iframe通信 加载完毕后才显示表单 解决卡顿问题
* chore: 审批终止/驳回
* chore: 附件图标
* chore: process_running显示按钮
* chore: label错误
* chore: 保存的事件
* chore: 需要加上clientId
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* feat: form `colon` support (#5156)
* chore: 完善请假申请
* feat: improve code login demo (#5154)
* chore: 客户端管理 行高自适应
* chore: 内嵌表单的路径
* chore: 修改avatar背景色
* chore: 注释
* chore: activePath
* chore: leave表单
* chore: 修改请假demo路径
* chore: categoryId
* chore: 我的已办
* chore: 我发起的
* chore: loading
* chore: 历史版本
* chore: 完善task api
* chore: 隐藏'菜单加载中'
* chore: missing import
* feat: add demo for modify menu badge data
* chore: 流程实例
* chore: 审批附件
* chore: 我的待办 提取公共组件
* chore: 流程部署
* chore: 新增/编辑/导出xml
* chore: 流程定义(除历史版本)
* feat: `autoActivateChild` support more layout mode (#5148)
* feat: auto activate subMenu on select root menu (#5147)
* fix: `disabledOnChangeListener` not work in form (#5146)
* fix: login expired modal z-index (#5145)
* feat: user-dropdown support `hover` trigger (#5143)
* fix: pinInput value synchronous update (#5142)
* fix: vxeGrid default sort data no effect in first query (#5141)
* fix: vscode debug profile (#5140)
* fix: form component events bind (#5137)
* chore: 在线用户样式 开启虚拟滚动
* chore: 去掉个人中心 在线设备的分页
* chore: 去掉在线用户的分页
* chore: changelog
* refactor: 获取字典的方法 提取公共函数 减少冗余代码
* fix: element plus validate failed style (#5130)
* chore: 使用私有桶的提示
* feat: tabbar support mouse wheel vertical (#5129)
* fix: form support `disabledOnInputListener` (#5127)
* fix: form submission not appropriate (#5126)
* Merge branch 'main' of https://gitee.com/dapppp/ruoyi-plus-vben5 into dev
* chore: release 5.5.1
* feat: table search form visible control (#5121)
* chore: 需要隐藏菜单
* chore: 我的待办 & 请假
* chore: 流程定义(未完成)
* chore: 流程定义(开发中)
* Merge branch 'main' of https://gitee.com/dapppp/ruoyi-plus-vben5 into dev
* Merge branch 'main' of https://gitee.com/dapppp/ruoyi-plus-vben5 into dev
* Merge branch 'main' of https://gitee.com/dapppp/ruoyi-plus-vben5 into dev
* chore: version
* chore: 锁定vxe-table版本 4.9.8版本存在样式问题
* chore: 暂时锁定cspell版本
* refactor: 由于不能输入 需要使用watch监听
* chore: https://gitee.com/dapppp/ruoyi-plus-vben5/issues/IB7ANL
* chore: 移除冗余代码
* chore: 组件卸载时移除emitter
* fix: the route path did not synchronize with the page (#4947)
* style: typo (#4948)
* chore: 替换为commonDownloadExcel
* fix: 左边部门树错误emit导致会调用两次列表api
* chore: label样式
* chore: 改为Textarea
* chore: 滚动条宽度
* chore: 审批样式
* chore: 部门及以下或本人数据权限
* Merge branch 'main' of https://gitee.com/dapppp/ruoyi-plus-vben5 into dev
* chore: 个人中心强退设备接口路径
This commit is contained in:
玲娜贝er
2025-01-20 03:43:19 +00:00
parent 8ab0bd2212
commit 29f9f3de31
729 changed files with 12839 additions and 9132 deletions

View File

@@ -1,14 +1,13 @@
<script lang="ts" setup>
import type { VNode } from 'vue';
import type {
RouteLocationNormalizedLoaded,
RouteLocationNormalizedLoadedGeneric,
} from 'vue-router';
import { type VNode } from 'vue';
import { RouterView } from 'vue-router';
import { preferences, usePreferences } from '@vben/preferences';
import { storeToRefs, useTabbarStore } from '@vben/stores';
import { RouterView } from 'vue-router';
import { IFrameRouterView } from '../../iframe';

View File

@@ -1,11 +1,10 @@
<script lang="ts" setup>
import { computed, useSlots } from 'vue';
import { useRefresh } from '@vben/hooks';
import { RotateCw } from '@vben/icons';
import { preferences, usePreferences } from '@vben/preferences';
import { useAccessStore } from '@vben/stores';
import { VbenFullScreen, VbenIconButton } from '@vben-core/shadcn-ui';
import { computed, useSlots } from 'vue';
import {
GlobalSearch,
@@ -133,7 +132,10 @@ function clearPreferencesAndLogout() {
>
<slot :name="slot.name"></slot>
</template>
<div class="flex h-full min-w-0 flex-1 items-center">
<div
:class="`menu-align-${preferences.header.menuAlign}`"
class="flex h-full min-w-0 flex-1 items-center"
>
<slot name="menu"></slot>
</div>
<div class="flex h-full min-w-0 flex-shrink-0 items-center">
@@ -166,3 +168,16 @@ function clearPreferencesAndLogout() {
</template>
</div>
</template>
<style lang="scss" scoped>
.menu-align-start {
--menu-align: start;
}
.menu-align-center {
--menu-align: center;
}
.menu-align-end {
--menu-align: end;
}
</style>

View File

@@ -1,10 +1,12 @@
<script lang="ts" setup>
import type { SetupContext } from 'vue';
import type { MenuRecordRaw } from '@vben/types';
import { computed, useSlots, watch } from 'vue';
import { useRefresh } from '@vben/hooks';
import { $t } from '@vben/locales';
import { $t, i18n } from '@vben/locales';
import {
preferences,
updatePreferences,
@@ -12,6 +14,7 @@ import {
} from '@vben/preferences';
import { useLockStore } from '@vben/stores';
import { cloneDeep, mapTree } from '@vben/utils';
import { VbenAdminLayout } from '@vben-core/layout-ui';
import { VbenBackTop, VbenLogo } from '@vben-core/shadcn-ui';
@@ -39,6 +42,8 @@ const {
isMixedNav,
isMobile,
isSideMixedNav,
isHeaderMixedNav,
isHeaderSidebarNav,
layout,
preferencesButtonPosition,
sidebarCollapsed,
@@ -80,16 +85,32 @@ const logoCollapsed = computed(() => {
if (isMobile.value && sidebarCollapsed.value) {
return true;
}
if (isHeaderNav.value || isMixedNav.value) {
if (isHeaderNav.value || isMixedNav.value || isHeaderSidebarNav.value) {
return false;
}
return sidebarCollapsed.value || isSideMixedNav.value;
return (
sidebarCollapsed.value || isSideMixedNav.value || isHeaderMixedNav.value
);
});
const showHeaderNav = computed(() => {
return !isMobile.value && (isHeaderNav.value || isMixedNav.value);
return (
!isMobile.value &&
(isHeaderNav.value || isMixedNav.value || isHeaderMixedNav.value)
);
});
const {
handleMenuSelect,
handleMenuOpen,
headerActive,
headerMenus,
sidebarActive,
sidebarMenus,
mixHeaderMenus,
sidebarVisible,
} = useMixedMenu();
// 侧边多列菜单
const {
extraActiveMenu,
@@ -99,16 +120,7 @@ const {
handleMixedMenuSelect,
handleSideMouseLeave,
sidebarExtraVisible,
} = useExtraMenu();
const {
handleMenuSelect,
headerActive,
headerMenus,
sidebarActive,
sidebarMenus,
sidebarVisible,
} = useMixedMenu();
} = useExtraMenu(mixHeaderMenus);
/**
* 包装菜单,翻译菜单名称
@@ -151,9 +163,10 @@ watch(
);
// 语言更新后,刷新页面
watch(() => preferences.app.locale, refresh);
// i18n.global.locale会在preference.app.locale变更之后才会更新因此watchpreference.app.locale是不合适的刷新页面时可能语言配置尚未完全加载完成
watch(i18n.global.locale, refresh, { flush: 'post' });
const slots = useSlots();
const slots: SetupContext['slots'] = useSlots();
const headerSlots = computed(() => {
return Object.keys(slots).filter((key) => key.startsWith('header-'));
});
@@ -260,13 +273,14 @@ const headerSlots = computed(() => {
:rounded="isMenuRounded"
:theme="sidebarTheme"
mode="vertical"
@open="handleMenuOpen"
@select="handleMenuSelect"
/>
</template>
<template #mixed-menu>
<LayoutMixedMenu
:active-path="extraActiveMenu"
:menus="wrapperMenus(headerMenus, false)"
:menus="wrapperMenus(mixHeaderMenus, false)"
:rounded="isMenuRounded"
:theme="sidebarTheme"
@default-select="handleDefaultSelect"

View File

@@ -2,9 +2,8 @@
import type { MenuRecordRaw } from '@vben/types';
import type { MenuProps } from '@vben-core/menu-ui';
import { useRoute } from 'vue-router';
import { Menu } from '@vben-core/menu-ui';
import { useRoute } from 'vue-router';
import { useNavigation } from './use-navigation';

View File

@@ -14,12 +14,17 @@ const props = withDefaults(defineProps<Props>(), {
});
const emit = defineEmits<{
open: [string, string[]];
select: [string, string?];
}>();
function handleMenuSelect(key: string) {
emit('select', key, props.mode);
}
function handleMenuOpen(key: string, path: string[]) {
emit('open', key, path);
}
</script>
<template>
@@ -32,6 +37,7 @@ function handleMenuSelect(key: string) {
:mode="mode"
:rounded="rounded"
:theme="theme"
@open="handleMenuOpen"
@select="handleMenuSelect"
/>
</template>

View File

@@ -2,11 +2,10 @@
import type { MenuRecordRaw } from '@vben/types';
import type { NormalMenuProps } from '@vben-core/menu-ui';
import { onBeforeMount } from 'vue';
import { useRoute } from 'vue-router';
import { findMenuByPath } from '@vben/utils';
import { NormalMenu } from '@vben-core/menu-ui';
import { onBeforeMount } from 'vue';
import { useRoute } from 'vue-router';
interface Props extends NormalMenuProps {}

View File

@@ -1,24 +1,30 @@
import type { MenuRecordRaw } from '@vben/types';
import { computed, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import type { ComputedRef } from 'vue';
import { preferences } from '@vben/preferences';
import { useAccessStore } from '@vben/stores';
import { findRootMenuByPath } from '@vben/utils';
import { computed, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import { useNavigation } from './use-navigation';
function useExtraMenu() {
function useExtraMenu(useRootMenus?: ComputedRef<MenuRecordRaw[]>) {
const accessStore = useAccessStore();
const { navigation } = useNavigation();
const menus = computed(() => accessStore.accessMenus);
const menus = computed(() => useRootMenus?.value ?? accessStore.accessMenus);
/** 记录当前顶级菜单下哪个子菜单最后激活 */
const defaultSubMap = new Map<string, string>();
const extraRootMenus = ref<MenuRecordRaw[]>([]);
const route = useRoute();
const extraMenus = ref<MenuRecordRaw[]>([]);
const sidebarExtraVisible = ref<boolean>(false);
const extraActiveMenu = ref('');
const parentLevel = computed(() =>
preferences.app.layout === 'header-mixed-nav' ? 1 : 0,
);
/**
* 选择混合菜单事件
@@ -26,12 +32,18 @@ function useExtraMenu() {
*/
const handleMixedMenuSelect = async (menu: MenuRecordRaw) => {
extraMenus.value = menu?.children ?? [];
extraActiveMenu.value = menu.parents?.[0] ?? menu.path;
extraActiveMenu.value = menu.parents?.[parentLevel.value] ?? menu.path;
const hasChildren = extraMenus.value.length > 0;
sidebarExtraVisible.value = hasChildren;
if (!hasChildren) {
await navigation(menu.path);
} else if (preferences.sidebar.autoActivateChild) {
await navigation(
defaultSubMap.has(menu.path)
? (defaultSubMap.get(menu.path) as string)
: menu.path,
);
}
};
@@ -40,12 +52,12 @@ function useExtraMenu() {
* @param menu
* @param rootMenu
*/
const handleDefaultSelect = (
const handleDefaultSelect = async (
menu: MenuRecordRaw,
rootMenu?: MenuRecordRaw,
) => {
extraMenus.value = rootMenu?.children ?? [];
extraActiveMenu.value = menu.parents?.[0] ?? menu.path;
extraMenus.value = rootMenu?.children ?? extraRootMenus.value ?? [];
extraActiveMenu.value = menu.parents?.[parentLevel.value] ?? menu.path;
if (preferences.sidebar.expandOnHover) {
sidebarExtraVisible.value = extraMenus.value.length > 0;
@@ -59,7 +71,6 @@ function useExtraMenu() {
if (preferences.sidebar.expandOnHover) {
return;
}
sidebarExtraVisible.value = false;
const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath(
menus.value,
@@ -73,24 +84,31 @@ function useExtraMenu() {
if (!preferences.sidebar.expandOnHover) {
const { findMenu } = findRootMenuByPath(menus.value, menu.path);
extraMenus.value = findMenu?.children ?? [];
extraActiveMenu.value = menu.parents?.[0] ?? menu.path;
extraActiveMenu.value = menu.parents?.[parentLevel.value] ?? menu.path;
sidebarExtraVisible.value = extraMenus.value.length > 0;
}
};
function calcExtraMenus(path: string) {
const currentPath = route.meta?.activePath || path;
const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath(
menus.value,
currentPath,
parentLevel.value,
);
extraRootMenus.value = rootMenu?.children ?? [];
if (rootMenuPath) defaultSubMap.set(rootMenuPath, currentPath);
extraActiveMenu.value = rootMenuPath ?? findMenu?.path ?? '';
extraMenus.value = rootMenu?.children ?? [];
if (preferences.sidebar.expandOnHover) {
sidebarExtraVisible.value = extraMenus.value.length > 0;
}
}
watch(
() => route.path,
(path) => {
const currentPath = route.meta?.activePath || path;
// if (preferences.sidebar.expandOnHover) {
// return;
// }
const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath(
menus.value,
currentPath,
);
extraActiveMenu.value = rootMenuPath ?? findMenu?.path ?? '';
extraMenus.value = rootMenu?.children ?? [];
() => [route.path, preferences.app.layout],
([path]) => {
calcExtraMenus(path || '');
},
{ immediate: true },
);

View File

@@ -15,11 +15,16 @@ function useMixedMenu() {
const route = useRoute();
const splitSideMenus = ref<MenuRecordRaw[]>([]);
const rootMenuPath = ref<string>('');
const { isMixedNav } = usePreferences();
const mixedRootMenuPath = ref<string>('');
const mixExtraMenus = ref<MenuRecordRaw[]>([]);
/** 记录当前顶级菜单下哪个子菜单最后激活 */
const defaultSubMap = new Map<string, string>();
const { isMixedNav, isHeaderMixedNav } = usePreferences();
const needSplit = computed(
() => preferences.navigation.split && isMixedNav.value,
() =>
(preferences.navigation.split && isMixedNav.value) ||
isHeaderMixedNav.value,
);
const sidebarVisible = computed(() => {
@@ -53,6 +58,10 @@ function useMixedMenu() {
return needSplit.value ? splitSideMenus.value : menus.value;
});
const mixHeaderMenus = computed(() => {
return isHeaderMixedNav.value ? sidebarMenus.value : headerMenus.value;
});
/**
* 侧边菜单激活路径
*/
@@ -86,6 +95,25 @@ function useMixedMenu() {
splitSideMenus.value = rootMenu?.children ?? [];
if (splitSideMenus.value.length === 0) {
navigation(key);
} else if (rootMenu && preferences.sidebar.autoActivateChild) {
navigation(
defaultSubMap.has(rootMenu.path)
? (defaultSubMap.get(rootMenu.path) as string)
: rootMenu.path,
);
}
};
/**
* 侧边菜单展开事件
* @param key 路由路径
* @param parentsPath 父级路径
*/
const handleMenuOpen = (key: string, parentsPath: string[]) => {
if (parentsPath.length <= 1 && preferences.sidebar.autoActivateChild) {
navigation(
defaultSubMap.has(key) ? (defaultSubMap.get(key) as string) : key,
);
}
};
@@ -98,6 +126,9 @@ function useMixedMenu() {
if (!rootMenu) {
rootMenu = menus.value.find((item) => item.path === path);
}
const result = findRootMenuByPath(rootMenu?.children || [], path, 1);
mixedRootMenuPath.value = result.rootMenuPath ?? '';
mixExtraMenus.value = result.rootMenu?.children ?? [];
rootMenuPath.value = rootMenu?.path ?? '';
splitSideMenus.value = rootMenu?.children ?? [];
}
@@ -107,6 +138,8 @@ function useMixedMenu() {
(path) => {
const currentPath = (route?.meta?.activePath as string) ?? path;
calcSideMenus(currentPath);
if (rootMenuPath.value)
defaultSubMap.set(rootMenuPath.value, currentPath);
},
{ immediate: true },
);
@@ -118,10 +151,13 @@ function useMixedMenu() {
return {
handleMenuSelect,
handleMenuOpen,
headerActive,
headerMenus,
sidebarActive,
sidebarMenus,
mixHeaderMenus,
mixExtraMenus,
sidebarVisible,
};
}

View File

@@ -1,6 +1,7 @@
import { type RouteRecordNormalized, useRouter } from 'vue-router';
import type { RouteRecordNormalized } from 'vue-router';
import { isHttpUrl, openRouteInNewWindow, openWindow } from '@vben/utils';
import { useRouter } from 'vue-router';
function useNavigation() {
const router = useRouter();

View File

@@ -5,6 +5,7 @@ import { useRoute } from 'vue-router';
import { useContentMaximize, useTabs } from '@vben/hooks';
import { preferences } from '@vben/preferences';
import { useTabbarStore } from '@vben/stores';
import { TabsToolMore, TabsToolScreen, TabsView } from '@vben-core/tabs-ui';
import { useTabbar } from './use-tabbar';
@@ -55,6 +56,8 @@ if (!preferences.tabbar.persist) {
:show-icon="showIcon"
:style-type="preferences.tabbar.styleType"
:tabs="currentTabs"
:wheelable="preferences.tabbar.wheelable"
:middle-click-to-close="preferences.tabbar.middleClickToClose"
@close="handleClose"
@sort-tabs="tabbarStore.sortTabs"
@unpin="unpinTab"

View File

@@ -2,9 +2,6 @@ import type { TabDefinition } from '@vben/types';
import type { IContextMenuItem } from '@vben-core/tabs-ui';
import type { RouteLocationNormalizedGeneric } from 'vue-router';
import { computed, ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { useContentMaximize, useTabs } from '@vben/hooks';
import {
ArrowLeftToLine,
@@ -22,6 +19,8 @@ import {
import { $t, useI18n } from '@vben/locales';
import { useAccessStore, useTabbarStore } from '@vben/stores';
import { filterTree } from '@vben/utils';
import { computed, ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
export function useTabbar() {
const router = useRouter();