From 5570855ec9d9a2bf1aa0fb02aec295f31b33de51 Mon Sep 17 00:00:00 2001
From: hejianhao <15708179461@qq.com>
Date: 星期三, 04 三月 2026 18:18:22 +0800
Subject: [PATCH] fix(审核): 完善审核流程的UI和校验逻辑

---
 /dev/null                                                     |  258 -------------------------------------------
 src/views/service/review/policyApplication/index.vue          |   34 +++++
 src/views/service/review/personnel/index.vue                  |   24 ++-
 src/views/service/review/personnel/components/ReviewModal.vue |   13 ++
 src/views/service/ticket/workOrder/index.vue                  |    4 
 5 files changed, 64 insertions(+), 269 deletions(-)

diff --git a/.trae/rules/project_rules.md b/.trae/rules/project_rules.md
deleted file mode 100644
index 3b43897..0000000
--- a/.trae/rules/project_rules.md
+++ /dev/null
@@ -1,258 +0,0 @@
-## 一、文档管理规范(核心基础)
-
-### 1.1 文档创建时机
-
-新项目开发启动时,**必须优先创建「说明文档.md」**,作为项目全生命周期唯一管理载体。
-
-### 1.2 文档核心内容
-
-需包含**项目规划、实施方案、进度记录**三大模块,且内容需明确、可落地(如进度需标注具体时间节点)。
-
-### 1.3 文档更新要求
-
-* 每次重新打开项目前,**必须先阅读「说明文档.md」**,确认当前进度与要求后再启动开发;
-* 项目计划调整、进度节点变更时,**需即时更新文档对应模块**;
-* 每完成一项工作任务(如一个功能开发、一个 BUG 修复),**需立即在文档进度记录中标记完成并补充结果说明**。
-
-## 二、开发流程规范(过程管控)
-
-### 2.1 任务管理逻辑
-
-采用<MCPsequential thinking>(顺序化思考)分析需求,拆解为可执行的 ToDoList,明确任务优先级与依赖关系。
-
-### 2.2 任务执行闭环
-
-严格按 ToDoList 顺序执行,完成一项任务后,**需在文档及任务清单中标记 “已完成”**,确认无遗留问题后,再启动下一项任务,直至全量完成。
-
-## 三、问题解决规范(技术支撑)
-
-### 3.1 问题处理优先级
-
-开发中遇到技术问题时,**优先通过<MCPContext7>工具查找最新文档、代码示例**,尝试解决问题。
-
-### 3.2 官方文档依赖
-
-若<MCPContext7>未解决问题,**必须查找对应编程语言的官方文档**(如 Python 查Python.org、Java 查 Oracle 官方文档),严禁自行编造代码或解决方案,确保技术方案的准确性与合规性。
-
-## 四、执行约束规范(硬性要求)
-
-### 4.1 三大 “绝不允许” 原则
-
-* **绝不允许项目延期**:严格按文档规划的时间节点执行,提前识别风险并调整计划(需同步更新文档);
-* **绝不允许超出计划**:开发范围、资源投入需严格匹配文档中的项目规划,若需扩容需先更新规划并确认可行性,严禁无规划扩展;
-* **绝不允许出错**:开发过程中需多轮自检(如代码编译检查、功能测试),若出现错误需立即暂停并按问题解决规范处理,修复后需验证无误再推进。
-
-## 五、环境与输出规范(基础保障)
-
-### 5.1 开发环境统一
-
-固定使用 Mac 系统进行 TRAE 编程开发,确保环境一致性,避免跨系统兼容性问题。
-
-### 5.2 代码输出标准
-
-生成代码时,**必须为所有函数添加函数级注释**(需包含功能描述、参数说明、返回值类型及用途),提升代码可读性与可维护性。
-
-# 6A工作流执行规则
-
-## 阶段1: Align (对齐阶段)
-
-### 目标: 模糊需求 → 精确规范
-
-### 执行步骤
-
-1. **项目上下文分析**
-    * 分析现有项目结构、技术栈、架构模式、依赖关系
-    * 分析现有代码模式、现有文档和约定
-    * 理解业务域和数据模型
-2. **需求理解确认**
-    * 创建 `docs/任务名/ALIGNMENT_[任务名].md`
-    * 包含项目和任务特性规范
-    * 包含原始需求、边界确认(明确任务范围)、需求理解(对现有项目的理解)、疑问澄清(存在歧义的地方)
-3. **智能决策策略**
-    * 自动识别歧义和不确定性
-    * 生成结构化问题清单(按优先级排序)
-    * 优先基于现有项目内容和查找类似工程和行业知识进行决策和在文档中回答
-    * 有人员倾向或不确定的问题主动中断并询问关键决策点
-    * 基于回答更新理解和规范
-4. **中断并询问关键决策点**
-    * 主动中断询问,迭代执行智能决策策略
-5. **最终共识**
-    * 生成 `docs/任务名/CONSENSUS_[任务名].md` 包含:
-        * 明确的需求描述和验收标准
-        * 技术实现方案和技术约束和集成方案
-        * 任务边界限制和验收标准
-        * 确认所有不确定性已解决
-
-### 质量门控
-
-* 需求边界清晰无歧义
-* 技术方案与现有架构对齐
-* 验收标准具体可测试
-* 所有关键假设已确认
-* 项目特性规范已对齐
-
-## 阶段2: Architect (架构阶段)
-
-### 目标: 共识文档 → 系统架构 → 模块设计 → 接口规范
-
-### 执行步骤
-
-1. **系统分层设计**
-    * 基于CONSENSUS、ALIGNMENT文档设计架构
-    * 生成 `docs/任务名/DESIGN_[任务名].md` 包含:
-        * 整体架构图(mermaid绘制)
-        * 分层设计和核心组件
-        * 模块依赖关系图
-        * 接口契约定义
-        * 数据流向图
-        * 异常处理策略
-2. **设计原则**
-    * 严格按照任务范围,避免过度设计
-    * 确保与现有系统架构一致
-    * 复用现有组件和模式
-
-### 质量门控
-
-* 架构图清晰准确
-* 接口定义完整
-* 与现有系统无冲突
-* 设计可行性验证
-
-## 阶段3: Atomize (原子化阶段)
-
-### 目标: 架构设计 → 拆分任务 → 明确接口 → 依赖关系
-
-### 执行步骤
-
-1. **子任务拆分**
-    * 基于DESIGN文档生成 `docs/任务名/TASK_[任务名].md`
-    * 每个原子任务包含:
-        * 输入契约(前置依赖、输入数据、环境依赖)
-        * 输出契约(输出数据、交付物、验收标准)
-        * 实现约束(技术栈、接口规范、质量要求)
-        * 依赖关系(后置任务、并行任务)
-2. **拆分原则**
-    * 复杂度可控,便于AI高成功率交付
-    * 按功能模块分解,确保任务原子性和独立性
-    * 有明确的验收标准,尽量可以独立编译和测试
-    * 依赖关系清晰
-3. **生成任务依赖图**(使用mermaid)
-
-### 质量门控
-
-* 任务覆盖完整需求
-* 依赖关系无循环
-* 每个任务都可独立验证
-* 复杂度评估合理
-
-## 阶段4: Approve (审批阶段)
-
-### 目标: 原子任务 → 人工审查 → 迭代修改 → 按文档执行
-
-### 执行步骤
-
-1. **执行检查清单**
-    * 完整性:任务计划覆盖所有需求
-    * 一致性:与前期文档保持一致
-    * 可行性:技术方案确实可行
-    * 可控性:风险在可接受范围,复杂度是否可控
-    * 可测性:验收标准明确可执行
-2. **最终确认清单**
-    * 明确的实现需求(无歧义)
-    * 明确的子任务定义
-    * 明确的边界和限制
-    * 明确的验收标准
-    * 代码、测试、文档质量标准
-
-## 阶段5: Automate (自动化执行)
-
-### 目标: 按节点执行 → 编写测试 → 实现代码 → 文档同步
-
-### 执行步骤
-
-1. **逐步实施子任务**
-    * 创建 `docs/任务名/ACCEPTANCE_[任务名].md` 记录完成情况
-2. **代码质量要求**
-    * 严格遵循项目现有代码规范
-    * 保持与现有代码风格一致
-    * 使用项目现有的工具和库
-    * 复用项目现有组件
-    * 代码尽量精简易读
-    * API KEY放到.env文件中并且不要提交git
-3. **异常处理**
-    * 遇到不确定问题立刻中断执行
-    * 在TASK文档中记录问题详细信息和位置
-    * 寻求人工澄清后继续
-4. **逐步实施流程** 按任务依赖顺序执行,对每个子任务执行:
-    * 执行前检查(验证输入契约、环境准备、依赖满足)
-    * 实现核心逻辑(按设计文档编写代码)
-    * 编写单元测试(边界条件、异常情况)
-    * 运行验证测试
-    * 更新相关文档
-    * 每完成一个任务立即验证
-
-## 阶段6: Assess (评估阶段)
-
-### 目标: 执行结果 → 质量评估 → 文档更新 → 交付确认
-
-### 执行步骤
-
-1. **验证执行结果**
-    * 更新 `docs/任务名/ACCEPTANCE_[任务名].md`
-    * 整体验收检查:
-        * 所有需求已实现
-        * 验收标准全部满足
-        * 项目编译通过
-        * 所有测试通过
-        * 功能完整性验证
-        * 实现与设计文档一致
-2. **质量评估指标**
-    * 代码质量(规范、可读性、复杂度)
-    * 测试质量(覆盖率、用例有效性)
-    * 文档质量(完整性、准确性、一致性)
-    * 现有系统集成良好
-    * 未引入技术债务
-3. **最终交付物**
-    * 生成 `docs/任务名/FINAL_[任务名].md`(项目总结报告)
-    * 生成 `docs/任务名/TODO_[任务名].md`(精简明确哪些待办的事宜和哪些缺少的配置等,我方便直接寻找支持)
-4. **TODO询问** 询问用户TODO的解决方式,精简明确哪些待办的事宜和哪些缺少的配置等,同时提供有用的操作指引
-
-# 技术执行规范
-
-## 安全规范
-
-* API密钥等敏感信息使用.env文件管理
-
-## 文档同步
-
-* 代码变更同时更新相关文档
-
-## 测试策略
-
-* 测试优先:先写测试,后写实现
-* 边界覆盖:覆盖正常流程、边界条件、异常情况
-
-## 交互体验优化
-
-### 进度反馈
-
-* 显示当前执行阶段
-* 提供详细的执行步骤
-* 标示完成情况
-* 突出需要关注的问题
-
-### 异常处理机制
-
-#### 中断条件
-
-* 遇到无法自主决策的问题
-* 觉得需要询问用户的问题
-* 技术实现出现阻塞
-* 文档不一致需要确认修正
-
-#### 恢复策略
-
-* 保存当前执行状态
-* 记录问题详细信息
-* 询问并等待人工干预
-* 从中断点任务继续执行
diff --git a/src/views/service/review/personnel/components/ReviewModal.vue b/src/views/service/review/personnel/components/ReviewModal.vue
index 93d10f4..809f89f 100644
--- a/src/views/service/review/personnel/components/ReviewModal.vue
+++ b/src/views/service/review/personnel/components/ReviewModal.vue
@@ -30,6 +30,17 @@
 const rules: FormRules = {
   result: [
     { required: true, message: '请选择审核结果', trigger: 'change' }
+  ],
+  auditRemarks: [
+    {
+      validator: (_rule, value) => {
+        if (formModel.value.result === 'reject' && (!value || !String(value).trim())) {
+          return new Error('请输入备注')
+        }
+        return true
+      },
+      trigger: ['input', 'blur']
+    }
   ]
 }
 
@@ -83,7 +94,7 @@
         </n-radio-group>
       </n-form-item>
 
-      <n-form-item label="备注" path="auditRemarks">
+      <n-form-item label="备注" path="auditRemarks" :required="formModel.result === 'reject'">
         <n-input
           v-model:value="formModel.auditRemarks"
           type="textarea"
diff --git a/src/views/service/review/personnel/index.vue b/src/views/service/review/personnel/index.vue
index 0e15929..a38f74a 100644
--- a/src/views/service/review/personnel/index.vue
+++ b/src/views/service/review/personnel/index.vue
@@ -49,6 +49,7 @@
 const columns: DataTableColumns<any> = [
   {
     type: "selection",
+    disabled: (row) => row.auditStatus !== 1,
   },
   {
     title: "序号",
@@ -132,8 +133,8 @@
     align: "center",
     render: (row) => {
       if (row.idCardFront && row.idCardBack) {
-        const idCardFront = JSON.parse(row.idCardFront).url
-        const idCardBack = JSON.parse(row.idCardBack).url
+        const idCardFront = JSON.parse(row.idCardFront).url;
+        const idCardBack = JSON.parse(row.idCardBack).url;
         return h("div", { class: "flex gap-1 justify-center" }, [
           h(NImage, {
             width: 60,
@@ -200,7 +201,7 @@
     align: "center",
     render: (row) => {
       if (row.driverLicense) {
-        const driverLicense = JSON.parse(row.driverLicense).url
+        const driverLicense = JSON.parse(row.driverLicense).url;
         return h(NImage, {
           width: 60,
           height: 40,
@@ -235,7 +236,9 @@
     align: "center",
     render: (row) => {
       if (row.certificateOfNoCriminalRecord) {
-        const certificateOfNoCriminalRecord = JSON.parse(row.certificateOfNoCriminalRecord).url
+        const certificateOfNoCriminalRecord = JSON.parse(
+          row.certificateOfNoCriminalRecord
+        ).url;
         return h(NImage, {
           width: 60,
           height: 40,
@@ -262,6 +265,12 @@
         "📷"
       );
     },
+  },
+  {
+    title: "上传时间",
+    key: "createTime",
+    width: 180,
+    align: "center",
   },
   {
     title: "操作",
@@ -338,7 +347,7 @@
     positiveText: "确定",
     negativeText: "取消",
     onPositiveClick: async () => {
-      const res= await deleteQualificationAuditById(id);
+      const res = await deleteQualificationAuditById(id);
       if (res.code === 200) {
         window.$message?.success("删除成功");
         getPersonnelList();
@@ -394,8 +403,9 @@
     if (res.code === 200 && res.data) {
       tableData.value = res.data.records || [];
       tableData.value.forEach((item: any, index: number) => {
-       item.serialNumber = (pagination.value.page - 1) * pagination.value.pageSize + index + 1
-      })
+        item.serialNumber =
+          (pagination.value.page - 1) * pagination.value.pageSize + index + 1;
+      });
       pagination.value.itemCount = res.data.total || 0;
     } else {
       tableData.value = [];
diff --git a/src/views/service/review/policyApplication/index.vue b/src/views/service/review/policyApplication/index.vue
index aeb6591..fcacc98 100644
--- a/src/views/service/review/policyApplication/index.vue
+++ b/src/views/service/review/policyApplication/index.vue
@@ -1,7 +1,7 @@
 <script setup lang="ts">
 import { ref, h, onMounted } from "vue";
 import type { DataTableColumns } from "naive-ui";
-import { NButton, NTag } from "naive-ui";
+import { NButton, NTag, NTooltip } from "naive-ui";
 import { useBoolean } from "@/hooks";
 import {
   batchAuditPolicyApplication,
@@ -58,6 +58,7 @@
 const columns: DataTableColumns<any> = [
   {
     type: "selection",
+    disabled: (row) => row.auditStatus !== 1,
   },
   {
     title: "序号",
@@ -135,6 +136,37 @@
     key: "auditRemarks",
     width: 160,
     align: "center",
+    render: (row) => {
+      const fullText = row.auditRemarks ?? "-";
+      const normalized = String(fullText);
+      const displayText =
+        normalized.length > 200 ? `${normalized.slice(0, 200)}...` : normalized;
+      return h(
+        NTooltip,
+        {
+          placement: "top",
+          trigger: "hover",
+          disabled: normalized.length <= 200,
+        },
+        {
+          trigger: () =>
+            h(
+              "span",
+              {
+                style: {
+                  display: "inline-block",
+                  maxWidth: "160px",
+                  overflow: "hidden",
+                  textOverflow: "ellipsis",
+                  whiteSpace: "nowrap",
+                },
+              },
+              displayText
+            ),
+          default: () => normalized,
+        }
+      );
+    },
   },
   {
     title: "操作",
diff --git a/src/views/service/ticket/workOrder/index.vue b/src/views/service/ticket/workOrder/index.vue
index ea424bb..3807116 100644
--- a/src/views/service/ticket/workOrder/index.vue
+++ b/src/views/service/ticket/workOrder/index.vue
@@ -87,9 +87,9 @@
 };
 
 const statusLabelMap: Record<number, string> = {
-  1: "待处理",
+  1: "未处理",
   2: "处理中",
-  3: "已处理",
+  3: "已完结",
 };
 
 const problemSourceLabelMap: Record<number, string> = {

--
Gitblit v1.7.1