|
|
@@ -1,494 +0,0 @@
|
|
|
-# SsSubTab 组件改造方案
|
|
|
-
|
|
|
-## 文件位置
|
|
|
-`/js/vue/ss-components.js` 第 5715-5895 行
|
|
|
-
|
|
|
-## 改造目标
|
|
|
-
|
|
|
-### 1. UI 模式改造
|
|
|
-- **去掉**:顶部图片 `headerImage`
|
|
|
-- **新增两种模式**:
|
|
|
- - `collapse`(默认):只显示图标,鼠标悬停时浮动显示文字
|
|
|
- - `fixed`:只显示图标,不展开浮动
|
|
|
-
|
|
|
-### 2. 性能优化
|
|
|
-- **现状**:iframe 用 `v-show`,页面打开时全部加载
|
|
|
-- **改为**:懒加载,点击哪个才加载哪个
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 具体修改方案
|
|
|
-
|
|
|
-### 一、Props 修改
|
|
|
-
|
|
|
-```js
|
|
|
-// 删除
|
|
|
-headerImage: { type: String, default: "" },
|
|
|
-
|
|
|
-// 新增
|
|
|
-initialMode: {
|
|
|
- type: String,
|
|
|
- default: 'collapse', // 'collapse' | 'fixed'
|
|
|
- validator: (v) => ['collapse', 'fixed'].includes(v)
|
|
|
-},
|
|
|
-```
|
|
|
-
|
|
|
-### 二、Setup 新增逻辑
|
|
|
-
|
|
|
-```js
|
|
|
-setup(props, { emit }) {
|
|
|
- // ... 原有逻辑保留 ...
|
|
|
-
|
|
|
- // ===== 新增:菜单模式管理 =====
|
|
|
- const menuMode = ref(props.initialMode); // 'collapse' | 'fixed'
|
|
|
- const isHovering = ref(false); // 鼠标是否在菜单区域
|
|
|
-
|
|
|
- // 切换模式
|
|
|
- const toggleMenuMode = () => {
|
|
|
- menuMode.value = menuMode.value === 'collapse' ? 'fixed' : 'collapse';
|
|
|
- };
|
|
|
-
|
|
|
- // 鼠标进入/离开
|
|
|
- const onMouseEnter = () => {
|
|
|
- if (menuMode.value === 'collapse') {
|
|
|
- isHovering.value = true;
|
|
|
- }
|
|
|
- };
|
|
|
- const onMouseLeave = () => {
|
|
|
- isHovering.value = false;
|
|
|
- };
|
|
|
-
|
|
|
- // 是否显示文字(展开状态)
|
|
|
- const isExpanded = computed(() => {
|
|
|
- return menuMode.value === 'collapse' && isHovering.value;
|
|
|
- });
|
|
|
-
|
|
|
- // ===== 新增:iframe 懒加载 =====
|
|
|
- const loadedMenus = ref(new Set()); // 已加载过的菜单 name
|
|
|
-
|
|
|
- // 修改 selectItem
|
|
|
- const selectItem = (item) => {
|
|
|
- currentMenu.value = item;
|
|
|
- // 标记为已加载
|
|
|
- if (item.name) {
|
|
|
- loadedMenus.value.add(item.name);
|
|
|
- }
|
|
|
- emit("menu-change", item);
|
|
|
- };
|
|
|
-
|
|
|
- // 初始化:默认选中项需要加入已加载集合
|
|
|
- watch(currentMenu, (menu) => {
|
|
|
- if (menu?.name) {
|
|
|
- loadedMenus.value.add(menu.name);
|
|
|
- }
|
|
|
- }, { immediate: true });
|
|
|
-
|
|
|
- // 判断菜单是否已加载
|
|
|
- const isMenuLoaded = (menuName) => {
|
|
|
- return loadedMenus.value.has(menuName);
|
|
|
- };
|
|
|
-
|
|
|
- return {
|
|
|
- // 原有
|
|
|
- currentMenu,
|
|
|
- selectItem,
|
|
|
- handleFooterClick,
|
|
|
- // 新增
|
|
|
- menuMode,
|
|
|
- isHovering,
|
|
|
- isExpanded,
|
|
|
- toggleMenuMode,
|
|
|
- onMouseEnter,
|
|
|
- onMouseLeave,
|
|
|
- isMenuLoaded,
|
|
|
- };
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-### 三、Template 修改
|
|
|
-
|
|
|
-```html
|
|
|
-<div class="project-edit-container">
|
|
|
- <!-- 左侧菜单 -->
|
|
|
- <div class="left-side"
|
|
|
- v-if="leftDisplay"
|
|
|
- :data-mode="menuMode"
|
|
|
- :class="{ 'is-expanded': isExpanded }"
|
|
|
- @mouseenter="onMouseEnter"
|
|
|
- @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 :name="menuItem.icon || 'folder'" class="menu-icon" size="20px" />
|
|
|
- <span class="menu-label" v-show="isExpanded">{{ menuItem.title }}</span>
|
|
|
- <span class="arrow" v-show="isExpanded">
|
|
|
- <ss-icon :name="menuItem.open ? 'arrow-up' : 'arrow-down'" size="16px" />
|
|
|
- </span>
|
|
|
- <!-- 收起时的悬浮提示 -->
|
|
|
- <div class="menu-tooltip" v-show="!isExpanded">{{ menuItem.title }}</div>
|
|
|
- </div>
|
|
|
- <div v-show="menuItem.open && isExpanded" 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 :name="item.icon || 'file'" class="menu-icon" size="18px" />
|
|
|
- <span class="menu-label">{{ item.title }}</span>
|
|
|
- <span class="menu-item-point" v-if="item.cgxList || item.objectList"></span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 普通菜单项 -->
|
|
|
- <div v-else
|
|
|
- class="menu-item"
|
|
|
- :class="{ active: menuItem.name === currentMenu?.name }"
|
|
|
- @click="selectItem(menuItem)">
|
|
|
- <ss-icon :name="menuItem.icon || 'file'" class="menu-icon" size="20px" />
|
|
|
- <span class="menu-label" v-show="isExpanded">{{ menuItem.title }}</span>
|
|
|
- <span class="menu-item-point" v-if="menuItem.cgxList || menuItem.objectList"></span>
|
|
|
- <!-- 收起时的悬浮提示 -->
|
|
|
- <div class="menu-tooltip" v-show="!isExpanded">{{ menuItem.title }}</div>
|
|
|
- </div>
|
|
|
-
|
|
|
- </template>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 底部:模式切换按钮 -->
|
|
|
- <div class="menu-mode-toggle" @click="toggleMenuMode">
|
|
|
- <ss-icon :name="menuMode === 'collapse' ? 'pin' : 'pin-fill'" size="20px" />
|
|
|
- <span class="menu-label" v-show="isExpanded">
|
|
|
- {{ menuMode === 'collapse' ? '固定菜单' : '取消固定' }}
|
|
|
- </span>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 底部按钮(保留原有) -->
|
|
|
- <div v-if="footerButtons.length > 0" class="sub-tab-menu-footer" @click="footerButtons[0].onclick">
|
|
|
- <!-- ... 保持原有 ... -->
|
|
|
- </div>
|
|
|
-
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 右侧内容区域 - 懒加载 iframe -->
|
|
|
- <div class="content-area fit-height-content"
|
|
|
- style="overflow: hidden;"
|
|
|
- :style="!leftDisplay ? { width: '100%' } : {}">
|
|
|
-
|
|
|
- <template v-for="(menuItem, i) in menuList" :key="i">
|
|
|
- <!-- 只有加载过的才渲染 iframe -->
|
|
|
- <iframe
|
|
|
- v-if="isMenuLoaded(menuItem.name)"
|
|
|
- :src="menuItem.url"
|
|
|
- style="height: 100%;width: 100%;"
|
|
|
- frameborder="0"
|
|
|
- class="sub-tab-iframe"
|
|
|
- :id="i === 0 ? 'sub-tab-iframe' : ''"
|
|
|
- v-show="currentMenu?.name === menuItem.name"
|
|
|
- />
|
|
|
- </template>
|
|
|
-
|
|
|
- </div>
|
|
|
-</div>
|
|
|
-```
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## CSS 样式修改(base.css:4784-4968)
|
|
|
-
|
|
|
-### 现有样式分析
|
|
|
-```css
|
|
|
-/* 现有:固定 180px 宽度 */
|
|
|
-.project-edit-container .left-side {
|
|
|
- width: 180px !important; /* 需要改为动态 */
|
|
|
-}
|
|
|
-.project-edit-container>div.content-area {
|
|
|
- width: calc(100% - 180px); /* 需要改为动态 */
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-### 需要修改的样式
|
|
|
-
|
|
|
-#### 1. 左侧容器宽度(行 4798-4802)
|
|
|
-```css
|
|
|
-/* 原来 */
|
|
|
-.project-edit-container .left-side {
|
|
|
- width: 180px !important;
|
|
|
- border-right: 1px solid #e2e4ec;
|
|
|
- background-color: #edf1f5;
|
|
|
-}
|
|
|
-
|
|
|
-/* 改为 */
|
|
|
-.project-edit-container .left-side {
|
|
|
- width: 60px; /* 默认收起宽度 */
|
|
|
- border-right: 1px solid #e2e4ec;
|
|
|
- background-color: #edf1f5;
|
|
|
- transition: width 0.2s ease;
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- overflow: hidden;
|
|
|
-}
|
|
|
-
|
|
|
-/* 展开状态 */
|
|
|
-.project-edit-container .left-side.is-expanded {
|
|
|
- width: 200px;
|
|
|
-}
|
|
|
-
|
|
|
-/* 固定模式:始终收起,不响应悬浮 */
|
|
|
-.project-edit-container .left-side[data-mode="fixed"] {
|
|
|
- width: 60px !important;
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-#### 2. 右侧内容区宽度(行 4964-4967)
|
|
|
-```css
|
|
|
-/* 原来 */
|
|
|
-.project-edit-container>div.content-area {
|
|
|
- width: calc(100% - 180px);
|
|
|
- overflow-y: auto;
|
|
|
-}
|
|
|
-
|
|
|
-/* 改为 */
|
|
|
-.project-edit-container>div.content-area {
|
|
|
- flex: 1; /* 自动填充剩余空间 */
|
|
|
- overflow-y: auto;
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-#### 3. 菜单项样式(行 4824-4832)
|
|
|
-```css
|
|
|
-/* 原来 */
|
|
|
-.project-edit-container .menu-item,
|
|
|
-.project-edit-container .group .menu-item {
|
|
|
- padding: 20px 12px 20px 30px;
|
|
|
- cursor: pointer;
|
|
|
- position: relative;
|
|
|
- color: #333333;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
-}
|
|
|
-
|
|
|
-/* 改为 */
|
|
|
-.project-edit-container .menu-item,
|
|
|
-.project-edit-container .group .menu-item {
|
|
|
- padding: 15px;
|
|
|
- cursor: pointer;
|
|
|
- position: relative;
|
|
|
- color: #333333;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center; /* 收起时图标居中 */
|
|
|
- gap: 10px;
|
|
|
-}
|
|
|
-
|
|
|
-/* 展开时左对齐 */
|
|
|
-.project-edit-container .left-side.is-expanded .menu-item {
|
|
|
- justify-content: flex-start;
|
|
|
- padding: 15px 20px;
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-#### 4. 删除头部图片相关样式(行 4808-4815)
|
|
|
-```css
|
|
|
-/* 删除或注释掉 */
|
|
|
-/* .project-edit-container .menu-header {
|
|
|
- height: 120px;
|
|
|
- border-bottom: 1px solid #d8dae3;
|
|
|
-} */
|
|
|
-
|
|
|
-/* 修改 menu-content 高度 */
|
|
|
-.project-edit-container .menu-content {
|
|
|
- height: calc(100% - 50px); /* 原来是 calc(100% - 60px),去掉图片后调整 */
|
|
|
- flex: 1;
|
|
|
- overflow: hidden;
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-#### 5. 箭头位置(行 4834-4837)
|
|
|
-```css
|
|
|
-/* 原来:固定位置 */
|
|
|
-.project-edit-container .menu-item .arrow {
|
|
|
- position: absolute;
|
|
|
- left: 180px;
|
|
|
-}
|
|
|
-
|
|
|
-/* 改为:相对定位,放在右侧 */
|
|
|
-.project-edit-container .menu-item .arrow {
|
|
|
- margin-left: auto;
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-### 需要新增的样式
|
|
|
-
|
|
|
-```css
|
|
|
-/* ===== 新增:图标样式 ===== */
|
|
|
-.project-edit-container .menu-icon {
|
|
|
- flex-shrink: 0;
|
|
|
- width: 24px;
|
|
|
- height: 24px;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
-}
|
|
|
-
|
|
|
-/* ===== 新增:文字标签 ===== */
|
|
|
-.project-edit-container .menu-label {
|
|
|
- white-space: nowrap;
|
|
|
- overflow: hidden;
|
|
|
- text-overflow: ellipsis;
|
|
|
-}
|
|
|
-
|
|
|
-/* 收起时隐藏文字 */
|
|
|
-.project-edit-container .left-side:not(.is-expanded) .menu-label {
|
|
|
- display: none;
|
|
|
-}
|
|
|
-
|
|
|
-/* ===== 新增:悬浮提示(收起时显示) ===== */
|
|
|
-.project-edit-container .menu-tooltip {
|
|
|
- position: absolute;
|
|
|
- left: calc(100% + 10px);
|
|
|
- top: 50%;
|
|
|
- transform: translateY(-50%);
|
|
|
- background: #393d51;
|
|
|
- color: #fff;
|
|
|
- padding: 8px 16px;
|
|
|
- border-radius: 4px;
|
|
|
- white-space: nowrap;
|
|
|
- z-index: 1000;
|
|
|
- opacity: 0;
|
|
|
- pointer-events: none;
|
|
|
- transition: opacity 0.15s ease;
|
|
|
- font-size: 14px;
|
|
|
-}
|
|
|
-
|
|
|
-/* 小三角 */
|
|
|
-.project-edit-container .menu-tooltip::before {
|
|
|
- content: "";
|
|
|
- position: absolute;
|
|
|
- left: -6px;
|
|
|
- top: 50%;
|
|
|
- transform: translateY(-50%);
|
|
|
- border: 6px solid transparent;
|
|
|
- border-right-color: #393d51;
|
|
|
- border-left: none;
|
|
|
-}
|
|
|
-
|
|
|
-/* 悬浮显示 tooltip */
|
|
|
-.project-edit-container .left-side:not(.is-expanded) .menu-item:hover .menu-tooltip {
|
|
|
- opacity: 1;
|
|
|
-}
|
|
|
-
|
|
|
-/* 展开时隐藏 tooltip */
|
|
|
-.project-edit-container .left-side.is-expanded .menu-tooltip {
|
|
|
- display: none;
|
|
|
-}
|
|
|
-
|
|
|
-/* ===== 新增:模式切换按钮 ===== */
|
|
|
-.project-edit-container .menu-mode-toggle {
|
|
|
- height: 50px;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- padding: 15px;
|
|
|
- cursor: pointer;
|
|
|
- border-top: 1px solid #d8dae3;
|
|
|
- color: #666;
|
|
|
- gap: 10px;
|
|
|
- flex-shrink: 0;
|
|
|
-}
|
|
|
-
|
|
|
-.project-edit-container .menu-mode-toggle:hover {
|
|
|
- background: #e0e4ea;
|
|
|
- color: #333;
|
|
|
-}
|
|
|
-
|
|
|
-/* 展开时左对齐 */
|
|
|
-.project-edit-container .left-side.is-expanded .menu-mode-toggle {
|
|
|
- justify-content: flex-start;
|
|
|
- padding: 15px 20px;
|
|
|
-}
|
|
|
-
|
|
|
-/* ===== 新增:子菜单样式调整 ===== */
|
|
|
-.project-edit-container .group-detail {
|
|
|
- background: rgba(0, 0, 0, 0.03);
|
|
|
-}
|
|
|
-
|
|
|
-.project-edit-container .group-detail .menu-item {
|
|
|
- padding-left: 25px;
|
|
|
-}
|
|
|
-
|
|
|
-.project-edit-container .left-side.is-expanded .group-detail .menu-item {
|
|
|
- padding-left: 50px;
|
|
|
-}
|
|
|
-
|
|
|
-/* 收起时隐藏子菜单 */
|
|
|
-.project-edit-container .left-side:not(.is-expanded) .group-detail {
|
|
|
- display: none;
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-### CSS 修改汇总表
|
|
|
-
|
|
|
-| 行号 | 原值 | 新值 | 说明 |
|
|
|
-|-----|------|------|-----|
|
|
|
-| 4799 | `width: 180px !important` | `width: 60px` | 默认收起宽度 |
|
|
|
-| 4808-4811 | `.menu-header {...}` | 删除或注释 | 去掉头部图片 |
|
|
|
-| 4814 | `height: calc(100% - 60px)` | `flex: 1` | 菜单内容自适应 |
|
|
|
-| 4826 | `padding: 20px 12px 20px 30px` | `padding: 15px` | 菜单项内边距 |
|
|
|
-| 4836 | `left: 180px` | `margin-left: auto` | 箭头位置 |
|
|
|
-| 4965 | `width: calc(100% - 180px)` | `flex: 1` | 右侧内容区自适应 |
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 数据结构要求
|
|
|
-
|
|
|
-菜单项需要增加 `icon` 字段:
|
|
|
-
|
|
|
-```js
|
|
|
-menuList: [
|
|
|
- {
|
|
|
- name: 'basic',
|
|
|
- title: '基本信息',
|
|
|
- icon: 'info', // 新增:图标名称
|
|
|
- url: '/page/xxx.jsp'
|
|
|
- },
|
|
|
- {
|
|
|
- title: '项目设置',
|
|
|
- icon: 'setting', // 新增
|
|
|
- children: [
|
|
|
- { name: 'config1', title: '配置1', icon: 'config', url: '...' },
|
|
|
- { name: 'config2', title: '配置2', icon: 'config', url: '...' }
|
|
|
- ]
|
|
|
- }
|
|
|
-]
|
|
|
-```
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 改造要点总结
|
|
|
-
|
|
|
-| 项目 | 原实现 | 新实现 |
|
|
|
-|-----|-------|-------|
|
|
|
-| 头部图片 | 有 headerImage | 删除 |
|
|
|
-| 菜单宽度 | 固定宽度 | 60px / 200px 切换 |
|
|
|
-| 文字显示 | 始终显示 | 收起时隐藏,悬浮/展开时显示 |
|
|
|
-| 模式切换 | 无 | collapse(悬浮展开) / fixed(始终收起) |
|
|
|
-| iframe 加载 | v-show 全部加载 | v-if 懒加载(点击才加载) |
|
|
|
-| 图标 | 无 | 每个菜单项需要 icon 字段 |
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 兼容性注意
|
|
|
-
|
|
|
-1. 需要确保 `menuList` 数据有 `icon` 字段,否则使用默认图标
|
|
|
-2. 懒加载后,切换回已加载的菜单不会重新加载(保持 iframe 状态)
|
|
|
-3. 底部按钮功能保持不变
|