From 4395d9fb225ae92f6c7f4854101644c9f267ffcc Mon Sep 17 00:00:00 2001 From: qiaoxinjiu Date: Wed, 22 Apr 2026 10:00:17 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E5=B9=B3=E5=8F=B0=E5=8A=9F=E8=83=BD=EF=BC=8C=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=EF=BC=8C=E6=94=AF=E6=8C=81=E5=A4=9A=E4=B8=AA?= =?UTF-8?q?=E8=A7=92=E8=89=B2=EF=BC=8C=E5=88=86=E9=85=8D=E8=8F=9C=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .plan/MEVsZvRZopyrJGc3cNsiN.md | 129 +++++++ Jenkins.txt | 2 +- config/index.js | 9 +- src/App.vue | 26 +- src/api/CreateDtapi.js | 10 +- src/api/Userapi.js | 6 +- src/api/caseApi.js | 122 ++++++ src/api/dataFactoryApi.js | 66 ++++ src/api/planApi.js | 98 +++++ src/api/productApi.js | 33 ++ src/api/projectApi.js | 91 +++++ src/api/rbacApi.js | 169 +++++++++ src/api/reportApi.js | 28 ++ src/components/Home.vue | 141 ++++++- src/components/System/MenuManage.vue | 322 ++++++++++++++++ src/components/System/RoleManage.vue | 353 +++++++++++++++++ src/components/System/UserManage.vue | 358 ++++++++++++++++++ .../TestPlatform/Case/CaseEditor.vue | 116 ++++++ src/components/TestPlatform/Case/CaseList.vue | 110 ++++++ .../TestPlatform/Case/CaseReview.vue | 64 ++++ .../DataFactory/BuilderEditor.vue | 82 ++++ .../TestPlatform/DataFactory/BuilderList.vue | 100 +++++ .../TestPlatform/DataFactory/MockService.vue | 72 ++++ .../TestPlatform/DataFactory/TaskHistory.vue | 55 +++ .../TestPlatform/Plan/PlanBuilder.vue | 69 ++++ .../TestPlatform/Plan/PlanExecute.vue | 114 ++++++ src/components/TestPlatform/Plan/PlanList.vue | 106 ++++++ .../TestPlatform/Plan/PlanProgress.vue | 73 ++++ .../TestPlatform/Product/ProductList.vue | 223 +++++++++++ .../TestPlatform/Project/ProjectDetail.vue | 55 +++ .../TestPlatform/Project/ProjectList.vue | 247 ++++++++++++ .../TestPlatform/Project/ProjectSettings.vue | 281 ++++++++++++++ .../TestPlatform/Report/ReportList.vue | 104 +++++ .../TestPlatform/Report/ReportViewer.vue | 58 +++ .../TestPlatform/common/JsonViewer.vue | 40 ++ .../common/KeyValueDescriptions.vue | 37 ++ .../TestPlatform/common/PageSection.vue | 39 ++ src/components/User/Login.vue | 71 +++- src/components/User/Register.vue | 73 ++-- src/router/index.js | 140 +++++++ src/utils/request.js | 9 +- src/vuex/store.js | 19 +- 42 files changed, 4239 insertions(+), 81 deletions(-) create mode 100644 .plan/MEVsZvRZopyrJGc3cNsiN.md create mode 100644 src/api/caseApi.js create mode 100644 src/api/dataFactoryApi.js create mode 100644 src/api/planApi.js create mode 100644 src/api/productApi.js create mode 100644 src/api/projectApi.js create mode 100644 src/api/rbacApi.js create mode 100644 src/api/reportApi.js create mode 100644 src/components/System/MenuManage.vue create mode 100644 src/components/System/RoleManage.vue create mode 100644 src/components/System/UserManage.vue create mode 100644 src/components/TestPlatform/Case/CaseEditor.vue create mode 100644 src/components/TestPlatform/Case/CaseList.vue create mode 100644 src/components/TestPlatform/Case/CaseReview.vue create mode 100644 src/components/TestPlatform/DataFactory/BuilderEditor.vue create mode 100644 src/components/TestPlatform/DataFactory/BuilderList.vue create mode 100644 src/components/TestPlatform/DataFactory/MockService.vue create mode 100644 src/components/TestPlatform/DataFactory/TaskHistory.vue create mode 100644 src/components/TestPlatform/Plan/PlanBuilder.vue create mode 100644 src/components/TestPlatform/Plan/PlanExecute.vue create mode 100644 src/components/TestPlatform/Plan/PlanList.vue create mode 100644 src/components/TestPlatform/Plan/PlanProgress.vue create mode 100644 src/components/TestPlatform/Product/ProductList.vue create mode 100644 src/components/TestPlatform/Project/ProjectDetail.vue create mode 100644 src/components/TestPlatform/Project/ProjectList.vue create mode 100644 src/components/TestPlatform/Project/ProjectSettings.vue create mode 100644 src/components/TestPlatform/Report/ReportList.vue create mode 100644 src/components/TestPlatform/Report/ReportViewer.vue create mode 100644 src/components/TestPlatform/common/JsonViewer.vue create mode 100644 src/components/TestPlatform/common/KeyValueDescriptions.vue create mode 100644 src/components/TestPlatform/common/PageSection.vue diff --git a/.plan/MEVsZvRZopyrJGc3cNsiN.md b/.plan/MEVsZvRZopyrJGc3cNsiN.md new file mode 100644 index 0000000..76aa048 --- /dev/null +++ b/.plan/MEVsZvRZopyrJGc3cNsiN.md @@ -0,0 +1,129 @@ +# 前端实现计划:测试平台页面与接口 + +## 1. 现状确认 +- 当前项目不是 React 18 + TypeScript,而是 **Vue 2 + Element UI + vue-router + vuex + axios**。 +- 已有页面以“效能平台/造数工具”为主,目录集中在: + - `src/components/` + - `src/api/` + - `src/router/index.js` +- 已存在一套造数相关接口封装:`src/api/CreateDtapi.js` +- 已存在基础布局页:`src/components/Home.vue` +- 因此本次应遵循**现有 Vue 2 结构**落地,不直接按你给出的 React 目录硬切,否则与当前代码库不兼容。 + +## 2. 实施目标 +按你提供的详细设计,在当前项目结构下补齐并升级前端代码,重点实现: +- 测试平台导航结构 +- 项目/用例/计划/报告/造数 五大功能入口页面 +- 对应 API 封装层 +- 页面级列表、详情、表单、执行、报告查看等基础交互 +- 复用当前 Element UI 风格,保持现有代码可运行 + +## 3. 实施范围拆分 + +### 阶段 A:基础设施与路由改造 +1. 梳理现有路由与导航。 +2. 扩展左侧菜单,新增模块入口: + - 项目管理 + - 用例管理 + - 测试计划 + - 测试报告 + - 造数工厂 +3. 在 `src/router/index.js` 注册对应页面路由。 +4. 保留现有造数页面入口,避免破坏已有功能。 + +### 阶段 B:API 服务层补齐 +1. 新增 API 文件,按你给出的接口定义封装: + - `src/api/projectApi.js` + - `src/api/caseApi.js` + - `src/api/planApi.js` + - `src/api/reportApi.js` + - `src/api/dataFactoryApi.js` +2. 统一复用 `src/utils/request.js`。 +3. 尽量映射到 REST 风格路径,例如: + - `/api/v1/projects/{projectId}/cases` + - `/api/v1/projects/{projectId}/plans` + - `/api/v1/projects/{projectId}/reports` + - `/api/v1/projects/{projectId}/data/*` +4. 对分页、详情、创建、更新、执行、导出等接口做最小可用封装。 + +### 阶段 C:页面骨架实现 +在 `src/components/` 下新增测试平台模块页面,优先做可运行页面骨架与核心交互: + +1. 项目模块 + - `src/components/TestPlatform/Project/ProjectList.vue` + - `src/components/TestPlatform/Project/ProjectDetail.vue` + - `src/components/TestPlatform/Project/ProjectSettings.vue` + +2. 用例模块 + - `src/components/TestPlatform/Case/CaseList.vue` + - `src/components/TestPlatform/Case/CaseEditor.vue` + - `src/components/TestPlatform/Case/CaseReview.vue` + +3. 测试计划模块 + - `src/components/TestPlatform/Plan/PlanList.vue` + - `src/components/TestPlatform/Plan/PlanBuilder.vue` + - `src/components/TestPlatform/Plan/PlanExecute.vue` + - `src/components/TestPlatform/Plan/PlanProgress.vue` + +4. 报告模块 + - `src/components/TestPlatform/Report/ReportList.vue` + - `src/components/TestPlatform/Report/ReportViewer.vue` + +5. 造数模块升级 + - 保留现有 `CreateData/*` + - 新增测试平台语义下页面: + - `src/components/TestPlatform/DataFactory/BuilderList.vue` + - `src/components/TestPlatform/DataFactory/BuilderEditor.vue` + - `src/components/TestPlatform/DataFactory/TaskHistory.vue` + - `src/components/TestPlatform/DataFactory/MockService.vue` + +### 阶段 D:公共组件抽取 +新增可复用基础组件,减少页面重复: +- `src/components/TestPlatform/common/JsonViewer.vue` +- `src/components/TestPlatform/common/KeyValueDescriptions.vue` +- `src/components/TestPlatform/common/PageSection.vue` + +### 阶段 E:联调友好处理 +1. 页面初版支持后端未完成时的容错: + - 空数据态 + - 请求失败提示 + - 默认 projectId 占位 +2. 不引入新依赖,避免额外安装。 +3. 保持接口函数独立,后续联调时只需替换 URL 或参数格式。 + +## 4. 执行顺序 +1. 先改路由与主页导航。 +2. 再补 API 封装。 +3. 再按模块逐步落页面: + - 项目 + - 用例 + - 计划 + - 报告 + - 造数 +4. 最后做公共组件复用与样式收口。 + +## 5. 每阶段交付物 +- 阶段 A:可点击进入的菜单与路由 +- 阶段 B:完整接口文件 +- 阶段 C:各模块页面可打开、可发请求、可展示表格/表单 +- 阶段 D:重复 UI 收敛 +- 阶段 E:整体自检,确保不破坏原有功能 + +## 6. 风险与约束 +- 当前代码库是旧版 Vue 2 工程,不能直接生成 React/TSX 代码。 +- 你的接口设计是目标态,实际后端返回结构可能与设计不完全一致,因此前端会适当做字段兼容。 +- 由于当前 `request.js` 已固定 `baseURL`,本次先复用,不额外改动接口基础配置,避免影响现有功能。 + +## 7. 本次建议执行策略 +按“先骨架、再细化”的方式推进: +- 第一步:完成导航、路由、API 文件、页面骨架 +- 第二步:优先把列表页和详情/编辑页做成可联调版本 +- 第三步:再补计划执行、报告查看、造数编排等复杂交互 + +## 8. 下一步实际执行内容 +获批后,我将从以下顺序开始落地: +1. 修改 `src/components/Home.vue` 增加测试平台菜单 +2. 修改 `src/router/index.js` 注册测试平台路由 +3. 新增五类 API 文件 +4. 新增项目/用例/计划/报告/造数页面骨架 +5. 检查并修正页面间跳转与基础请求 diff --git a/Jenkins.txt b/Jenkins.txt index eefc74f..94ed1c8 100644 --- a/Jenkins.txt +++ b/Jenkins.txt @@ -23,7 +23,7 @@ pipeline { DEPLOY_PORT = '22' DEPLOY_USER = 'user' CONTAINER_NAME = 'effekt-interface-frontend' - HOST_PORT = '8080' + HOST_PORT = '8881' CONTAINER_PORT = '80' } diff --git a/config/index.js b/config/index.js index e2c3467..7cd288c 100644 --- a/config/index.js +++ b/config/index.js @@ -10,7 +10,12 @@ module.exports = { // Paths assetsSubDirectory: 'static', assetsPublicPath: '/', - proxyTable: {}, + proxyTable: { + '/it/api': { + target: 'http://192.168.11.46:5010', + changeOrigin: true + } + }, // Various Dev Server settings // host: '172.19.29.63', // can be overwritten by process.env.HOST @@ -18,7 +23,7 @@ module.exports = { port: 8081, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined autoOpenBrowser: false, errorOverlay: true, - notifyOnErrors: true, + notifyOnErrors: false, poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- diff --git a/src/App.vue b/src/App.vue index 1b89d05..30b67fb 100644 --- a/src/App.vue +++ b/src/App.vue @@ -5,16 +5,30 @@ + + diff --git a/src/components/System/RoleManage.vue b/src/components/System/RoleManage.vue new file mode 100644 index 0000000..ce8d4c0 --- /dev/null +++ b/src/components/System/RoleManage.vue @@ -0,0 +1,353 @@ + + + + + + + created() { + this.fetchList() + } +} + + +reated() { + this.fetchList() + } +} + + diff --git a/src/components/System/UserManage.vue b/src/components/System/UserManage.vue new file mode 100644 index 0000000..9c5acbb --- /dev/null +++ b/src/components/System/UserManage.vue @@ -0,0 +1,358 @@ + + + + + diff --git a/src/components/TestPlatform/Case/CaseEditor.vue b/src/components/TestPlatform/Case/CaseEditor.vue new file mode 100644 index 0000000..dd71055 --- /dev/null +++ b/src/components/TestPlatform/Case/CaseEditor.vue @@ -0,0 +1,116 @@ + + + + + diff --git a/src/components/TestPlatform/Case/CaseList.vue b/src/components/TestPlatform/Case/CaseList.vue new file mode 100644 index 0000000..3ba2a13 --- /dev/null +++ b/src/components/TestPlatform/Case/CaseList.vue @@ -0,0 +1,110 @@ + + + + + diff --git a/src/components/TestPlatform/Case/CaseReview.vue b/src/components/TestPlatform/Case/CaseReview.vue new file mode 100644 index 0000000..e7a15f7 --- /dev/null +++ b/src/components/TestPlatform/Case/CaseReview.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/src/components/TestPlatform/DataFactory/BuilderEditor.vue b/src/components/TestPlatform/DataFactory/BuilderEditor.vue new file mode 100644 index 0000000..c41ecfd --- /dev/null +++ b/src/components/TestPlatform/DataFactory/BuilderEditor.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/src/components/TestPlatform/DataFactory/BuilderList.vue b/src/components/TestPlatform/DataFactory/BuilderList.vue new file mode 100644 index 0000000..ec8b05d --- /dev/null +++ b/src/components/TestPlatform/DataFactory/BuilderList.vue @@ -0,0 +1,100 @@ + + + + + +style> diff --git a/src/components/TestPlatform/DataFactory/MockService.vue b/src/components/TestPlatform/DataFactory/MockService.vue new file mode 100644 index 0000000..7a58934 --- /dev/null +++ b/src/components/TestPlatform/DataFactory/MockService.vue @@ -0,0 +1,72 @@ + + + + + diff --git a/src/components/TestPlatform/DataFactory/TaskHistory.vue b/src/components/TestPlatform/DataFactory/TaskHistory.vue new file mode 100644 index 0000000..f8c9cb7 --- /dev/null +++ b/src/components/TestPlatform/DataFactory/TaskHistory.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/src/components/TestPlatform/Plan/PlanBuilder.vue b/src/components/TestPlatform/Plan/PlanBuilder.vue new file mode 100644 index 0000000..d5d5852 --- /dev/null +++ b/src/components/TestPlatform/Plan/PlanBuilder.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/src/components/TestPlatform/Plan/PlanExecute.vue b/src/components/TestPlatform/Plan/PlanExecute.vue new file mode 100644 index 0000000..2278c95 --- /dev/null +++ b/src/components/TestPlatform/Plan/PlanExecute.vue @@ -0,0 +1,114 @@ + + + + + diff --git a/src/components/TestPlatform/Plan/PlanList.vue b/src/components/TestPlatform/Plan/PlanList.vue new file mode 100644 index 0000000..91290dd --- /dev/null +++ b/src/components/TestPlatform/Plan/PlanList.vue @@ -0,0 +1,106 @@ + + + + + diff --git a/src/components/TestPlatform/Plan/PlanProgress.vue b/src/components/TestPlatform/Plan/PlanProgress.vue new file mode 100644 index 0000000..47ae1b2 --- /dev/null +++ b/src/components/TestPlatform/Plan/PlanProgress.vue @@ -0,0 +1,73 @@ + + + + + diff --git a/src/components/TestPlatform/Product/ProductList.vue b/src/components/TestPlatform/Product/ProductList.vue new file mode 100644 index 0000000..f180f76 --- /dev/null +++ b/src/components/TestPlatform/Product/ProductList.vue @@ -0,0 +1,223 @@ + + + + + diff --git a/src/components/TestPlatform/Project/ProjectDetail.vue b/src/components/TestPlatform/Project/ProjectDetail.vue new file mode 100644 index 0000000..4e10fd5 --- /dev/null +++ b/src/components/TestPlatform/Project/ProjectDetail.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/src/components/TestPlatform/Project/ProjectList.vue b/src/components/TestPlatform/Project/ProjectList.vue new file mode 100644 index 0000000..0c3a4cb --- /dev/null +++ b/src/components/TestPlatform/Project/ProjectList.vue @@ -0,0 +1,247 @@ + + + + + diff --git a/src/components/TestPlatform/Project/ProjectSettings.vue b/src/components/TestPlatform/Project/ProjectSettings.vue new file mode 100644 index 0000000..16d8399 --- /dev/null +++ b/src/components/TestPlatform/Project/ProjectSettings.vue @@ -0,0 +1,281 @@ + + + + + diff --git a/src/components/TestPlatform/Report/ReportList.vue b/src/components/TestPlatform/Report/ReportList.vue new file mode 100644 index 0000000..279bc24 --- /dev/null +++ b/src/components/TestPlatform/Report/ReportList.vue @@ -0,0 +1,104 @@ + + + + + diff --git a/src/components/TestPlatform/Report/ReportViewer.vue b/src/components/TestPlatform/Report/ReportViewer.vue new file mode 100644 index 0000000..0adb7c5 --- /dev/null +++ b/src/components/TestPlatform/Report/ReportViewer.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/src/components/TestPlatform/common/JsonViewer.vue b/src/components/TestPlatform/common/JsonViewer.vue new file mode 100644 index 0000000..a114af6 --- /dev/null +++ b/src/components/TestPlatform/common/JsonViewer.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/src/components/TestPlatform/common/KeyValueDescriptions.vue b/src/components/TestPlatform/common/KeyValueDescriptions.vue new file mode 100644 index 0000000..30e67b5 --- /dev/null +++ b/src/components/TestPlatform/common/KeyValueDescriptions.vue @@ -0,0 +1,37 @@ + + + diff --git a/src/components/TestPlatform/common/PageSection.vue b/src/components/TestPlatform/common/PageSection.vue new file mode 100644 index 0000000..34f40a3 --- /dev/null +++ b/src/components/TestPlatform/common/PageSection.vue @@ -0,0 +1,39 @@ + + + + + diff --git a/src/components/User/Login.vue b/src/components/User/Login.vue index 5f2e55d..e7d49a2 100644 --- a/src/components/User/Login.vue +++ b/src/components/User/Login.vue @@ -12,7 +12,7 @@   + placeholder="用户名" + @keyup.enter="handleLogin">
  @@ -34,14 +35,13 @@ type="password" size="25" autocomplete="off" - placeholder="密码"> + placeholder="密码" + @keyup.enter="handleLogin">
- - 注册 - + 注册
@@ -49,31 +49,70 @@ diff --git a/src/utils/request.js b/src/utils/request.js index b36deae..ee22868 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -26,17 +26,30 @@ service.interceptors.request.use( // 响应拦截 401 token过期处理 service.interceptors.response.use( response => { - if(response.data.code===500){ - Message.error("服务异常") - }else if(response.data.code===451){ - router.push({name:'login'}) - } - else { + const data = response && response.data ? response.data : {} + // 兼容后端返回结构:{ success, code, message, data } + if (data && data.code === 500) { + Message.error('服务异常') + } else if (data && data.code === 451) { + router.push({ name: 'login' }) + } else if (data && data.success === false) { + Message.error(data.message || '请求失败') + } else { return response.data } }, error => { - // 错误提醒 + // 非 2xx 时会进入这里(如 40009/40012),后端通常会带 JSON body + const data = error && error.response && error.response.data ? error.response.data : null + if (data && typeof data === 'object') { + if (data.success === false) { + Message.error(data.message || '请求失败') + } else if (data.code && data.code !== 20000 && data.message) { + Message.error(data.message || '请求失败') + } + } else if (error && error.message) { + Message.error(error.message) + } return Promise.reject(error) } ) -- 2.49.1 From f8211673eee56fef71e8f685088ef6bf6b0620fc Mon Sep 17 00:00:00 2001 From: qiaoxinjiu Date: Thu, 7 May 2026 19:43:05 +0800 Subject: [PATCH 4/8] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=EF=BC=9A=E6=96=B0=E5=A2=9EBug=E7=AE=A1=E7=90=86=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=EF=BC=8C=E5=AE=8C=E5=96=84=E7=94=A8=E6=88=B7=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E5=88=86=E9=85=8D=EF=BC=8C=E4=BC=98=E5=8C=96=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .plan/MEVsZvRZopyrJGc3cNsiN.md | 4 +- .plan/fsKfEW4Z6YGlqrLCshlxS.md | 165 ++ index.html | 1 + package-lock.json | 226 +-- package.json | 4 +- src/App.vue | 5 +- src/api/CreateDtapi.js | 22 +- src/api/bugApi.js | 80 + src/api/caseApi.js | 21 + src/api/projectApi.js | 50 + src/api/rbacApi.js | 67 + src/api/reportApi.js | 27 +- src/components/Bug/BugDetail.vue | 1498 +++++++++++++++++ src/components/Bug/BugEditor.vue | 815 +++++++++ src/components/Bug/BugList.vue | 721 ++++++++ src/components/Bug/BugStats.vue | 701 ++++++++ src/components/Bug/BugStepsRichEditor.vue | 212 +++ src/components/CreateData/CreateDataInfo.vue | 4 +- src/components/EffektHome.vue | 301 +++- src/components/Home.vue | 106 +- src/components/System/MenuManage.vue | 177 ++ src/components/System/PermissionManage.vue | 464 +++++ src/components/System/UserManage.vue | 14 +- .../TestPlatform/Case/CaseEditor.vue | 55 +- src/components/TestPlatform/Case/CaseList.vue | 1464 +++++++++++++++- .../DataFactory/BuilderEditor.vue | 2 +- .../TestPlatform/DataFactory/BuilderList.vue | 6 +- .../TestPlatform/Plan/PlanBuilder.vue | 354 +++- .../TestPlatform/Plan/PlanCaseAdd.vue | 268 +++ .../TestPlatform/Plan/PlanExecute.vue | 319 +++- src/components/TestPlatform/Plan/PlanList.vue | 825 ++++++++- .../TestPlatform/Plan/PlanProgress.vue | 382 ++++- .../TestPlatform/Project/ProjectList.vue | 2 +- .../TestPlatform/Project/ProjectSettings.vue | 435 ++++- .../TestPlatform/Report/ReportList.vue | 320 +++- .../TestPlatform/Report/ReportViewer.vue | 13 +- src/components/User/Login.vue | 5 +- src/router/index.js | 95 +- src/utils/bugHistory.js | 73 + src/utils/bugHistoryDisplay.js | 163 ++ src/utils/bugMaps.js | 143 ++ src/utils/bugStepsFormat.js | 192 +++ src/utils/lastProductProjectCache.js | 39 + src/utils/request.js | 7 + 44 files changed, 10410 insertions(+), 437 deletions(-) create mode 100644 .plan/fsKfEW4Z6YGlqrLCshlxS.md create mode 100644 src/api/bugApi.js create mode 100644 src/components/Bug/BugDetail.vue create mode 100644 src/components/Bug/BugEditor.vue create mode 100644 src/components/Bug/BugList.vue create mode 100644 src/components/Bug/BugStats.vue create mode 100644 src/components/Bug/BugStepsRichEditor.vue create mode 100644 src/components/System/PermissionManage.vue create mode 100644 src/components/TestPlatform/Plan/PlanCaseAdd.vue create mode 100644 src/utils/bugHistory.js create mode 100644 src/utils/bugHistoryDisplay.js create mode 100644 src/utils/bugMaps.js create mode 100644 src/utils/bugStepsFormat.js create mode 100644 src/utils/lastProductProjectCache.js diff --git a/.plan/MEVsZvRZopyrJGc3cNsiN.md b/.plan/MEVsZvRZopyrJGc3cNsiN.md index 76aa048..975f62e 100644 --- a/.plan/MEVsZvRZopyrJGc3cNsiN.md +++ b/.plan/MEVsZvRZopyrJGc3cNsiN.md @@ -40,8 +40,8 @@ - `src/api/dataFactoryApi.js` 2. 统一复用 `src/utils/request.js`。 3. 尽量映射到 REST 风格路径,例如: - - `/api/v1/projects/{projectId}/cases` - - `/api/v1/projects/{projectId}/plans` + - `/api/v1/projects/{projectId}/case` + - `/api/v1/projects/{projectId}/plan` - `/api/v1/projects/{projectId}/reports` - `/api/v1/projects/{projectId}/data/*` 4. 对分页、详情、创建、更新、执行、导出等接口做最小可用封装。 diff --git a/.plan/fsKfEW4Z6YGlqrLCshlxS.md b/.plan/fsKfEW4Z6YGlqrLCshlxS.md new file mode 100644 index 0000000..7fee5a9 --- /dev/null +++ b/.plan/fsKfEW4Z6YGlqrLCshlxS.md @@ -0,0 +1,165 @@ +# 执行计划:用例管理与模块管理改造 + +## 目标 +根据后端 `Case 与 Module` 接口文档,改造前端接口调用与用例管理页面: +- 用例管理页面包含两个表格:模块列表、用例列表。 +- 模块支持查询、新增、删除,并展示模块字段与搜索条件。 +- 用例列表支持项目名称、用例标题模糊搜索、优先级、是否自动化、标签等条件。 +- 用例列表展示项目名称、用例编号、用例标题、优先级、类型、状态、是否实现自动化、标签等字段。 + +## 已定位文件 +- `src/api/caseApi.js` + - 已有 `module/tree/create/update/delete` 与 `case/list/detail/create/update/delete` 封装。 + - 当前部分参数仍使用旧字段:`project_id`、`case_id` 等,需要调整为文档里的 camelCase 参数。 +- `src/components/TestPlatform/Case/CaseList.vue` + - 当前只有一个用例表格。 + - 当前搜索条件只有项目ID、关键词、优先级。 + - 当前缺少分页状态定义与模块管理区。 +- `src/components/TestPlatform/Case/CaseEditor.vue` + - 当前表单字段使用 `case_type` 等后端返回字段,提交时需要按文档转为 `caseType`、`moduleId`、`caseKey`、`isAuto` 等。 +- `src/router/index.js` + - 用例相关路由已存在,无需新增路由。 + +## 改造步骤 + +### 1. 调整接口封装 `src/api/caseApi.js` +- 保留已有函数名,降低页面调用改动成本。 +- `getCaseList(projectId, params)` 改为请求参数包含: + - `projectId` + - `pageNo` + - `pageSize` + - `projectName` + - `moduleId` + - `keyword` + - `priority` + - `caseType` + - `status` + - `isAuto` + - `tag` +- `getCaseDetail(projectId, caseId)` 改为传 `caseId`,必要时兼容 `projectId`。 +- `createCase(projectId, data)` 改为提交 `projectId`,不再提交 `project_id`。 +- `updateCase(projectId, caseId, data)` 改为提交 `caseId`,不再提交 `id/project_id` 旧字段。 +- `deleteCase(projectId, caseId)` 改为提交 `{ caseId }`,必要时保留 `projectId` 不影响后端。 +- 模块接口保持: + - `getModuleTree(params)` -> `/module/tree` + - `createModule(data)` -> `/module/create` + - `deleteModule(data)` -> `/module/delete` + - 删除模块调用传 `{ moduleId }`。 + +### 2. 改造 `CaseList.vue` 页面布局 +- 在同一个页面内使用两个 `page-section`: + 1. `模块列表` + 2. `用例列表` +- 模块列表区: + - 搜索条件:`projectId`、`parentId`。 + - 按钮:查询、新增模块。 + - 表格字段: + - 模块ID:`id` + - 项目ID:`project_id` + - 父模块ID:`parent_id` + - 模块名称:`name` + - 排序:`sort_order` + - 路径:`path` + - 创建时间:`created_time` + - 更新时间:`updated_time` + - 操作:删除 + - 新增模块弹窗字段: + - `projectId` 必填 + - `name` 必填 + - `parentId` + - `sortOrder` + - `path` + - 删除模块调用 `deleteModule({ moduleId: row.id })`。 + +### 3. 改造用例列表搜索条件 +- 搜索表单字段: + - `projectId` + - `projectName` + - `keyword`(用例标题模糊搜索) + - `priority` + - `caseType` + - `status` + - `isAuto` + - `tag` +- 查询时传入分页:`pageNo`、`pageSize`。 +- 查询成功后兼容读取:`data.list || data.items || []`,`data.total || list.length`。 + +### 4. 改造用例列表表格字段展示 +- 表格字段: + - 项目名称:`project_name` + - 用例编号:`case_key` + - 用例标题:`title` + - 优先级:`priority`,格式化为 `P0/P1/P2/P3` + - 类型:`case_type`,格式化为 `功能/性能/安全/接口` + - 状态:`status`,格式化为 `正常/已废弃/评审中` + - 是否实现自动化:`is_auto`,格式化为 `已实现/未实现` + - 标签:`tags`,数组使用 `el-tag` 展示,字符串兜底直接展示 + - 操作:编辑、评审、删除 +- 删除用例调用 `deleteCase(projectId, row.id)`。 + +### 5. 补齐分页与交互逻辑 +- `CaseList.vue` 增加: + - `pageNo` + - `pageSize` + - `total` + - `moduleLoading` + - `moduleData` + - `moduleQueryForm` + - `moduleDialogVisible` + - `moduleSubmitting` + - `moduleForm` + - `moduleRules` +- 增加方法: + - `fetchModuleList` + - `openModuleCreate` + - `resetModuleForm` + - `submitModuleCreate` + - `removeModule` + - `handleSizeChange` + - `handleCurrentChange` + - `formatPriority` + - `formatCaseType` + - `formatStatus` + - `formatIsAuto` + - `formatTags` + +### 6. 调整 `CaseEditor.vue` 提交字段 +- 详情加载:兼容后端 snake_case 返回字段,映射到表单: + - `module_id` -> `moduleId` + - `case_key` -> `caseKey` + - `case_type` -> `caseType` + - `is_auto` -> `isAuto` +- 表单补充字段: + - 模块ID + - 用例编号 + - 状态 + - 是否自动化 +- 保存前构造 payload: + - `projectId` + - `moduleId` + - `caseKey` + - `title` + - `preconditions` + - `steps` + - `priority` + - `caseType` + - `tags` + - `status` + - `isAuto` +- 新增调用 `createCase(projectId, payload)`。 +- 编辑调用 `updateCase(projectId, caseId, payload)`。 + +### 7. 验证 +- 优先运行:`npm run build`。 +- 如构建耗时或环境缺依赖,至少做静态检查:确认 Vue 模板字段、方法引用、导入函数均存在。 + +## 预期改动范围 +- 修改:`src/api/caseApi.js` +- 修改:`src/components/TestPlatform/Case/CaseList.vue` +- 修改:`src/components/TestPlatform/Case/CaseEditor.vue` +- 不新增路由,不新增依赖。 + +## 风险与兼容处理 +- 后端返回字段是 snake_case,前端提交字段是 camelCase,需要在编辑页做映射。 +- 若后端仍兼容旧字段,当前改造会优先使用新文档字段;删除/详情可保留少量兼容参数但不依赖旧字段。 +- 模块树接口可能返回树形结构,但当前需求是模块列表 table;表格直接展示返回 list,不做树形展开,除非后续明确需要树表。 \ No newline at end of file diff --git a/index.html b/index.html index e3f539d..a87da34 100644 --- a/index.html +++ b/index.html @@ -4,6 +4,7 @@ 造数管理系统 + + + diff --git a/src/components/Bug/BugEditor.vue b/src/components/Bug/BugEditor.vue new file mode 100644 index 0000000..9bec5b5 --- /dev/null +++ b/src/components/Bug/BugEditor.vue @@ -0,0 +1,815 @@ + + + + + diff --git a/src/components/Bug/BugList.vue b/src/components/Bug/BugList.vue new file mode 100644 index 0000000..ffd651f --- /dev/null +++ b/src/components/Bug/BugList.vue @@ -0,0 +1,721 @@ + + + + + diff --git a/src/components/Bug/BugStats.vue b/src/components/Bug/BugStats.vue new file mode 100644 index 0000000..bc722c7 --- /dev/null +++ b/src/components/Bug/BugStats.vue @@ -0,0 +1,701 @@ + + + + + diff --git a/src/components/Bug/BugStepsRichEditor.vue b/src/components/Bug/BugStepsRichEditor.vue new file mode 100644 index 0000000..623cf63 --- /dev/null +++ b/src/components/Bug/BugStepsRichEditor.vue @@ -0,0 +1,212 @@ + + + + + diff --git a/src/components/CreateData/CreateDataInfo.vue b/src/components/CreateData/CreateDataInfo.vue index 7625bc7..d7dfd7e 100644 --- a/src/components/CreateData/CreateDataInfo.vue +++ b/src/components/CreateData/CreateDataInfo.vue @@ -128,7 +128,7 @@ export default { ItApiCreate(this.form).then(res => { if (res && res.success === true) { this.$message({type: 'success', message: this.form.sqlId ? '修改成功' : '新增成功'}) - this.$router.push({path: '/create/data'}) + this.$router.push({path: '/data-tools/db-builder'}) } else { this.$message({type: 'error', message: res.message || '保存失败'}) } @@ -138,7 +138,7 @@ export default { }) }, goBack() { - this.$router.push({path: '/create/data'}) + this.$router.push({path: '/data-tools/db-builder'}) } }, created() { diff --git a/src/components/EffektHome.vue b/src/components/EffektHome.vue index d210f0e..50b3577 100644 --- a/src/components/EffektHome.vue +++ b/src/components/EffektHome.vue @@ -1,24 +1,61 @@ @@ -62,6 +211,117 @@ export default { diff --git a/src/components/System/UserManage.vue b/src/components/System/UserManage.vue index 9c5acbb..28a312e 100644 --- a/src/components/System/UserManage.vue +++ b/src/components/System/UserManage.vue @@ -125,7 +125,7 @@ @@ -107,4 +1204,263 @@ export default { .page-wrap { padding: 20px; } + +.toolbar-wrap { + text-align: right; + margin-top: 8px; +} + +.case-action-buttons-item { + float: right; + margin-right: 0 !important; +} + +.more-filter-wrap { + padding: 4px 0; +} + +.more-filter-footer { + border-top: 1px solid #ebeef5; + text-align: right; + padding-top: 10px; +} + +.column-setting-wrap { + max-height: 320px; + overflow-y: auto; +} + +.column-setting-title { + color: #606266; + font-weight: 500; + margin-bottom: 8px; +} + +.case-import-panel { + border: 1px solid #ebeef5; + border-radius: 4px; + padding: 28px 24px; + text-align: center; +} + +.case-import-icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border-radius: 6px; + color: #fff; + background: #409eff; + font-weight: 600; + margin-bottom: 8px; +} + +.case-import-title { + font-size: 28px; + color: #303133; + margin-bottom: 6px; +} + +.case-import-subtitle { + color: #909399; + margin-bottom: 16px; +} + +.case-import-dropzone { + border: 1px dashed #dcdfe6; + border-radius: 4px; + padding: 28px 20px; + margin: 0 auto; + max-width: 520px; +} + +.case-import-drop-text { + color: #606266; + margin-bottom: 10px; +} + +.link-text { + color: #409eff; + cursor: pointer; +} + +.case-import-file-tip { + color: #909399; +} + +.case-import-file-name { + margin-top: 8px; + color: #303133; +} + +.case-import-actions { + margin-top: 18px; + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; +} + +.hidden-file-input { + display: none; +} + +.mindmap-wrap { + margin-top: 8px; + border: 1px solid #ebeef5; + border-radius: 6px; + background: #fafcff; + padding: 14px 12px; + min-height: 280px; + overflow: auto; +} + +.xmind-tree { + min-width: 980px; + background: transparent; +} + +.xmind-tree /deep/ .el-tree-node { + position: relative; +} + +.xmind-tree /deep/ .el-tree-node__content { + height: auto; + padding: 8px 0; +} + +.xmind-tree /deep/ .el-tree-node__children { + position: relative; + margin-left: 12px; + padding-left: 22px; +} + +.xmind-tree /deep/ .el-tree-node__children:before { + content: ''; + position: absolute; + left: 8px; + top: 0; + bottom: 10px; + border-left: 1px solid #b7d0e8; +} + +.xmind-tree /deep/ .el-tree-node__content:before { + content: ''; + position: absolute; + left: -14px; + top: 50%; + width: 14px; + border-top: 1px solid #8fb8de; +} + +.xmind-tree /deep/ .el-tree > .el-tree-node > .el-tree-node__content:before { + display: none; +} + +.mindmap-node { + display: inline-flex; + flex-direction: column; + gap: 6px; + min-width: 220px; + max-width: 760px; + background: #fff; + border: 1px solid #dce6ff; + border-radius: 8px; + padding: 8px 10px; + box-shadow: 0 1px 4px rgba(64, 158, 255, 0.08); +} + +.mindmap-node-wrap { + display: inline-flex; + align-items: flex-start; +} + +.mindmap-node-title { + color: #303133; + font-weight: 600; + line-height: 1.4; +} + +.mindmap-node-project { + border-color: #67c23a; + box-shadow: 0 1px 6px rgba(103, 194, 58, 0.16); +} + +.mindmap-node-module { + border-color: #e6a23c; + box-shadow: 0 1px 6px rgba(230, 162, 60, 0.14); +} + +.mindmap-node-case { + border-color: #7fb3e3; +} + +.mindmap-inline-detail { + display: inline-flex; + align-items: stretch; + margin-left: 14px; +} + +.mindmap-inline-detail-line { + width: 18px; + margin-top: 22px; + border-top: 1px solid #8fb8de; +} + +.mindmap-inline-detail-card { + width: 420px; + max-width: 620px; + background: #fff; + border: 1px solid #d9e8f6; + border-radius: 8px; + padding: 10px 12px; + box-shadow: 0 1px 6px rgba(64, 158, 255, 0.12); +} + +.mindmap-inline-detail-title { + color: #303133; + font-weight: 600; +} + +.mindmap-inline-detail-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 8px; +} + +.mindmap-inline-detail-item { + color: #606266; + line-height: 1.6; + margin-bottom: 6px; + white-space: pre-wrap; +} + +.mindmap-inline-detail-item:last-child { + margin-bottom: 0; +} + +.mindmap-inline-actions { + text-align: right; + margin-top: 8px; +} + +.mindmap-node-meta { + display: inline-flex; + align-items: center; + flex-wrap: wrap; + gap: 8px; +} + +.mindmap-meta-text { + color: #909399; + font-size: 12px; +} + +.mindmap-empty { + color: #909399; + text-align: center; + line-height: 220px; +} diff --git a/src/components/TestPlatform/DataFactory/BuilderEditor.vue b/src/components/TestPlatform/DataFactory/BuilderEditor.vue index c41ecfd..239c288 100644 --- a/src/components/TestPlatform/DataFactory/BuilderEditor.vue +++ b/src/components/TestPlatform/DataFactory/BuilderEditor.vue @@ -66,7 +66,7 @@ export default { this.saving = true createBuilder(this.projectId, Object.assign({}, this.form, { definition, input_schema })).then(() => { this.$message({ type: 'success', message: '造数器保存成功' }) - this.$router.push({ path: '/test-platform/data-factory/builders', query: { projectId: this.projectId } }) + this.$router.push({ path: '/data-tools/factory/builders', query: { projectId: this.projectId } }) }).finally(() => { this.saving = false }) diff --git a/src/components/TestPlatform/DataFactory/BuilderList.vue b/src/components/TestPlatform/DataFactory/BuilderList.vue index ec8b05d..4268ba0 100644 --- a/src/components/TestPlatform/DataFactory/BuilderList.vue +++ b/src/components/TestPlatform/DataFactory/BuilderList.vue @@ -72,13 +72,13 @@ export default { }) }, goEditor(row) { - this.$router.push({ path: '/test-platform/data-factory/editor', query: { projectId: this.projectId, builderId: row && row.id } }) + this.$router.push({ path: '/data-tools/factory/editor', query: { projectId: this.projectId, builderId: row && row.id } }) }, goTasks() { - this.$router.push({ path: '/test-platform/data-factory/tasks', query: { projectId: this.projectId } }) + this.$router.push({ path: '/data-tools/factory/task', query: { projectId: this.projectId } }) }, goMock() { - this.$router.push({ path: '/test-platform/data-factory/mock', query: { projectId: this.projectId } }) + this.$router.push({ path: '/data-tools/factory/mock', query: { projectId: this.projectId } }) }, execute(row) { executeBuilder(this.projectId, row.id, { params: { count: 1 }, async: true }).then(() => { diff --git a/src/components/TestPlatform/Plan/PlanBuilder.vue b/src/components/TestPlatform/Plan/PlanBuilder.vue index d5d5852..385e132 100644 --- a/src/components/TestPlatform/Plan/PlanBuilder.vue +++ b/src/components/TestPlatform/Plan/PlanBuilder.vue @@ -1,26 +1,100 @@