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

961 lines
21 KiB
Markdown
Raw Permalink 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.
# 项目详情页面导航菜单改造实施计划
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** 将项目详情页面右侧的按钮组改为水平导航菜单,使用 Element UI Menu 组件实现简洁链接风格,支持菜单切换组件内容。
**Architecture:** 使用 Element UI 的 `el-menu` 组件(水平模式)替换现有的按钮组,通过 Vue 动态组件(`<component :is="...">`)实现内容切换。菜单项包括"上传数据"、"参数配置"和"初核结果"下拉菜单(含三个子项)。采用简洁链接风格,激活状态显示底部下划线。
**Tech Stack:** Vue 2.6.12, Element UI 2.15.14, Scoped CSS
---
## 前置检查
**验证当前项目状态:**
```bash
cd D:/ccdi/ccdi
git status
```
预期:工作目录干净,或只有 CLAUDE.md 修改
**验证文件存在:**
```bash
ls ruoyi-ui/src/views/ccdiProject/detail.vue
ls ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue
```
预期:两个文件都存在
---
## Task 1: 创建占位组件 ParamConfig
**Files:**
- Create: `ruoyi-ui/src/views/ccdiProject/components/detail/ParamConfig.vue`
**Step 1: 创建 ParamConfig 占位组件**
创建文件 `ruoyi-ui/src/views/ccdiProject/components/detail/ParamConfig.vue`:
```vue
<template>
<div class="param-config-container">
<div class="placeholder-content">
<i class="el-icon-setting"></i>
<p>参数配置功能开发中...</p>
</div>
</div>
</template>
<script>
export default {
name: "ParamConfig",
props: {
projectId: {
type: [String, Number],
default: null,
},
projectInfo: {
type: Object,
default: () => ({
projectName: "",
updateTime: "",
projectStatus: "0",
}),
},
},
};
</script>
<style lang="scss" scoped>
.param-config-container {
padding: 40px 20px;
background: #fff;
min-height: 400px;
}
.placeholder-content {
text-align: center;
color: #909399;
i {
font-size: 48px;
margin-bottom: 16px;
}
p {
font-size: 14px;
margin: 0;
}
}
</style>
```
**Step 2: 提交 ParamConfig 组件**
```bash
git add ruoyi-ui/src/views/ccdiProject/components/detail/ParamConfig.vue
git commit -m "feat(ccdiProject): 添加参数配置占位组件"
```
---
## Task 2: 创建占位组件 PreliminaryCheck
**Files:**
- Create: `ruoyi-ui/src/views/ccdiProject/components/detail/PreliminaryCheck.vue`
**Step 1: 创建 PreliminaryCheck 占位组件**
创建文件 `ruoyi-ui/src/views/ccdiProject/components/detail/PreliminaryCheck.vue`:
```vue
<template>
<div class="preliminary-check-container">
<div class="placeholder-content">
<i class="el-icon-data-analysis"></i>
<p>结果总览功能开发中...</p>
</div>
</div>
</template>
<script>
export default {
name: "PreliminaryCheck",
props: {
projectId: {
type: [String, Number],
default: null,
},
projectInfo: {
type: Object,
default: () => ({
projectName: "",
updateTime: "",
projectStatus: "0",
}),
},
},
};
</script>
<style lang="scss" scoped>
.preliminary-check-container {
padding: 40px 20px;
background: #fff;
min-height: 400px;
}
.placeholder-content {
text-align: center;
color: #909399;
i {
font-size: 48px;
margin-bottom: 16px;
}
p {
font-size: 14px;
margin: 0;
}
}
</style>
```
**Step 2: 提交 PreliminaryCheck 组件**
```bash
git add ruoyi-ui/src/views/ccdiProject/components/detail/PreliminaryCheck.vue
git commit -m "feat(ccdiProject): 添加结果总览占位组件"
```
---
## Task 3: 创建占位组件 SpecialCheck
**Files:**
- Create: `ruoyi-ui/src/views/ccdiProject/components/detail/SpecialCheck.vue`
**Step 1: 创建 SpecialCheck 占位组件**
创建文件 `ruoyi-ui/src/views/ccdiProject/components/detail/SpecialCheck.vue`:
```vue
<template>
<div class="special-check-container">
<div class="placeholder-content">
<i class="el-icon-search"></i>
<p>专项排查功能开发中...</p>
</div>
</div>
</template>
<script>
export default {
name: "SpecialCheck",
props: {
projectId: {
type: [String, Number],
default: null,
},
projectInfo: {
type: Object,
default: () => ({
projectName: "",
updateTime: "",
projectStatus: "0",
}),
},
},
};
</script>
<style lang="scss" scoped>
.special-check-container {
padding: 40px 20px;
background: #fff;
min-height: 400px;
}
.placeholder-content {
text-align: center;
color: #909399;
i {
font-size: 48px;
margin-bottom: 16px;
}
p {
font-size: 14px;
margin: 0;
}
}
</style>
```
**Step 2: 提交 SpecialCheck 组件**
```bash
git add ruoyi-ui/src/views/ccdiProject/components/detail/SpecialCheck.vue
git commit -m "feat(ccdiProject): 添加专项排查占位组件"
```
---
## Task 4: 创建占位组件 DetailQuery
**Files:**
- Create: `ruoyi-ui/src/views/ccdiProject/components/detail/DetailQuery.vue`
**Step 1: 创建 DetailQuery 占位组件**
创建文件 `ruoyi-ui/src/views/ccdiProject/components/detail/DetailQuery.vue`:
```vue
<template>
<div class="detail-query-container">
<div class="placeholder-content">
<i class="el-icon-document"></i>
<p>流水明细查询功能开发中...</p>
</div>
</div>
</template>
<script>
export default {
name: "DetailQuery",
props: {
projectId: {
type: [String, Number],
default: null,
},
projectInfo: {
type: Object,
default: () => ({
projectName: "",
updateTime: "",
projectStatus: "0",
}),
},
},
};
</script>
<style lang="scss" scoped>
.detail-query-container {
padding: 40px 20px;
background: #fff;
min-height: 400px;
}
.placeholder-content {
text-align: center;
color: #909399;
i {
font-size: 48px;
margin-bottom: 16px;
}
p {
font-size: 14px;
margin: 0;
}
}
</style>
```
**Step 2: 提交 DetailQuery 组件**
```bash
git add ruoyi-ui/src/views/ccdiProject/components/detail/DetailQuery.vue
git commit -m "feat(ccdiProject): 添加流水明细查询占位组件"
```
---
## Task 5: 修改 detail.vue - 添加数据字段和导入组件
**Files:**
- Modify: `ruoyi-ui/src/views/ccdiProject/detail.vue`
**Step 1: 添加组件导入**
`detail.vue``<script>` 部分,找到 import 语句(第 72 行附近),替换为:
```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";
```
**Step 2: 注册组件**
`components` 对象中(第 81-88 行),替换为:
```javascript
components: {
UploadData,
ParamConfig,
PreliminaryCheck,
SpecialCheck,
DetailQuery,
},
```
**Step 3: 添加数据字段**
`data()` 函数中(第 89-110 行),在 `activeTab: "data"` 之后添加:
```javascript
data() {
return {
// 当前激活的菜单项索引
activeTab: "upload",
// 当前显示的组件名称
currentComponent: "UploadData",
// 项目ID
projectId: this.$route.params.projectId,
// ... 其他现有数据保持不变
projectInfo: {
projectId: this.$route.params.projectId,
projectName: "",
projectDesc: "",
createTime: "",
updateTime: "",
startDate: "",
endDate: "",
targetCount: 0,
warningCount: 0,
warningThreshold: 60,
projectStatus: "0",
},
};
},
```
**Step 4: 验证文件语法正确**
```bash
cd ruoyi-ui
npm run lint -- --fix src/views/ccdiProject/detail.vue
```
预期:无语法错误
**Step 5: 提交组件导入修改**
```bash
git add ruoyi-ui/src/views/ccdiProject/detail.vue
git commit -m "feat(ccdiProject): 导入子组件并添加菜单状态数据"
```
---
## Task 6: 修改 detail.vue - 替换模板中的按钮为菜单
**Files:**
- Modify: `ruoyi-ui/src/views/ccdiProject/detail.vue`
**Step 1: 替换 header-right 中的按钮组**
找到 `<div class="header-right">` 部分(第 27-55 行),替换为:
```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>
```
**Step 2: 替换 UploadData 为动态组件**
找到 `<UploadData>` 组件(第 59-67 行),替换为:
```vue
<!-- 动态组件渲染区域 -->
<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"
/>
```
**Step 3: 验证模板语法**
```bash
cd ruoyi-ui
npm run lint -- --fix src/views/ccdiProject/detail.vue
```
预期:无语法错误
**Step 4: 提交模板修改**
```bash
git add ruoyi-ui/src/views/ccdiProject/detail.vue
git commit -m "feat(ccdiProject): 替换按钮组为导航菜单并使用动态组件"
```
---
## Task 7: 修改 detail.vue - 添加菜单选择处理方法
**Files:**
- Modify: `ruoyi-ui/src/views/ccdiProject/detail.vue`
**Step 1: 添加菜单选择处理方法**
`methods` 对象中(第 124 行),在 `handleBack()` 方法之后添加新方法:
```javascript
/** 菜单选择事件 */
handleMenuSelect(index) {
console.log("菜单选择:", index);
this.activeTab = index;
// 组件映射
const componentMap = {
upload: "UploadData",
config: "ParamConfig",
overview: "PreliminaryCheck",
special: "SpecialCheck",
detail: "DetailQuery",
};
this.currentComponent = componentMap[index] || "UploadData";
},
```
**Step 2: 删除废弃的方法**
删除以下不再使用的方法(第 226-251 行):
- `handleUploadData()`
- `handleParamConfig()`
- `handleCheckResultCommand()`
**Step 3: 更新 handleMenuChange 方法**
修改 `handleMenuChange` 方法(第 185-205 行),简化为:
```javascript
/** UploadData 组件:菜单切换 */
handleMenuChange({ key, route }) {
console.log("切换到菜单:", key, route);
// 直接触发菜单选择
this.handleMenuSelect(route);
},
```
**Step 4: 验证方法逻辑**
```bash
cd ruoyi-ui
npm run lint -- --fix src/views/ccdiProject/detail.vue
```
预期:无语法错误,未使用的方法已删除
**Step 5: 提交方法修改**
```bash
git add ruoyi-ui/src/views/ccdiProject/detail.vue
git commit -m "feat(ccdiProject): 添加菜单选择处理方法并清理废弃代码"
```
---
## Task 8: 修改 detail.vue - 添加导航菜单样式
**Files:**
- Modify: `ruoyi-ui/src/views/ccdiProject/detail.vue`
**Step 1: 添加导航菜单样式**
`<style lang="scss" scoped>` 部分(第 306 行之后),在 `.header-right` 样式块内部添加:
```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;
}
}
}
```
**Step 2: 添加下拉菜单弹窗样式**
在样式末尾(第 496 行之后),添加深度选择器样式:
```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;
}
}
}
```
**Step 3: 验证样式语法**
```bash
cd ruoyi-ui
npm run lint -- --fix src/views/ccdiProject/detail.vue
```
预期:无语法错误
**Step 4: 提交导航菜单样式**
```bash
git add ruoyi-ui/src/views/ccdiProject/detail.vue
git commit -m "style(ccdiProject): 添加导航菜单简洁链接风格样式"
```
---
## Task 9: 修改 detail.vue - 添加响应式样式
**Files:**
- Modify: `ruoyi-ui/src/views/ccdiProject/detail.vue`
**Step 1: 添加响应式样式**
在现有的 `@media (max-width: 768px)` 媒体查询中(第 464 行),找到 `.detail-header` 样式块,添加响应式菜单样式:
```scss
@media (max-width: 768px) {
.dpc-detail-container {
padding: 8px;
}
.detail-header {
flex-direction: column;
align-items: flex-start;
gap: 12px;
.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;
}
}
}
}
// ... 其他现有响应式样式保持不变
}
```
**Step 2: 验证响应式样式**
```bash
cd ruoyi-ui
npm run lint -- --fix src/views/ccdiProject/detail.vue
```
预期:无语法错误
**Step 3: 提交响应式样式**
```bash
git add ruoyi-ui/src/views/ccdiProject/detail.vue
git commit -m "style(ccdiProject): 添加导航菜单响应式布局支持"
```
---
## Task 10: 手动测试验证
**Files:**
- Test: `ruoyi-ui/src/views/ccdiProject/detail.vue`
**Step 1: 启动前端开发服务器**
```bash
cd ruoyi-ui
npm run dev
```
预期:服务启动成功,监听 http://localhost:80
**Step 2: 访问项目详情页面**
在浏览器中访问:`http://localhost/ccdiProject`,点击任意项目进入详情页面
预期:页面正常加载,右侧显示导航菜单
**Step 3: 测试菜单切换功能**
测试步骤:
1. 点击"上传数据"菜单项
- 预期:激活状态显示蓝色文字和底部下划线,显示 UploadData 组件
2. 点击"参数配置"菜单项
- 预期:激活状态切换,显示 ParamConfig 占位组件("参数配置功能开发中..."
3. 点击"初核结果"菜单,展开下拉菜单
- 预期:下拉菜单展开,显示三个子项
4. 点击"结果总览"子菜单项
- 预期:激活状态切换,显示 PreliminaryCheck 占位组件
5. 点击"专项排查"子菜单项
- 预期:显示 SpecialCheck 占位组件
6. 点击"流水明细查询"子菜单项
- 预期:显示 DetailQuery 占位组件
**Step 4: 测试样式效果**
测试步骤:
1. Hover 菜单项
- 预期:显示浅灰背景(#f5f7fa
2. 检查激活菜单项
- 预期:蓝色文字(#1890ff+ 底部 2px 蓝色下划线
3. 点击下拉菜单外部区域
- 预期:下拉菜单关闭
4. 调整浏览器窗口宽度至 768px 以下
- 预期:菜单项平均分配宽度,布局自适应
**Step 5: 测试数据传递**
测试步骤:
1. 切换到"参数配置"组件
2. 在浏览器控制台检查组件 props
- 预期projectId 和 projectInfo 正确传递
3. 点击"上传数据"中的功能按钮
- 预期:事件正常触发,原有功能不受影响
**Step 6: 记录测试结果**
创建测试报告文件 `docs/test-reports/2026-03-04-navigation-menu-test.md`:
```markdown
# 项目详情页面导航菜单改造测试报告
## 测试环境
- 浏览器: [记录浏览器名称和版本]
- 测试时间: 2026-03-04
- 测试人员: [你的名字]
## 功能测试
### 菜单切换
- [x] 点击"上传数据",显示 UploadData 组件
- [x] 点击"参数配置",显示 ParamConfig 占位组件
- [x] 点击"初核结果",下拉菜单展开
- [x] 点击"结果总览",显示 PreliminaryCheck 占位组件
- [x] 点击"专项排查",显示 SpecialCheck 占位组件
- [x] 点击"流水明细查询",显示 DetailQuery 占位组件
### 样式测试
- [x] 默认状态:灰色文字,透明背景
- [x] Hover 状态:浅灰背景,深色文字
- [x] 激活状态:蓝色文字 + 底部下划线
- [x] 下拉菜单样式统一
### 交互测试
- [x] 下拉菜单点击外部区域关闭
- [x] 菜单切换流畅无闪烁
- [x] 组件切换数据正确传递
### 响应式测试
- [x] 移动端菜单布局正常
- [x] 菜单项平均分配宽度
## 问题记录
[记录发现的任何问题]
## 测试结论
[通过/需要修复]
```
**Step 7: 提交测试报告**
```bash
git add docs/test-reports/2026-03-04-navigation-menu-test.md
git commit -m "test(ccdiProject): 添加导航菜单改造测试报告"
```
---
## Task 11: 清理和最终提交
**Step 1: 检查所有修改文件**
```bash
git status
```
预期:所有修改已提交
**Step 2: 查看提交历史**
```bash
git log --oneline -10
```
预期:看到 10 个新提交:
1. feat(ccdiProject): 添加参数配置占位组件
2. feat(ccdiProject): 添加结果总览占位组件
3. feat(ccdiProject): 添加专项排查占位组件
4. feat(ccdiProject): 添加流水明细查询占位组件
5. feat(ccdiProject): 导入子组件并添加菜单状态数据
6. feat(ccdiProject): 替换按钮组为导航菜单并使用动态组件
7. feat(ccdiProject): 添加菜单选择处理方法并清理废弃代码
8. style(ccdiProject): 添加导航菜单简洁链接风格样式
9. style(ccdiProject): 添加导航菜单响应式布局支持
10. test(ccdiProject): 添加导航菜单改造测试报告
**Step 3: 验证无遗留问题**
```bash
cd ruoyi-ui
npm run lint
```
预期:无 lint 错误
**Step 4: 推送到远程分支**
```bash
git push origin dev
```
预期:推送成功
---
## 实施后检查清单
- [ ] 所有 4 个占位组件已创建
- [ ] detail.vue 已修改完成(模板、脚本、样式)
- [ ] 导航菜单样式符合简洁链接风格
- [ ] 菜单切换功能正常
- [ ] 下拉菜单交互正常
- [ ] 响应式布局正常
- [ ] 所有修改已提交到 git
- [ ] 测试报告已完成
- [ ] 代码已推送到远程仓库
---
## 预期成果
### 文件创建
- `ruoyi-ui/src/views/ccdiProject/components/detail/ParamConfig.vue`
- `ruoyi-ui/src/views/ccdiProject/components/detail/PreliminaryCheck.vue`
- `ruoyi-ui/src/views/ccdiProject/components/detail/SpecialCheck.vue`
- `ruoyi-ui/src/views/ccdiProject/components/detail/DetailQuery.vue`
- `docs/test-reports/2026-03-04-navigation-menu-test.md`
### 文件修改
- `ruoyi-ui/src/views/ccdiProject/detail.vue`(模板、脚本、样式)
### Git 提交
- 10 个功能清晰的提交记录
### 功能实现
- ✅ 水平导航菜单替代按钮组
- ✅ 简洁链接风格样式
- ✅ 菜单切换组件内容
- ✅ 下拉菜单支持
- ✅ 响应式布局
- ✅ 原有功能不受影响
---
## 潜在问题和解决方案
### 问题 1: 组件切换时状态丢失
**解决方案:** 使用 `<keep-alive>` 包裹动态组件(可选优化)
```vue
<keep-alive>
<component :is="currentComponent" ... />
</keep-alive>
```
### 问题 2: 下拉菜单样式不生效
**解决方案:** 检查 `::v-deep` 是否被正确编译,可能需要使用 `/deep/``>>>`
### 问题 3: 移动端菜单换行
**解决方案:** 调整响应式断点或使用折叠菜单el-menu 的 collapse 模式)
### 问题 4: 原有事件未触发
**解决方案:** 检查动态组件的事件绑定是否完整,确保所有事件都有对应的处理方法
---
## 后续优化建议
1. **添加组件切换动画**
```vue
<transition name="fade" mode="out-in">
<component :is="currentComponent" ... />
</transition>
```
2. **实现占位组件的完整功能**
- ParamConfig: 模型参数配置界面
- PreliminaryCheck: 结果总览数据展示
- SpecialCheck: 专项排查功能
- DetailQuery: 流水明细查询和筛选
3. **添加菜单权限控制**
- 根据用户权限显示/隐藏菜单项
- 使用 `v-if` 或动态生成菜单配置
4. **添加面包屑导航**
- 在页面顶部显示当前位置
- 支持快速返回上级页面
5. **添加快捷键支持**
- Ctrl+Tab: 切换到下一个菜单
- Ctrl+Shift+Tab: 切换到上一个菜单
---
## 相关技能参考
- @superpowers:brainstorming - 需求分析和设计
- @superpowers:test-driven-development - TDD 开发流程
- @superpowers:verification-before-completion - 完成前验证
- @superpowers:requesting-code-review - 代码审查
---
## 文档参考
- 设计文档: `docs/plans/2026-03-04-project-detail-navigation-menu-design.md`
- Element UI Menu 文档: https://element.eleme.cn/#/zh-CN/component/menu
- Vue 动态组件: https://cn.vuejs.org/v2/guide/components.html#动态组件