feat(msgcenter,settings): 消息中心与设置中心路由化 + 背景层双卡改造
build / build (push) Successful in 13m13s

- 新增 /msg 消息中心路由页:左右双卡(左卡按分类/按应用双模式、右卡工具栏+列表),
  mock 数据,含时间格式/未读红点/已读三重置灰/审批直批按钮
- 新增 /settings 设置中心路由页:左导航卡+右内容卡,10 个 pane,?pane= 双向同步,
  管理员/普通用户角色差异(普通用户直达管理项渲染无权限黄条)
- 侧栏新增「设置」一级入口(前台硬编码补位,后台已配同 url 时自动去重)+ 分隔线 + 本地齿轮图标
- SysSetting.vue 卡片化:圆角 5→10px + 阴影,统一为 0 10px 20px rgba(0,0,0,.1)
- .base-mask 提升:rgba(255,255,255,.35)→.55,blur(2px)→10px
- Header 铃铛「查看全部」改跳 /msg;App.vue 菜单守卫放行 /msg、/settings(前台路由不在后端菜单表)
This commit is contained in:
chenxing
2026-09-30 09:28:50 +08:00
parent 08fa15db24
commit aa3dafa932
9 changed files with 1737 additions and 12 deletions
+1 -1
View File
@@ -694,7 +694,7 @@ function resetMsgPage() {
}
function showMsgList() {
isMsgShow.value = false;
isMsgListShow.value = true;
router.push("/msg");
refTablePage.value.reloadData();
}
+31 -5
View File
@@ -5,17 +5,18 @@
<SvgIcon name="menu-operate" color="#ececec" />
</li>
<template v-for="(item, index) in menuList" :key="index">
<!-- 硬编码补位的「设置」一级入口上方的分隔线(业务入口 vs 系统入口分层) -->
<li v-if="item.sep" class="menu-sep" aria-hidden="true"></li>
<li
v-wave="myWave"
@click="linkPage(item, index)"
:class="{ active: index == activeIndex, 'first-bottom': index == menuFirstBottomIndex }"
>
<a :title="item.name">
<FetchSvg
size="24"
:src="$conf.serviceHost + item.icon"
:color="index == activeIndex ? '#fff' : '#ececec'"
/>
<SvgIcon v-if="item.localIcon" :name="item.localIcon" size="24"
:color="index == activeIndex ? '#fff' : '#ececec'" />
<FetchSvg v-else size="24" :src="$conf.serviceHost + item.icon"
:color="index == activeIndex ? '#fff' : '#ececec'" />
<span>{{ item.name }}</span>
</a>
</li>
@@ -65,9 +66,26 @@ const route = useRoute(),
const store = useDefaultStore();
const { menuVisible } = storeToRefs(store);
/** 硬编码的「设置」一级入口:isNative 直走 router.push,图标用本地 svg sprite */
const SETTINGS_MENU_ITEM = {
id: -1,
name: "设置",
url: "/settings",
isNative: true,
isBottom: true,
orderNum: 9999,
localIcon: "menu-settings",
sep: true,
};
const menuList = computed<any[]>(() => {
let topArr = store.curUserMenuList.filter(x => x.isBottom !== true).sort((a, b) => a.orderNum - b.orderNum);
let bottomArr = store.curUserMenuList.filter(x => x.isBottom === true).sort((a, b) => a.orderNum - b.orderNum);
// 「设置」一级入口走前台硬编码补位(路径 A,不动后端菜单表);
// 若后台菜单表已配置同 url 的项则不重复追加,避免双入口
if (!store.curUserMenuList.some(x => x.url === "/settings")) {
bottomArr = [...bottomArr, SETTINGS_MENU_ITEM];
}
return [...topArr, ...bottomArr];
});
@@ -198,6 +216,14 @@ async function linkPage(item: any, index: number) {
bottom: 8px;
left: 5px;
}
li.menu-sep {
width: 36px;
height: 1px;
margin: 6px auto;
padding: 0;
background: rgba(255, 255, 255, 0.22);
pointer-events: none;
}
li:hover {
background-color: rgba(255, 255, 255, 0.15);
}