Files
ccdi/docs/plans/2026-03-04-project-detail-navigation-menu-design.md

335 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 项目详情页面导航菜单改造设计文档
## 概述
将项目详情页面detail.vue右侧的按钮组改为水平导航菜单使用 Element UI Menu 组件实现简洁链接风格。
## 当前问题
项目详情页面右侧的操作按钮(上传数据、参数配置、初核结果)占用空间较大,视觉层级不够清晰,交互方式不够统一。
## 解决方案
### 核心设计
- 使用 Element UI 的 `el-menu` 组件(水平模式)
- 菜单放在标题右侧,右对齐
- "上传数据"和"参数配置"作为普通菜单项
- "初核结果"保留下拉菜单结构,包含三个子项:结果总览、专项排查、流水明细查询
- 采用简洁链接风格:透明背景 + 底部下划线激活效果
### 视觉风格
- 默认状态:灰色文字(#606266),透明背景
- Hover 状态:浅灰背景(#f5f7fa),深色文字(#303133
- 激活状态:蓝色文字(#1890ff+ 底部 2px 蓝色下划线
- 下拉菜单:白色背景,激活项浅蓝背景(#e6f7ff
## 技术设计
### 1. 组件结构
#### detail.vue 模板改造
```vue
<div class="header-right">
<el-menu
:default-active="activeTab"
mode="horizontal"
@select="handleMenuSelect"
class="nav-menu"
>
<el-menu-item index="upload">上传数据</el-menu-item>
<el-menu-item index="config">参数配置</el-menu-item>
<el-submenu index="result">
<template slot="title">初核结果</template>
<el-menu-item index="overview">结果总览</el-menu-item>
<el-menu-item index="special">专项排查</el-menu-item>
<el-menu-item index="detail">流水明细查询</el-menu-item>
</el-submenu>
</el-menu>
</div>
<!-- 动态组件渲染区域 -->
<component
:is="currentComponent"
:project-id="projectId"
:project-info="projectInfo"
@menu-change="handleMenuChange"
@data-uploaded="handleDataUploaded"
@name-selected="handleNameSelected"
@generate-report="handleGenerateReport"
@fetch-bank-info="handleFetchBankInfo"
/>
```
### 2. 数据结构
```javascript
data() {
return {
activeTab: 'upload', // 当前激活的菜单项索引
currentComponent: 'UploadData', // 当前显示的组件名称
// ... 其他现有数据
}
}
```
### 3. 交互逻辑
```javascript
methods: {
/** 菜单选择事件 */
handleMenuSelect(index) {
this.activeTab = index;
// 组件映射
const componentMap = {
'upload': 'UploadData',
'config': 'ParamConfig',
'overview': 'PreliminaryCheck',
'special': 'SpecialCheck',
'detail': 'DetailQuery'
};
this.currentComponent = componentMap[index] || 'UploadData';
},
// ... 其他现有方法
}
```
### 4. 组件导入
```javascript
import UploadData from "./components/detail/UploadData";
import ParamConfig from "./components/detail/ParamConfig";
import PreliminaryCheck from "./components/detail/PreliminaryCheck";
import SpecialCheck from "./components/detail/SpecialCheck";
import DetailQuery from "./components/detail/DetailQuery";
export default {
name: "ProjectDetail",
components: {
UploadData,
ParamConfig,
PreliminaryCheck,
SpecialCheck,
DetailQuery,
},
// ...
}
```
## 样式设计
### 1. 导航菜单样式
```scss
.header-right {
.nav-menu {
// 移除默认背景色和边框
background-color: transparent;
border-bottom: none;
// 菜单项基础样式
.el-menu-item,
.el-submenu__title {
font-size: 14px;
color: #606266;
padding: 0 16px;
height: 40px;
line-height: 40px;
border-bottom: 2px solid transparent;
&:hover {
background-color: #f5f7fa;
color: #303133;
}
}
// 激活状态:底部下划线 + 蓝色文字
.el-menu-item.is-active {
color: #1890ff;
border-bottom: 2px solid #1890ff;
background-color: transparent;
}
// 下拉菜单激活状态
.el-submenu.is-active > .el-submenu__title {
color: #1890ff;
border-bottom: 2px solid #1890ff;
}
// 下拉菜单图标
.el-submenu__icon-arrow {
margin-left: 4px;
}
}
}
```
### 2. 下拉菜单弹窗样式
```scss
::v-deep .el-menu--popup {
min-width: 140px;
.el-menu-item {
font-size: 14px;
&:hover {
background-color: #f5f7fa;
}
&.is-active {
color: #1890ff;
background-color: #e6f7ff;
}
}
}
```
### 3. 响应式适配
```scss
@media (max-width: 768px) {
.detail-header {
flex-direction: column;
align-items: flex-start;
.header-right {
width: 100%;
margin-top: 12px;
.nav-menu {
width: 100%;
display: flex;
justify-content: flex-start;
.el-menu-item,
.el-submenu {
flex: 1;
text-align: center;
padding: 0 8px;
font-size: 13px;
}
}
}
}
}
```
## 组件规范
### Props 接口
所有子组件应接收相同的 props
```javascript
props: {
projectId: {
type: [String, Number],
default: null,
},
projectInfo: {
type: Object,
default: () => ({
projectName: "",
updateTime: "",
projectStatus: "0",
}),
},
},
```
### Events 接口
```javascript
this.$emit('data-uploaded', { type: 'xxx' });
this.$emit('generate-report');
this.$emit('fetch-bank-info');
this.$emit('menu-change', { key, route });
this.$emit('name-selected', nameList);
```
## 实施步骤
### 第一步:修改 detail.vue 文件
1. 替换 header-right 中的按钮为 el-menu 组件
2. 添加 activeTab 和 currentComponent 数据字段
3. 实现 handleMenuSelect 方法
4. 添加动态组件渲染区域
5. 导入所有子组件
### 第二步:添加样式
1. 添加导航菜单的自定义样式
2. 添加下拉菜单样式
3. 添加响应式样式
### 第三步:创建占位组件
为未实现的功能创建占位组件:
- ParamConfig.vue
- PreliminaryCheck.vue
- SpecialCheck.vue
- DetailQuery.vue
### 第四步:测试验证
- 功能测试:菜单切换、下拉菜单交互
- 视觉测试:样式符合设计要求
- 响应式测试:移动端布局正常
## 技术栈
- Element UI Menu 组件(`el-menu`, `el-menu-item`, `el-submenu`
- Vue 动态组件(`<component :is="...">`
- Scoped CSS 样式覆盖
- Vue 2.6.12
- Element UI 2.15.14
## 预期效果
### 视觉效果
- 菜单项横向排列在标题右侧,右对齐
- 简洁链接风格,无背景色和边框
- 激活项显示蓝色文字和底部下划线
- 下拉菜单样式统一
### 交互效果
- 点击菜单项切换组件URL 不变
- 下拉菜单点击外部区域可关闭
- 组件切换流畅,数据正确传递
- 响应式布局在移动端自适应
## 代码改动量估算
- detail.vue 文件改动:约 80-100 行(模板 + 脚本 + 样式)
- 占位组件创建4 个文件,每个约 20 行
- 总代码量:约 150-180 行
## 风险与注意事项
1. **组件文件不存在**ParamConfig、PreliminaryCheck 等组件需要创建占位组件
2. **样式覆盖**Element UI 默认样式覆盖需要使用 `::v-deep``/deep/`
3. **事件传递**:确保所有子组件的事件正确向上传递
4. **路由监听**:移除原有路由相关的逻辑,改为组件状态管理
## 后续优化建议
1. 添加菜单切换动画效果
2. 为占位组件实现完整功能
3. 添加面包屑导航支持
4. 支持菜单项权限控制
5. 添加快捷键支持Ctrl+Tab 切换)
## 测试清单
- [ ] 点击"上传数据"菜单,显示 UploadData 组件
- [ ] 点击"参数配置"菜单,显示占位组件或 ParamConfig 组件
- [ ] 点击"初核结果"菜单,展开下拉菜单
- [ ] 点击下拉菜单子项,切换到对应组件
- [ ] 激活菜单项显示底部下划线
- [ ] Hover 菜单项显示浅灰背景
- [ ] 下拉菜单点击外部区域关闭
- [ ] 组件切换时 projectId 和 projectInfo 正确传递
- [ ] 移动端菜单响应式布局正常
- [ ] 现有功能不受影响(返回按钮、项目信息显示等)