|
@@ -5740,9 +5740,9 @@ import { EVEN_VAR } from "./EventBus.js";
|
|
|
* SsSubTab 左侧菜单+iframe内容组件
|
|
* SsSubTab 左侧菜单+iframe内容组件
|
|
|
* v3.0 改造:去掉顶部图片,改为图标+悬浮模式,iframe懒加载 by xu 20251216
|
|
* v3.0 改造:去掉顶部图片,改为图标+悬浮模式,iframe懒加载 by xu 20251216
|
|
|
*/
|
|
*/
|
|
|
- const SsSubTab = {
|
|
|
|
|
- name: "SsSubTab",
|
|
|
|
|
- props: {
|
|
|
|
|
|
|
+ const SsSubTab = {
|
|
|
|
|
+ name: "SsSubTab",
|
|
|
|
|
+ props: {
|
|
|
menuList: {
|
|
menuList: {
|
|
|
type: Array,
|
|
type: Array,
|
|
|
required: true,
|
|
required: true,
|
|
@@ -5765,33 +5765,195 @@ import { EVEN_VAR } from "./EventBus.js";
|
|
|
default: 'collapse',
|
|
default: 'collapse',
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
- emits: ["menu-change", "footer-click"],
|
|
|
|
|
- setup(props, { emit }) {
|
|
|
|
|
- // v3.0 新增:默认图标映射,使用icon-biz图标 by xu 20251216
|
|
|
|
|
- const defaultIcons = [
|
|
|
|
|
- 'icon-obj-ry', // 人员
|
|
|
|
|
- 'icon-obj-dw', // 单位
|
|
|
|
|
- 'icon-obj-gw', // 岗位
|
|
|
|
|
- 'icon-biz-rc', // 人才
|
|
|
|
|
- 'icon-biz-xc', // 巡查
|
|
|
|
|
- 'icon-biz-cl', // 材料
|
|
|
|
|
- 'icon-biz-men', // 门
|
|
|
|
|
- 'icon-obj-xy' // 协议
|
|
|
|
|
- ];
|
|
|
|
|
- const getMenuIcon = (item, index) => {
|
|
|
|
|
- if (item.icon) return item.icon;
|
|
|
|
|
- // 返回完整的 class:menu-icon (字体族) + 具体图标类
|
|
|
|
|
- return 'menu-icon ' + defaultIcons[index % defaultIcons.length];
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- // v3.0 新增:菜单模式管理 by xu 20251216
|
|
|
|
|
- const menuMode = ref(props.initialMode);
|
|
|
|
|
- const isHovering = ref(false);
|
|
|
|
|
|
|
+ emits: ["menu-change", "footer-click"],
|
|
|
|
|
+ setup(props, { emit }) {
|
|
|
|
|
+ // v3.0 新增:默认图标映射,使用icon-biz图标 by xu 20251216
|
|
|
|
|
+ const defaultIcons = [
|
|
|
|
|
+ 'icon-obj-ry', // 人员
|
|
|
|
|
+ 'icon-obj-dw', // 单位
|
|
|
|
|
+ 'icon-obj-gw', // 岗位
|
|
|
|
|
+ 'icon-biz-rc', // 人才
|
|
|
|
|
+ 'icon-biz-xc', // 巡查
|
|
|
|
|
+ 'icon-biz-cl', // 材料
|
|
|
|
|
+ 'icon-biz-men', // 门
|
|
|
|
|
+ 'icon-obj-xy' // 协议
|
|
|
|
|
+ ];
|
|
|
|
|
+ //功能: SsSubTab 支持后端下发 iconName + pobj/cobj 两级菜单 by xu 20251222
|
|
|
|
|
+ const isTrue = (v) => v === true || v === "true" || v === 1 || v === "1"; //功能 by xu 20251222
|
|
|
|
|
+ const resolveIconClass = (iconNameOrClass, fallbackIndex) => { //功能 by xu 20251222
|
|
|
|
|
+ const fallback = `menu-icon ${defaultIcons[fallbackIndex % defaultIcons.length]}`;
|
|
|
|
|
+ if (!iconNameOrClass) {
|
|
|
|
|
+ return fallback;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 已经是完整 class(可能包含 menu-icon / menu-base-icon / 多个 class)
|
|
|
|
|
+ if (typeof iconNameOrClass === "string" && iconNameOrClass.indexOf(" ") > -1) {
|
|
|
|
|
+ return iconNameOrClass;
|
|
|
|
|
+ }
|
|
|
|
|
+ const iconName = iconNameOrClass;
|
|
|
|
|
+ if (iconName === "menu-icon" || iconName === "menu-base-icon") {
|
|
|
|
|
+ return fallback;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 业务图标库:icon-biz / icon-obj -> menu-icon
|
|
|
|
|
+ if (
|
|
|
|
|
+ typeof iconName === "string" &&
|
|
|
|
|
+ (iconName.indexOf("icon-obj-") === 0 || iconName.indexOf("icon-biz-") === 0)
|
|
|
|
|
+ ) {
|
|
|
|
|
+ return `menu-icon ${iconName}`;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 默认认为是 icon-base 图标 -> menu-base-icon
|
|
|
|
|
+ return `menu-base-icon ${iconName}`;
|
|
|
|
|
+ };
|
|
|
|
|
+ const getMenuIcon = (item, index) => { //功能 by xu 20251222
|
|
|
|
|
+ if (!item) {
|
|
|
|
|
+ return resolveIconClass(null, index);
|
|
|
|
|
+ }
|
|
|
|
|
+ //功能: 变动图标后端暂不正确,前端先写死为 icon-chg by xu 20251223
|
|
|
|
|
+ if (item.title === "变动" || item.name === "sys_bd") {
|
|
|
|
|
+ return resolveIconClass("icon-chg", index);
|
|
|
|
|
+ }
|
|
|
|
|
+ // 兼容旧字段 icon(优先使用)
|
|
|
|
|
+ if (item.icon) return resolveIconClass(item.icon, index);
|
|
|
|
|
+ // v3.0 使用后端下发 iconName
|
|
|
|
|
+ if (item.iconName) return resolveIconClass(item.iconName, index);
|
|
|
|
|
+ return resolveIconClass(null, index);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ //功能: SsSubTab 底部按钮支持 icon+文字(icon-base)by xu 20251224
|
|
|
|
|
+ const getFooterIcon = (button) => { //功能 by xu 20251224
|
|
|
|
|
+ if (!button) return "menu-base-icon icon-save";
|
|
|
|
|
+ const iconNameOrClass = button.iconClass || button.iconName || button.icon;
|
|
|
|
|
+ if (!iconNameOrClass) return "menu-base-icon icon-save";
|
|
|
|
|
+ if (typeof iconNameOrClass === "string" && iconNameOrClass.indexOf(" ") > -1) {
|
|
|
|
|
+ return iconNameOrClass;
|
|
|
|
|
+ }
|
|
|
|
|
+ return `menu-base-icon ${iconNameOrClass}`;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ //功能: pobj/cobj 扁平结构转换为 children 树结构,兼容原 children 结构 by xu 20251222
|
|
|
|
|
+ const normalizeMenuList = (rawList) => {
|
|
|
|
|
+ if (!Array.isArray(rawList) || rawList.length === 0) {
|
|
|
|
|
+ return [];
|
|
|
|
|
+ }
|
|
|
|
|
+ const hasTree = rawList.some((it) => Array.isArray(it?.children) && it.children.length > 0);
|
|
|
|
|
+ if (hasTree) {
|
|
|
|
|
+ return rawList.map((it) => ({
|
|
|
|
|
+ ...it,
|
|
|
|
|
+ __level: 1,
|
|
|
|
|
+ children: Array.isArray(it.children)
|
|
|
|
|
+ ? it.children.map((c) => ({ ...c, __level: 2 }))
|
|
|
|
|
+ : it.children,
|
|
|
|
|
+ }));
|
|
|
|
|
+ }
|
|
|
|
|
+ const hasMarker = rawList.some((it) => it && ("pobj" in it || "cobj" in it));
|
|
|
|
|
+ if (!hasMarker) {
|
|
|
|
|
+ return rawList.map((it) => ({ ...it, __level: 1 }));
|
|
|
|
|
+ }
|
|
|
|
|
+ const result = [];
|
|
|
|
|
+ let currentGroup = null;
|
|
|
|
|
+ for (const item of rawList) {
|
|
|
|
|
+ //功能: “变动”始终按一级处理(即使后端误传 pobj/cobj)by xu 20251223
|
|
|
|
|
+ const isChgItem = item && (item.title === "变动" || item.name === "sys_bd");
|
|
|
|
|
+ if (isChgItem) {
|
|
|
|
|
+ result.push({ ...item, __level: 1 });
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ const isParent = isTrue(item?.pobj);
|
|
|
|
|
+ const isChild = isTrue(item?.cobj);
|
|
|
|
|
+ if (isParent) {
|
|
|
|
|
+ currentGroup = {
|
|
|
|
|
+ ...item,
|
|
|
|
|
+ __level: 1,
|
|
|
|
|
+ children: [],
|
|
|
|
|
+ };
|
|
|
|
|
+ result.push(currentGroup);
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isChild && currentGroup) {
|
|
|
|
|
+ currentGroup.children.push({ ...item, __level: 2 });
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ //功能: 变动等无 pobj/cobj 的选项按一级展示(不挂到 children,也不打断当前分组)by xu 20251223
|
|
|
|
|
+ result.push({ ...item, __level: 1 });
|
|
|
|
|
+ }
|
|
|
|
|
+ return result;
|
|
|
|
|
+ };
|
|
|
|
|
+ const menuListComputed = computed(() => normalizeMenuList(props.menuList)); //功能 by xu 20251222
|
|
|
|
|
+ //功能: 分组展开状态(默认展开),避免 computed 生成对象导致 open 状态丢失 by xu 20251222
|
|
|
|
|
+ const groupOpenState = reactive({}); // { [key]: boolean }
|
|
|
|
|
+ const getGroupKey = (item) => (item?.name || item?.title || ""); //功能 by xu 20251222
|
|
|
|
|
+ const isGroupOpen = (item) => { //功能 by xu 20251222
|
|
|
|
|
+ const key = getGroupKey(item);
|
|
|
|
|
+ if (!key) return true;
|
|
|
|
|
+ return groupOpenState[key] !== false;
|
|
|
|
|
+ };
|
|
|
|
|
+ const toggleGroupOpen = (item) => { //功能 by xu 20251222
|
|
|
|
|
+ const key = getGroupKey(item);
|
|
|
|
|
+ if (!key) return;
|
|
|
|
|
+ groupOpenState[key] = !isGroupOpen(item);
|
|
|
|
|
+ };
|
|
|
|
|
+ const getLevelClass = (item, fallbackLevel) => { //功能 by xu 20251222
|
|
|
|
|
+ //功能: “变动”始终按一级样式处理 by xu 20251223
|
|
|
|
|
+ if (item && (item.title === "变动" || item.name === "sys_bd")) {
|
|
|
|
|
+ return "level-1";
|
|
|
|
|
+ }
|
|
|
|
|
+ const level = item?.__level || fallbackLevel || 1;
|
|
|
|
|
+ return level === 2 ? "level-2" : "level-1";
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // v3.0 新增:菜单模式管理 by xu 20251216
|
|
|
|
|
+ const menuMode = ref(props.initialMode);
|
|
|
|
|
+ const isHovering = ref(false);
|
|
|
|
|
|
|
|
const toggleMenuMode = () => {
|
|
const toggleMenuMode = () => {
|
|
|
menuMode.value = menuMode.value === 'collapse' ? 'fixed' : 'collapse';
|
|
menuMode.value = menuMode.value === 'collapse' ? 'fixed' : 'collapse';
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ //功能: 提供给旧UI弹窗顶部按钮调用的 API(替代点击 .menu-mode-toggle DOM)by xu 20251224
|
|
|
|
|
+ const registerSsSubTabApi = () => { //功能 by xu 20251224
|
|
|
|
|
+ try {
|
|
|
|
|
+ window.SS = window.SS || {};
|
|
|
|
|
+ window.SS.dom = window.SS.dom || {};
|
|
|
|
|
+ //功能: 兼容小写 ss 命名空间(部分页面只引用 window.ss)by xu 20251224
|
|
|
|
|
+ window.ss = window.ss || window.SS;
|
|
|
|
|
+ window.ss.dom = window.ss.dom || window.SS.dom;
|
|
|
|
|
+ const api = {
|
|
|
|
|
+ toggleMenuMode,
|
|
|
|
|
+ getMenuMode: () => menuMode.value,
|
|
|
|
|
+ };
|
|
|
|
|
+ window.SS.dom.ssSubTabApi = api;
|
|
|
|
|
+ window.ss.dom.ssSubTabApi = api;
|
|
|
|
|
+ //功能: 多层弹窗(如 objPlay -> objInfo) 场景,将 API 注册到 topWindow 供按钮跨层调用 by xu 20251224
|
|
|
|
|
+ try {
|
|
|
|
|
+ const wdDialogId = window.wd && wd.display && wd.display.getwdDialogId && wd.display.getwdDialogId();
|
|
|
|
|
+ if (wdDialogId && window.top) {
|
|
|
|
|
+ window.top.__ssSubTabApiMap = window.top.__ssSubTabApiMap || {};
|
|
|
|
|
+ window.top.__ssSubTabApiMap[wdDialogId] = api;
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) { }
|
|
|
|
|
+ try { console.log("[SsSubTabApi] registered", window.location && window.location.pathname); } catch (e) { }
|
|
|
|
|
+ } catch (e) { }
|
|
|
|
|
+ };
|
|
|
|
|
+ const unregisterSsSubTabApi = () => { //功能 by xu 20251224
|
|
|
|
|
+ try {
|
|
|
|
|
+ //功能: 从 topWindow 解绑(避免弹窗关闭后残留)by xu 20251224
|
|
|
|
|
+ try {
|
|
|
|
|
+ const wdDialogId = window.wd && wd.display && wd.display.getwdDialogId && wd.display.getwdDialogId();
|
|
|
|
|
+ if (wdDialogId && window.top && window.top.__ssSubTabApiMap && window.top.__ssSubTabApiMap[wdDialogId]) {
|
|
|
|
|
+ delete window.top.__ssSubTabApiMap[wdDialogId];
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) { }
|
|
|
|
|
+ if (window.SS?.dom?.ssSubTabApi?.toggleMenuMode === toggleMenuMode) {
|
|
|
|
|
+ delete window.SS.dom.ssSubTabApi;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (window.ss?.dom?.ssSubTabApi?.toggleMenuMode === toggleMenuMode) {
|
|
|
|
|
+ delete window.ss.dom.ssSubTabApi;
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) { }
|
|
|
|
|
+ };
|
|
|
|
|
+ //功能: 立即注册,避免 enable 早于 onMounted 导致“api not ready”by xu 20251224
|
|
|
|
|
+ registerSsSubTabApi(); //功能 by xu 20251224
|
|
|
|
|
+ onBeforeUnmount(unregisterSsSubTabApi); //功能 by xu 20251224
|
|
|
|
|
+
|
|
|
const onMouseEnter = () => {
|
|
const onMouseEnter = () => {
|
|
|
if (menuMode.value === 'collapse') {
|
|
if (menuMode.value === 'collapse') {
|
|
|
isHovering.value = true;
|
|
isHovering.value = true;
|
|
@@ -5808,17 +5970,17 @@ import { EVEN_VAR } from "./EventBus.js";
|
|
|
// v3.0 新增:iframe 懒加载,点击才加载 by xu 20251216
|
|
// v3.0 新增:iframe 懒加载,点击才加载 by xu 20251216
|
|
|
const loadedMenus = ref(new Set());
|
|
const loadedMenus = ref(new Set());
|
|
|
|
|
|
|
|
- const isMenuLoaded = (menuName) => {
|
|
|
|
|
- return loadedMenus.value.has(menuName);
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- // 根据标题找到对应的菜单项
|
|
|
|
|
- const findMenuByTitle = (title) => {
|
|
|
|
|
- for (const item of props.menuList) {
|
|
|
|
|
- if (item.children?.length > 0) {
|
|
|
|
|
- const child = item.children.find((c) => c.title === title);
|
|
|
|
|
- if (child) return child;
|
|
|
|
|
- } else if (item.title === title) {
|
|
|
|
|
|
|
+ const isMenuLoaded = (menuName) => {
|
|
|
|
|
+ return loadedMenus.value.has(menuName);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 根据标题找到对应的菜单项
|
|
|
|
|
+ const findMenuByTitle = (title) => {
|
|
|
|
|
+ for (const item of menuListComputed.value) { //功能 by xu 20251222
|
|
|
|
|
+ if (item.children?.length > 0) {
|
|
|
|
|
+ const child = item.children.find((c) => c.title === title);
|
|
|
|
|
+ if (child) return child;
|
|
|
|
|
+ } else if (item.title === title) {
|
|
|
return item;
|
|
return item;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -5831,11 +5993,10 @@ import { EVEN_VAR } from "./EventBus.js";
|
|
|
const menu = findMenuByTitle(props.activeMenu);
|
|
const menu = findMenuByTitle(props.activeMenu);
|
|
|
if (menu) return menu;
|
|
if (menu) return menu;
|
|
|
}
|
|
}
|
|
|
- const firstItem = props.menuList[0];
|
|
|
|
|
|
|
+ const firstItem = menuListComputed.value[0]; //功能 by xu 20251222
|
|
|
if (!firstItem) return null;
|
|
if (!firstItem) return null;
|
|
|
- return firstItem.children?.length > 0
|
|
|
|
|
- ? firstItem.children[0]
|
|
|
|
|
- : firstItem;
|
|
|
|
|
|
|
+ //功能: 默认选中第一个一级菜单(不默认跳到第一个二级)by xu 20251224
|
|
|
|
|
+ return firstItem;
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const currentMenu = ref(defaultActiveMenu.value);
|
|
const currentMenu = ref(defaultActiveMenu.value);
|
|
@@ -5875,22 +6036,27 @@ import { EVEN_VAR } from "./EventBus.js";
|
|
|
emit("footer-click", { button, index });
|
|
emit("footer-click", { button, index });
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- return {
|
|
|
|
|
- currentMenu,
|
|
|
|
|
- selectItem,
|
|
|
|
|
- handleFooterClick,
|
|
|
|
|
- menuMode,
|
|
|
|
|
- isHovering,
|
|
|
|
|
- isExpanded,
|
|
|
|
|
- toggleMenuMode,
|
|
|
|
|
- onMouseEnter,
|
|
|
|
|
- onMouseLeave,
|
|
|
|
|
- isMenuLoaded,
|
|
|
|
|
- getMenuIcon,
|
|
|
|
|
- };
|
|
|
|
|
- },
|
|
|
|
|
- template: `
|
|
|
|
|
- <div class="project-edit-container">
|
|
|
|
|
|
|
+ return {
|
|
|
|
|
+ menuListComputed, //功能 by xu 20251222
|
|
|
|
|
+ currentMenu,
|
|
|
|
|
+ selectItem,
|
|
|
|
|
+ handleFooterClick,
|
|
|
|
|
+ getFooterIcon, //功能: SsSubTab 底部按钮支持 icon+文字(icon-base)by xu 20251224
|
|
|
|
|
+ menuMode,
|
|
|
|
|
+ isHovering,
|
|
|
|
|
+ isExpanded,
|
|
|
|
|
+ toggleMenuMode,
|
|
|
|
|
+ onMouseEnter,
|
|
|
|
|
+ onMouseLeave,
|
|
|
|
|
+ isMenuLoaded,
|
|
|
|
|
+ getMenuIcon,
|
|
|
|
|
+ isGroupOpen, //功能 by xu 20251222
|
|
|
|
|
+ toggleGroupOpen, //功能 by xu 20251222
|
|
|
|
|
+ getLevelClass, //功能 by xu 20251222
|
|
|
|
|
+ };
|
|
|
|
|
+ },
|
|
|
|
|
+ template: `
|
|
|
|
|
+ <div class="project-edit-container">
|
|
|
<div class="left-side"
|
|
<div class="left-side"
|
|
|
v-if="leftDisplay"
|
|
v-if="leftDisplay"
|
|
|
:data-mode="menuMode"
|
|
:data-mode="menuMode"
|
|
@@ -5899,64 +6065,62 @@ import { EVEN_VAR } from "./EventBus.js";
|
|
|
@mouseleave="onMouseLeave">
|
|
@mouseleave="onMouseLeave">
|
|
|
|
|
|
|
|
<!-- 菜单内容 -->
|
|
<!-- 菜单内容 -->
|
|
|
- <div class="menu-content">
|
|
|
|
|
- <div class="scroll-view">
|
|
|
|
|
- <template v-for="(menuItem, i) in menuList" :key="i">
|
|
|
|
|
- <!-- 分组菜单 -->
|
|
|
|
|
- <div v-if="menuItem.children?.length > 0" class="group">
|
|
|
|
|
- <div class="menu-item" @click="menuItem.open = !menuItem.open">
|
|
|
|
|
- <ss-icon :class="getMenuIcon(menuItem, i)" />
|
|
|
|
|
- <span class="menu-label">{{ menuItem.title }}</span>
|
|
|
|
|
- <span class="arrow">
|
|
|
|
|
- <ss-icon :class="menuItem.open ? 'menu-icon icon-jiantou-shang' : 'menu-icon icon-jiantou-xia'" />
|
|
|
|
|
- </span>
|
|
|
|
|
- <div class="menu-tooltip">{{ menuItem.title }}</div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-show="menuItem.open" class="group-detail">
|
|
|
|
|
- <div v-for="(item, j) in menuItem.children"
|
|
|
|
|
- :key="j"
|
|
|
|
|
- class="menu-item"
|
|
|
|
|
- :class="{ active: item.name === currentMenu?.name }"
|
|
|
|
|
- @click="selectItem(item)">
|
|
|
|
|
- <ss-icon :class="getMenuIcon(item, j)" />
|
|
|
|
|
- <span class="menu-label">{{ item.title }}</span>
|
|
|
|
|
- <span class="menu-item-point" v-if="item.cgxList || item.objectList"></span>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ <div class="menu-content">
|
|
|
|
|
+ <div class="scroll-view">
|
|
|
|
|
+ <template v-for="(menuItem, i) in menuListComputed" :key="i">
|
|
|
|
|
+ <!-- 分组菜单 -->
|
|
|
|
|
+ <div v-if="menuItem.children?.length > 0" class="group">
|
|
|
|
|
+ <!-- 功能: 一级(pobj)可点击进入,箭头仅控制展开/收起;二级点击不影响一级选中状态 by xu 20251223 -->
|
|
|
|
|
+ <div class="menu-item"
|
|
|
|
|
+ :class="[getLevelClass(menuItem, 1), { active: menuItem.name === currentMenu?.name }]"
|
|
|
|
|
+ @click="selectItem(menuItem)">
|
|
|
|
|
+ <ss-icon :class="getMenuIcon(menuItem, i)" />
|
|
|
|
|
+ <span class="menu-label">{{ menuItem.title }}</span>
|
|
|
|
|
+ <!-- 功能: 一级菜单有子项时显示 dot(参考全局左侧菜单)by xu 20251224 -->
|
|
|
|
|
+ <div class="has-children-dot"></div>
|
|
|
|
|
+ <div class="menu-tooltip">{{ menuItem.title }}</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <!-- 功能: 二级菜单始终展示,不做收缩展开 by xu 20251223 -->
|
|
|
|
|
+ <div class="group-detail">
|
|
|
|
|
+ <div v-for="(item, j) in menuItem.children"
|
|
|
|
|
+ :key="j"
|
|
|
|
|
+ class="menu-item"
|
|
|
|
|
+ :class="[getLevelClass(item, 2), { active: item.name === currentMenu?.name }]"
|
|
|
|
|
+ @click.stop="selectItem(item)">
|
|
|
|
|
+ <ss-icon :class="getMenuIcon(item, j)" />
|
|
|
|
|
+ <span class="menu-label">{{ item.title }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
<!-- 普通菜单项 -->
|
|
<!-- 普通菜单项 -->
|
|
|
- <div v-else
|
|
|
|
|
- class="menu-item"
|
|
|
|
|
- :class="{ active: menuItem.name === currentMenu?.name }"
|
|
|
|
|
- @click="selectItem(menuItem)">
|
|
|
|
|
- <ss-icon :class="getMenuIcon(menuItem, i)" />
|
|
|
|
|
- <span class="menu-label">{{ menuItem.title }}</span>
|
|
|
|
|
- <span class="menu-item-point" v-if="menuItem.cgxList || menuItem.objectList"></span>
|
|
|
|
|
- <div class="menu-tooltip">{{ menuItem.title }}</div>
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ <div v-else
|
|
|
|
|
+ class="menu-item"
|
|
|
|
|
+ :class="[getLevelClass(menuItem, 1), { active: menuItem.name === currentMenu?.name }]"
|
|
|
|
|
+ @click="selectItem(menuItem)">
|
|
|
|
|
+ <ss-icon :class="getMenuIcon(menuItem, i)" />
|
|
|
|
|
+ <span class="menu-label">{{ menuItem.title }}</span>
|
|
|
|
|
+ <div class="menu-tooltip">{{ menuItem.title }}</div>
|
|
|
|
|
+ </div>
|
|
|
</template>
|
|
</template>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <!-- v3.0 模式切换按钮,只显示图标 by xu 20251216 -->
|
|
|
|
|
- <div class="menu-mode-toggle" @click="toggleMenuMode">
|
|
|
|
|
- <ss-icon class="menu-base-icon icon-qiehuan" />
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 底部按钮 -->
|
|
|
|
|
- <div v-if="footerButtons.length > 0"
|
|
|
|
|
- class="sub-tab-menu-footer"
|
|
|
|
|
- @click="footerButtons[0].onclick">
|
|
|
|
|
- <div>{{ footerButtons[0].text }}</div>
|
|
|
|
|
- <ss-icon v-if="footerButtons.length > 1" name="arrow-up" size="24px" />
|
|
|
|
|
- <div v-if="footerButtons.length > 1" class="sub-tab-menu-popup">
|
|
|
|
|
- <div v-for="(button, index) in footerButtons.slice(1)"
|
|
|
|
|
- :key="index"
|
|
|
|
|
- @click.stop="button.onclick">
|
|
|
|
|
- {{ button.text }}
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ <!-- 底部按钮 -->
|
|
|
|
|
+ <div v-if="footerButtons.length > 0"
|
|
|
|
|
+ class="sub-tab-menu-footer"
|
|
|
|
|
+ :class="{ 'has-text': !!footerButtons[0].text }"
|
|
|
|
|
+ @click="footerButtons[0].onclick">
|
|
|
|
|
+ <ss-icon :class="getFooterIcon(footerButtons[0])" />
|
|
|
|
|
+ <div class="footer-label" v-if="footerButtons[0].text">{{ footerButtons[0].text }}</div>
|
|
|
|
|
+ <ss-icon v-if="footerButtons.length > 1" class="footer-arrow" name="arrow-up" size="24px" />
|
|
|
|
|
+ <div v-if="footerButtons.length > 1" class="sub-tab-menu-popup">
|
|
|
|
|
+ <div v-for="(button, index) in footerButtons.slice(1)"
|
|
|
|
|
+ :key="index"
|
|
|
|
|
+ @click.stop="button.onclick">
|
|
|
|
|
+ {{ button.text }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|