Browse Source

页面菜单优化

main
wang 1 month ago
parent
commit
0cfafa6633
  1. 21
      smart-flow-web/src/layout/components/side-menu/recursion-menu.vue
  2. 30
      smart-flow-web/src/layout/components/top-side-menu/recursion-menu.vue
  3. 6
      smart-flow-web/src/router/index.js
  4. 73
      smart-flow-web/src/store/modules/system/user.js
  5. 26
      smart-flow-web/src/views/jwpy/jwpy/flow/index.vue

21
smart-flow-web/src/layout/components/side-menu/recursion-menu.vue

@ -33,7 +33,7 @@
import SubMenu from './sub-menu.vue'; import SubMenu from './sub-menu.vue';
import { router } from '/@/router/index'; import { router } from '/@/router/index';
import { useAppConfigStore } from '/@/store/modules/system/app-config'; import { useAppConfigStore } from '/@/store/modules/system/app-config';
import { useUserStore } from '/@/store/modules/system/user'; import { useUserStore, stateIndexMap } from '/@/store/modules/system/user';
const theme = computed(() => useAppConfigStore().$state.sideMenuTheme); const theme = computed(() => useAppConfigStore().$state.sideMenuTheme);
const flatPattern = computed(() => useAppConfigStore().$state.flatPattern); const flatPattern = computed(() => useAppConfigStore().$state.flatPattern);
@ -64,16 +64,31 @@
* SmartAdmin中 router的name 就是 后端存储menu的id * SmartAdmin中 router的name 就是 后端存储menu的id
* 所以此处可以直接监听路由根据路由更新菜单的选中和展开 * 所以此处可以直接监听路由根据路由更新菜单的选中和展开
*/ */
function updateOpenKeysAndSelectKeys() { function updateOpenKeysAndSelectKeys() {
let currentMenuId = _.toNumber(currentRoute.name);
//
const tabType = currentRoute.params.tabType;
if (tabType && stateIndexMap[tabType]) {
currentMenuId = currentMenuId * 100 + stateIndexMap[tabType];
}
// watch
if (selectedKeys.value.includes(currentMenuId)) {
return;
}
// //
selectedKeys.value = [_.toNumber(currentRoute.name)]; selectedKeys.value = [currentMenuId];
/** /**
* 更新展开1获取新展开的menu key集合2保留原有的openkeys然后把新展开的与之合并 * 更新展开1获取新展开的menu key集合2保留原有的openkeys然后把新展开的与之合并
*/ */
//menu key //menu key
let menuParentIdListMap = useUserStore().getMenuParentIdListMap; let menuParentIdListMap = useUserStore().getMenuParentIdListMap;
let parentList = menuParentIdListMap.get(currentRoute.name) || []; let parentList = menuParentIdListMap.get(currentMenuId.toString()) || [];
// openkey // openkey
if (!props.collapsed) { if (!props.collapsed) {

30
smart-flow-web/src/layout/components/top-side-menu/recursion-menu.vue

@ -29,7 +29,7 @@
import SubMenu from './sub-menu.vue'; import SubMenu from './sub-menu.vue';
import { router } from '/@/router/index'; import { router } from '/@/router/index';
import { useAppConfigStore } from '/@/store/modules/system/app-config'; import { useAppConfigStore } from '/@/store/modules/system/app-config';
import { useUserStore } from '/@/store/modules/system/user'; import { useUserStore, stateIndexMap } from '/@/store/modules/system/user';
const theme = computed(() => useAppConfigStore().$state.sideMenuTheme); const theme = computed(() => useAppConfigStore().$state.sideMenuTheme);
const flatPattern = computed(() => useAppConfigStore().$state.flatPattern); const flatPattern = computed(() => useAppConfigStore().$state.flatPattern);
@ -58,13 +58,28 @@
router.push({ path: menu.path }); router.push({ path: menu.path });
} }
function updateOpenKeysAndSelectKeys() { function updateOpenKeysAndSelectKeys() {
let currentMenuId = _.toNumber(currentRoute.name);
//
const tabType = currentRoute.params.tabType;
if (tabType && stateIndexMap[tabType]) {
currentMenuId = currentMenuId * 100 + stateIndexMap[tabType];
}
// watch
if (selectedKeys.value.includes(currentMenuId)) {
return;
}
// //
selectedKeys.value = [_.toNumber(currentRoute.name)]; selectedKeys.value = [currentMenuId];
// menu key // menu key
let menuParentIdListMap = useUserStore().getMenuParentIdListMap; let menuParentIdListMap = useUserStore().getMenuParentIdListMap;
let parentList = menuParentIdListMap.get(currentRoute.name) || []; let parentList = menuParentIdListMap.get(currentMenuId.toString()) || [];
// openkey // openkey
if (!props.collapsed) { if (!props.collapsed) {
@ -105,5 +120,14 @@
position: relative; position: relative;
border-right: none; border-right: none;
background: transparent; background: transparent;
// SubMenu
:deep(.ant-menu-submenu-title) {
color: rgba(30, 41, 59, 0.85) !important; // Slate-800
font-weight: 500;
}
:deep(.ant-menu-submenu-arrow) {
color: rgba(30, 41, 59, 0.45) !important;
}
} }
</style> </style>

6
smart-flow-web/src/router/index.js

@ -117,8 +117,12 @@ export function buildRoutes(menuRouterList) {
if (e.deletedFlag && e.deletedFlag === true) { if (e.deletedFlag && e.deletedFlag === true) {
continue; continue;
} }
let routePath = e.path.startsWith('/') ? e.path : `/${e.path}`;
if (e.component && e.component.includes('jwpy/flow/index')) {
routePath = `${routePath}/:tabType?`;
}
let route = { let route = {
path: e.path.startsWith('/') ? e.path : `/${e.path}`, path: routePath,
// 使用【menuId】作为name唯一标识 // 使用【menuId】作为name唯一标识
name: e.menuId.toString(), name: e.menuId.toString(),
meta: { meta: {

73
smart-flow-web/src/store/modules/system/user.js

@ -73,7 +73,7 @@ export const useUserStore = defineStore({
} }
return localRead(localKey.USER_TOKEN); return localRead(localKey.USER_TOKEN);
}, },
getNeedUpdatePwdFlag(state){ getNeedUpdatePwdFlag(state) {
return state.needUpdatePwdFlag; return state.needUpdatePwdFlag;
}, },
//是否初始化了 路由 //是否初始化了 路由
@ -212,7 +212,7 @@ export const useUserStore = defineStore({
// @ts-ignore // @ts-ignore
menuTitle: route.meta.title, menuTitle: route.meta.title,
menuQuery: route.query, menuQuery: route.query,
menuIcon:route.meta?.icon, menuIcon: route.meta?.icon,
// @ts-ignore // @ts-ignore
fromMenuName: from.name, fromMenuName: from.name,
fromMenuQuery: from.query, fromMenuQuery: from.query,
@ -345,6 +345,12 @@ function buildMenuTree(menuList) {
for (const topCatalog of topCatalogList) { for (const topCatalog of topCatalogList) {
buildMenuChildren(topCatalog, catalogAndMenuList); buildMenuChildren(topCatalog, catalogAndMenuList);
} }
// 3 动态为警务评议与问题处置业务菜单挂载状态折叠子菜单
for (const topCatalog of topCatalogList) {
injectWorkflowSubMenus(topCatalog);
}
return topCatalogList; return topCatalogList;
} }
@ -358,3 +364,66 @@ function buildMenuChildren(menu, allMenuList) {
buildMenuChildren(item, allMenuList); buildMenuChildren(item, allMenuList);
} }
} }
// ---------------------------- 动态工单流转状态插拔装配 ----------------------------
export const statePool = {
'all': { title: '全部工单', queryType: 'all' },
'to_handle': { title: '待办工单', queryType: 'to_handle' },
'transferred': { title: '已流转工单', queryType: 'transferred' },
'about_to_expire': { title: '即将超期工单', queryType: 'about_to_expire' },
'expired': { title: '已超期工单', queryType: 'expired' },
'completed': { title: '已办结工单', queryType: 'completed' },
'invalid': { title: '已作废工单', queryType: 'invalid' }
};
export const businessWorkflowConfig = {
default: ['all', 'to_handle', 'transferred', 'about_to_expire', 'expired', 'completed', 'invalid']
};
// 动态根据默认数组顺序生成索引映射,防止后续修改顺序时高亮乱蹦
export const stateIndexMap = {};
businessWorkflowConfig.default.forEach((key, index) => {
stateIndexMap[key] = index + 1;
});
function injectWorkflowSubMenus(menuNode) {
if (menuNode.children && menuNode.children.length > 0) {
for (const child of menuNode.children) {
injectWorkflowSubMenus(child);
}
}
// 检测组件路径是否为警务评议与问题处置的通用工单列表
if (menuNode.component && menuNode.component.includes('jwpy/flow/index')) {
let states = businessWorkflowConfig.default;
// 支持通过后端菜单的扩展字段配置该业务支持的状态,实现可插拔
if (menuNode.extendInfo) {
try {
const config = JSON.parse(menuNode.extendInfo);
if (config.workflowStates && config.workflowStates.length > 0) {
states = config.workflowStates;
}
} catch (e) { }
}
const sjlyNo = menuNode.path ? menuNode.path.split('/').pop() : menuNode.menuId.toString();
const children = [];
states.forEach((stateKey, index) => {
const stateObj = statePool[stateKey];
if (stateObj) {
children.push({
menuId: menuNode.menuId * 100 + (index + 1), // 生成全局唯一数字 ID
parentId: menuNode.menuId,
menuName: stateObj.title,
path: `${menuNode.path}/${stateObj.queryType}`,
component: menuNode.component,
menuType: MENU_TYPE_ENUM.MENU.value,
visibleFlag: true,
disabledFlag: false
});
}
});
menuNode.children = [...(menuNode.children || []), ...children];
}
}

26
smart-flow-web/src/views/jwpy/jwpy/flow/index.vue

@ -8,15 +8,6 @@
<div class="page-container"> <div class="page-container">
<div class="glass-card"> <div class="glass-card">
<div class="content-box"> <div class="content-box">
<!-- Tab 切换区域 -->
<a-tabs v-model:activeKey="activeTab" @change="onTabChange" class="custom-tabs">
<a-tab-pane key="mine" tab="我的" />
<a-tab-pane key="todo" tab="待办" />
<a-tab-pane key="expiring" tab="即将超期" />
<a-tab-pane key="expired" tab="已超期" />
<a-tab-pane key="all" tab="全部" />
</a-tabs>
<!-- 头部查询过滤区域 --> <!-- 头部查询过滤区域 -->
<a-form layout="inline" class="query-form"> <a-form layout="inline" class="query-form">
<a-form-item label="工单编号"> <a-form-item label="工单编号">
@ -130,12 +121,6 @@ const route = useRoute();
// ---------------------------- Tab ---------------------------- // ---------------------------- Tab ----------------------------
const activeTab = ref('all'); const activeTab = ref('all');
// Tab
function onTabChange(key) {
queryForm.pageNum = 1;
queryData();
}
// URL // URL
const currentBizTypeCode = computed(() => { const currentBizTypeCode = computed(() => {
// 1. query // 1. query
@ -235,7 +220,16 @@ function resetQuery() {
queryData(); queryData();
} }
onMounted(queryData); //
watch(
() => route.params.tabType,
(newTabType) => {
activeTab.value = newTabType ? newTabType : 'all';
queryForm.pageNum = 1;
queryData();
},
{ immediate: true }
);
// //
watch( watch(

Loading…
Cancel
Save