Explorar o código

Merge remote-tracking branch 'origin/dev' into test

lihaiting hai 5 días
pai
achega
ced14afb63

+ 1 - 0
.gitignore

@@ -25,3 +25,4 @@ vue.config.js
 package-lock.json
 .history
 .workbuddy
+AGENTS.md

+ 10 - 10
src/BIZComponents/processSubmitDialog/components/businessComponent.vue

@@ -21,7 +21,7 @@
                 label="出发地">
             </el-table-column>
             <el-table-column
-                prop="endPlace" 
+                prop="endPlace"
                 align="center"
                 label="到达地">
             </el-table-column>
@@ -41,7 +41,7 @@
                 width="100"
                  v-if="!view">
                 <template slot-scope="scope">
-                    <!-- <el-button @click="editRow(scope.row, scope.$index)" type="text" size="mini">编辑</el-button> -->
+                    <el-button @click="editRow(scope.row, scope.$index)" type="text" size="mini">编辑</el-button>
                     <el-button @click="deleteRow(scope.$index)" type="text" size="mini">删除</el-button>
                 </template>
                 </el-table-column>
@@ -129,9 +129,9 @@
                             v-model="form.endPlace"
                         ></el-input>
                     </el-form-item>
-                    <el-form-item 
-                        label="交通方式" 
-                        label-width="80px" 
+                    <el-form-item
+                        label="交通方式"
+                        label-width="80px"
                         prop="transportationWay"
                         :rules="{
                                 required: true,
@@ -250,9 +250,9 @@
                         v-model="row.endPlace"
                     ></el-input>
                 </el-form-item>
-                <el-form-item 
-                    label="交通方式" 
-                    label-width="80px" 
+                <el-form-item
+                    label="交通方式"
+                    label-width="80px"
                     :prop="'blank_business_component.' + $index + '.transportationWay'"
                     :rules="{
                             required: true,
@@ -486,7 +486,7 @@ export default {
                 if(this.type === 'add') {
                     this.tableData.push(newForm);
                 } else {
-                    this.tableData[this.currentIndex] = newForm;
+                    this.$set(this.tableData, this.currentIndex, newForm);
                 }
                 console.log('this.tableData', this.tableData);
                 this.updateRowInfo()
@@ -522,4 +522,4 @@ export default {
     padding-left: 10px;
     padding-right: 10px;
 }
-</style>
+</style>

+ 38 - 34
src/BIZComponents/processSubmitDialog/components/eventComponent.vue

@@ -43,7 +43,7 @@
                 width="100"
                  v-if="!view">
                 <template slot-scope="scope">
-                    <!-- <el-button @click="editRow(scope.row, scope.$index)" type="text" size="mini">编辑</el-button> -->
+                    <el-button @click="editRow(scope.row, scope.$index)" type="text" size="mini">编辑</el-button>
                     <el-button @click="deleteRow(scope.$index)" type="text" size="mini">删除</el-button>
                 </template>
                 </el-table-column>
@@ -84,7 +84,7 @@
                         >
                         </el-date-picker>
                     </el-form-item>
-        
+
                     <el-form-item
                         label="事件发生的医院及科室"
                         label-width="110px"
@@ -103,9 +103,9 @@
                         ></el-input>
                     </el-form-item>
 
-                    <el-form-item 
-                        label="事件详细描述" 
-                        label-width="110px" 
+                    <el-form-item
+                        label="事件详细描述"
+                        label-width="110px"
                         prop="eventDesc"
                     >
                         <el-input
@@ -116,9 +116,9 @@
                         ></el-input>
                     </el-form-item>
 
-                    <el-form-item 
-                        label="图片上传" 
-                        label-width="110px" 
+                    <el-form-item
+                        label="图片上传"
+                        label-width="110px"
                         prop="eventImage"
                         :rules="{
                                 required: true,
@@ -144,9 +144,9 @@
                         </el-upload>
                     </el-form-item>
 
-                    <el-form-item 
-                        label="其他意见" 
-                        label-width="110px" 
+                    <el-form-item
+                        label="其他意见"
+                        label-width="110px"
                         prop="eventOpinion"
                     >
                         <el-input
@@ -267,14 +267,14 @@ export default {
                 this.$message.error(`最多上传 ${this.limit}个文件`);
                 return Promise.reject(new Error('文件数量超出限制'));
             }
-            
+
             // 3. 文件类型校验(虽然accept属性已限制,但这里再做一层校验确保安全性)
             const isImage = /\.(jpg|jpeg|png|gif)$/i.test(file.name);
             if (!isImage) {
                 this.$message.error('请上传图片格式的文件');
                 return Promise.reject(new Error('文件类型不是图片'));
             }
-            
+
             // 4. 执行文件上传
             return uploadFile({
                 module: this.module,
@@ -282,13 +282,13 @@ export default {
             }).then((res) => {
                 if (res.data) {
                     // 将上传成功的文件添加到表单中
-                    const uploadedFile = { 
-                        ...file, 
-                        url: res.data.storePath, 
+                    const uploadedFile = {
+                        ...file,
+                        url: res.data.storePath,
                         ...res.data,
                         status: 'success' // 标记为成功状态
                     };
-                    
+
                     // 检查文件是否已存在,避免重复添加
                     const existingIndex = this.form.eventImage.findIndex(item => item.uid === file.uid);
                     if (existingIndex === -1) {
@@ -296,7 +296,7 @@ export default {
                     } else {
                         this.form.eventImage.splice(existingIndex, 1, uploadedFile);
                     }
-                    
+
                     return res.data;
                 }
                 return Promise.reject(new Error('上传失败,未返回数据'));
@@ -307,6 +307,10 @@ export default {
         },
         beforeRemove (file) {
             if (file.id) {
+                // 原明细仍可能被取消编辑或被流程引用,编辑时仅移除草稿中的引用。
+                if (this.type === 'edit' && (this.currentItem.eventImage || []).some(item => item.id === file.id)) {
+                    return true;
+                }
                 return removeFile({
                     fileId: file.id
                 }).then(() => {
@@ -370,50 +374,50 @@ export default {
             try {
                 // 1. 先进行表单基本验证
                 await this.validateForm();
-                
+
                 // 2. 额外验证图片上传是否有效
                 // if (!this.form.eventImage || this.form.eventImage.length === 0) {
                 //     this.$message.error('请上传图片');
                 //     return;
                 // }
-                
+
                 // // 3. 检查是否有上传中的图片或上传失败的图片
-                // const hasInvalidFile = this.form.eventImage.some(file => 
+                // const hasInvalidFile = this.form.eventImage.some(file =>
                 //     file.status === 'uploading' || file.status === 'fail'
                 // );
-                
+
                 // if (hasInvalidFile) {
                 //     this.$message.error('存在图片正在上传中或上传失败,请等待上传完成或重新上传');
                 //     return;
                 // }
-                
+
                 // console.log('表单验证通过,图片上传有效');
-                
+
                 // 4. 深拷贝form对象,避免引用问题
                 const newForm = JSON.parse(JSON.stringify(this.form));
-                
+
                 // 5. 过滤出有效的图片数据(只保留成功上传的图片)
-                newForm.eventImage = newForm.eventImage.filter(file => 
+                newForm.eventImage = newForm.eventImage.filter(file =>
                     file.status === 'success' && file.url
                 );
-                
+
                 console.log('newForm', newForm);
-                
+
                 // 6. 更新表格数据
                 if(this.type === 'add') {
                     this.tableData.push(newForm);
                 } else {
-                    this.tableData[this.currentIndex] = newForm;
+                    this.$set(this.tableData, this.currentIndex, newForm);
                 }
-                
+
                 console.log('this.tableData', this.tableData);
-                
+
                 // 7. 更新父组件数据
                 this.updateRowInfo();
-                
+
                 // 8. 保存成功后关闭弹窗并重置表单
                 this.handleClose();
-                
+
                 // 重置form
                 // this.form = {
                 //     eventType: '',
@@ -453,4 +457,4 @@ export default {
     padding-left: 10px;
     padding-right: 10px;
 }
-</style>
+</style>

+ 7 - 7
src/BIZComponents/processSubmitDialog/components/productSpecificationComponent.vue

@@ -26,7 +26,7 @@
                 width="100"
                  v-if="!view">
                 <template slot-scope="scope">
-                    <!-- <el-button @click="editRow(scope.row, scope.$index)" type="text" size="mini">编辑</el-button> -->
+                    <el-button @click="editRow(scope.row, scope.$index)" type="text" size="mini">编辑</el-button>
                     <el-button @click="deleteRow(scope.$index)" type="text" size="mini">删除</el-button>
                 </template>
                 </el-table-column>
@@ -63,7 +63,7 @@
                             placeholder="请输入"
                         ></el-input>
                     </el-form-item>
-        
+
                     <el-form-item
                         label="数量"
                         label-width="110px"
@@ -79,9 +79,9 @@
                             placeholder="请输入"
                         ></el-input>
                     </el-form-item>
-                    <el-form-item 
-                        label="批号" 
-                        label-width="110px" 
+                    <el-form-item
+                        label="批号"
+                        label-width="110px"
                         prop="batchNo"
                         :rules="{
                                 required: true,
@@ -257,7 +257,7 @@ export default {
                 if(this.type === 'add') {
                     this.tableData.push(newForm);
                 } else {
-                    this.tableData[this.currentIndex] = newForm;
+                    this.$set(this.tableData, this.currentIndex, newForm);
                 }
                 console.log('this.tableData', this.tableData);
                 this.updateRowInfo()
@@ -294,4 +294,4 @@ export default {
     padding-left: 10px;
     padding-right: 10px;
 }
-</style>
+</style>

+ 17 - 17
src/BIZComponents/processSubmitDialog/components/reissueComponent.vue

@@ -31,7 +31,7 @@
                 width="100"
                  v-if="!view">
                 <template slot-scope="scope">
-                    <!-- <el-button @click="editRow(scope.row, scope.$index)" type="text" size="mini">编辑</el-button> -->
+                    <el-button @click="editRow(scope.row, scope.$index)" type="text" size="mini">编辑</el-button>
                     <el-button @click="deleteRow(scope.$index)" type="text" size="mini">删除</el-button>
                 </template>
                 </el-table-column>
@@ -72,7 +72,7 @@
                             </el-option>
                         </el-select>
                     </el-form-item>
-        
+
                     <el-form-item
                         label="补发其他规格型号"
                         label-width="110px"
@@ -85,9 +85,9 @@
                             :autosize="{ minRows: 2, maxRows: 4}"
                         ></el-input>
                     </el-form-item>
-                    <el-form-item 
-                        label="收件地址/联系人/电话" 
-                        label-width="110px" 
+                    <el-form-item
+                        label="收件地址/联系人/电话"
+                        label-width="110px"
                         prop="reissueContact"
                         :rules="{
                                 required: true,
@@ -102,9 +102,9 @@
                             :autosize="{ minRows: 2, maxRows: 4}"
                         ></el-input>
                     </el-form-item>
-                    <el-form-item 
-                        label="其他要求" 
-                        label-width="110px" 
+                    <el-form-item
+                        label="其他要求"
+                        label-width="110px"
                         prop="reissueOtherReq"
                     >
                         <el-input
@@ -230,31 +230,31 @@ export default {
             this.tableData.splice(index, 1);
             this.updateRowInfo();
         },
-   
+
         async save() {
             try {
                 // 执行表单验证
                 await this.validateForm();
                 console.log('表单验证通过');
-                
+
                 // 深拷贝form对象,避免引用问题
                 const newForm = JSON.parse(JSON.stringify(this.form));
-                
+
                 // 根据操作类型更新表格数据
                 if(this.type === 'add') {
                     this.tableData.push(newForm);
                 } else if (this.currentIndex !== null && this.currentIndex !== undefined) {
-                    this.tableData[this.currentIndex] = newForm;
+                    this.$set(this.tableData, this.currentIndex, newForm);
                 }
-                
+
                 console.log('this.tableData', this.tableData);
-                
+
                 // 更新父组件数据
                 this.updateRowInfo();
-                
+
                 // 保存后关闭弹窗
                 this.handleClose();
-                
+
                 // 重置form为初始状态,使用formItem作为模板
                 this.form = JSON.parse(JSON.stringify(this.formItem));
             } catch (error) {
@@ -288,4 +288,4 @@ export default {
     padding-left: 10px;
     padding-right: 10px;
 }
-</style>
+</style>

+ 15 - 0
src/api/hr/index.js

@@ -964,6 +964,21 @@ export const renewContract = async (id, data) =>
   unwrap(await request.post(`/hr/contracts/${id}/renew`, data));
 export const terminateContract = async (id, data) =>
   unwrap(await request.post(`/hr/contracts/${id}/termination`, data));
+/**
+ * 查询合同审批完整详情 GET /hr/contracts/approval-detail
+ * 审批中心(本系统)查看合同详情专用:服务端按 businessId + businessKey 解析原合同主键,
+ * 前端不需要知道合同 id,也不需要从流程变量里猜。
+ *  - businessKey = hr_contract_approval           businessId = 合同主键(签订 / 续签)
+ *  - businessKey = hr_contract_change_approval     businessId = 变更单主键
+ *  - businessKey = hr_contract_termination_approval businessId = 解除终止单主键
+ * 响应 = 劳动合同完整档案(与 GET /hr/contracts/{id} 同模型,含 changes / terminations 台账)。
+ */
+export const getContractApprovalDetail = async (businessId, businessKey) =>
+  unwrap(
+    await request.get("/hr/contracts/approval-detail", {
+      params: compact({ businessId, businessKey }),
+    })
+  );
 export const archiveContractOffline = async (id, data) =>
   unwrap(await request.post(`/hr/contracts/${id}/offline/archive`, data));
 export const voidContract = async (id, data) =>

+ 76 - 76
src/views/bpm/handleTask/components/hrChangeContractManagement/hrChangeContractDetail.vue

@@ -20,8 +20,8 @@
             </div>
             <div class="cm-compare-item is-span-2">
               <span class="cm-compare-label">合同附件:</span><span class="cm-compare-value">
-                <fileMain v-if="detailRow.attachmentFileIds.length" :value="detailRow.attachmentFileIds" type="view"
-                  size="small" />
+                <fileMain v-if="detailRow.beforeAttachmentFileIds.length" :value="detailRow.beforeAttachmentFileIds"
+                  type="view" size="small" />
                 <span v-else class="cm-detail-muted">暂无附件</span>
               </span>
             </div>
@@ -37,8 +37,8 @@
             </div>
             <div class="cm-compare-item is-span-2">
               <span class="cm-compare-label">合同附件:</span><span class="cm-compare-value">
-                <fileMain v-if="detailRow.attachmentFileIds.length" :value="detailRow.attachmentFileIds" type="view"
-                  size="small" />
+                <fileMain v-if="detailRow.afterAttachmentFileIds.length" :value="detailRow.afterAttachmentFileIds"
+                  type="view" size="small" />
                 <span v-else class="cm-detail-muted">暂无附件</span>
               </span>
             </div>
@@ -80,16 +80,29 @@
 </template>
 
 <script>
-import { getContractById } from '@/api/hr';
-import { getProcessInstance } from '@/api/bpm/processInstance';
+import { getContractApprovalDetail } from '@/api/hr';
 import { parseAttachmentIds } from '@/utils/attachment';
 
+/** 本组件只服务「劳动合同变更审批」,businessKey 固定 */
+const CHANGE_BUSINESS_KEY = 'hr_contract_change_approval';
+
 /** 签署方式:ONLINE-审批待办附件盖章签字;OFFLINE-线下签署 */
 const SIGNING_METHOD_LABELS = {
   ONLINE: '线上',
   OFFLINE: '线下'
 };
 
+/** 变更单业务状态(DRAFT/PENDING_APPROVAL/SIGNING/EFFECTIVE/REJECTED/CANCELLED):
+    后端 changeStatusName 缺失时按已知编码翻中文,未知编码原样回显 */
+const CHANGE_STATUS_LABELS = {
+  DRAFT: '草稿',
+  PENDING_APPROVAL: '审批中',
+  SIGNING: '签署中',
+  EFFECTIVE: '已生效',
+  REJECTED: '已驳回',
+  CANCELLED: '已取消'
+};
+
 /** 对比字段:快照字段名与合同顶层字段同名,缺失时逐层回退 */
 const FIELD_DEFS = [
   { key: 'employeeName', label: '签订员工' },
@@ -118,9 +131,19 @@ function parseSnapshot(raw) {
   }
 }
 
+/** 快照日期可能是秒(10 位)/毫秒(13 位)时间戳或日期串 → 统一转本地时区 YYYY-MM-DD */
 function formatDate(value) {
   if (!value) return '';
-  return String(value).slice(0, 10);
+  const str = String(value).trim();
+  if (/^\d{10}$/.test(str)) return tsToYMD(Number(str) * 1000);
+  if (/^\d{13}$/.test(str)) return tsToYMD(Number(str));
+  return str.slice(0, 10);
+}
+
+function tsToYMD(ms) {
+  const d = new Date(ms);
+  const pad = (n) => String(n).padStart(2, '0');
+  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
 }
 
 function formatSalary(value) {
@@ -140,12 +163,13 @@ function formatProbation(value) {
 export default {
   name: 'HrChangeContractDetail',
   props: {
+    /** 流程业务主键:变更审批即变更单主键(不是合同主键) */
     businessId: {
       default: ''
     },
-    /** 流程实例 id:用于从流程变量里补取合同 id */
-    id: {
-      default: ''
+    /** 业务标识,默认取本组件对应的流程 */
+    businessKey: {
+      default: CHANGE_BUSINESS_KEY
     }
   },
   data() {
@@ -170,17 +194,22 @@ export default {
     }
   },
   methods: {
+    /**
+     * 审批详情统一走 GET /hr/contracts/approval-detail:
+     * 服务端按 businessKey + businessId(变更单主键)解析出原合同,返回合同完整档案(含 changes 台账)。
+     * 前端不再用变更单 id 去猜合同 id,也不再从流程变量里补取。
+     */
     async getInfo(businessId) {
       if (!businessId) return;
       this.loading = true;
       try {
-        let contract = await this.fetchContract(businessId);
-        // businessId 可能是变更单 id(不是合同 id):拿到的不对时从流程变量补取合同 id
-        if (!contract || String(contract.id) !== String(businessId)) {
-          const contractId = await this.resolveContractIdFromProcess();
-          if (contractId) contract = await this.fetchContract(contractId);
+        const contract = await getContractApprovalDetail(
+          businessId,
+          this.businessKey
+        );
+        if (!contract) {
+          throw new Error('未获取到合同信息,请后端确认审批详情的返回');
         }
-        if (!contract) throw new Error('未获取到合同信息');
         this.detailRow = this.adaptChange(contract, businessId);
       } catch (e) {
         this.detailRow = null;
@@ -189,63 +218,19 @@ export default {
         this.loading = false;
       }
     },
-    async fetchContract(id) {
-      try {
-        return (await getContractById(id)) || null;
-      } catch (e) {
-        return null;
-      }
-    },
-    /**
-     * 从流程变量补取合同 id(项目内既有做法,见 api/hr/attendanceApply.js)。
-     * 兼容常见变量命名,并打印变量内容便于确认后端实际下发的字段名。
-     */
-    async resolveContractIdFromProcess() {
-      if (!this.id) return '';
-      try {
-        const instance = await getProcessInstance(this.id);
-        const raw = instance && instance.formVariables;
-        const vars = typeof raw === 'string' ? parseSnapshot(raw) : raw || {};
-        // eslint-disable-next-line no-console
-        console.log('[HrChangeContractDetail] 流程变量 formVariables:', vars);
-        const candidates = [
-          vars.contractId,
-          vars.contract_id,
-          vars.contractPrimaryKey,
-          vars.businessContractId,
-          vars.contract && vars.contract.id
-        ];
-        const hit = candidates.find((item) => item != null && item !== '');
-        return hit != null ? String(hit) : '';
-      } catch (e) {
-        return '';
-      }
-    },
-    /**
-     * 合同详情接口返回该合同全部变更记录(changes),定位本条审批对应的变更:
-     * ① 传入的 businessId(后端流程 businessKey 实际存的是变更单 id)
-     * ② contract.changeId
-     * ③ 审批中/签署中的那条
-     * ④ 最新一条
-     */
-    adaptChange(contract = {}, changeIdHint = '') {
+    /** 在合同变更台账里按 businessId(=变更单主键)精确取本条变更,取不到直接报错,不猜 */
+    adaptChange(contract = {}, changeId = '') {
       const list = Array.isArray(contract.changes) ? contract.changes : [];
-      const pendingStatuses = ['PENDING_APPROVAL', 'SIGNING'];
-      const record =
-        list.find((item) => String(item.id) === String(changeIdHint)) ||
-        list.find((item) => String(item.id) === String(contract.changeId)) ||
-        list.find((item) =>
-          pendingStatuses.includes(
-            String(item.changeStatus || '').toUpperCase()
-          )
-        ) ||
-        list[0] ||
-        {};
-      const before = {
-        ...this.contractSnapshot(contract),
-        ...parseSnapshot(record.beforeSnapshot)
-      };
-      const after = { ...before, ...parseSnapshot(record.afterSnapshot) };
+      const record = list.find((item) => String(item.id) === String(changeId));
+      if (!record) {
+        throw new Error(
+          `合同变更台账中未找到变更单(id: ${changeId}),请后端确认 approval-detail 是否返回该变更单`
+        );
+      }
+      const beforeSnapshot = parseSnapshot(record.beforeSnapshot);
+      const afterSnapshot = parseSnapshot(record.afterSnapshot);
+      const before = { ...this.contractSnapshot(contract), ...beforeSnapshot };
+      const after = { ...before, ...afterSnapshot };
       const normalize = (snap) => ({
         employeeName: snap.employeeName || '',
         contractNo: snap.contractNo || '',
@@ -262,7 +247,7 @@ export default {
         endDate: formatDate(snap.endDate),
         signingMethodText:
           SIGNING_METHOD_LABELS[
-          String(snap.signingMethod || '').toUpperCase()
+            String(snap.signingMethod || '').toUpperCase()
           ] ||
           snap.signingMethodName ||
           snap.signingMethod ||
@@ -282,15 +267,30 @@ export default {
         contractNo: contract.contractNo || beforeView.contractNo,
         beforeFields: buildFields(beforeView, null),
         afterFields: buildFields(afterView, beforeView),
-        attachmentFileIds: parseAttachmentIds(contract),
+        /** 原合同附件:合同档案 + 变更前快照 */
+        beforeAttachmentFileIds: parseAttachmentIds({
+          ...contract,
+          ...beforeSnapshot
+        }),
+        /** 变更后附件:变更单顶层 attachmentIds 与变更后快照合并,快照优先 */
+        afterAttachmentFileIds: parseAttachmentIds({
+          ...record,
+          ...afterSnapshot
+        }),
         changeNo: record.changeNo || '',
         changeTypeText: record.changeTypeName || record.changeType || '-',
-        changeStatusText: record.changeStatusName || record.changeStatus || '-',
+        changeStatusText:
+          record.changeStatusName ||
+          CHANGE_STATUS_LABELS[
+            String(record.changeStatus || '').toUpperCase()
+          ] ||
+          record.changeStatus ||
+          '-',
         effectiveDate: formatDate(record.effectiveDate),
         changeReason: record.changeReason || ''
       };
     },
-    /** 合同顶层快照字段:作为变更前快照的兜底来源 */
+    /** 合同顶层快照字段:变更前快照里没有的字段,用合同当前值补齐对比基准 */
     contractSnapshot(contract) {
       return {
         employeeName: contract.employeeName,

+ 12 - 3
src/views/bpm/handleTask/components/hrContractManagement/hrContractDetail.vue

@@ -171,7 +171,7 @@
 
 <script>
 import {
-  getContractById,
+  getContractApprovalDetail,
   adaptContractFlowSignNodes,
   contractSigningStatusLabel,
   contractStatusLabel,
@@ -180,6 +180,9 @@ import {
 } from '@/api/hr';
 import { parseAttachmentIds } from '@/utils/attachment';
 
+/** 本合同详情组件只服务「劳动合同签订/续签审批」,businessKey 固定 */
+const CONTRACT_BUSINESS_KEY = 'hr_contract_approval';
+
 const CONTRACT_TYPES = [
   { value: 'FIXED', label: '固定期限劳动合同' },
   { value: 'NON_FIXED', label: '无固定期限劳动合同' },
@@ -266,8 +269,13 @@ function adaptContract(item = {}) {
 export default {
   name: 'HrContractDetail',
   props: {
+    /** 流程业务主键:签订/续签审批即合同主键 */
     businessId: {
       default: ''
+    },
+    /** 业务标识,默认取本组件对应的流程 */
+    businessKey: {
+      default: CONTRACT_BUSINESS_KEY
     }
   },
   data() {
@@ -299,8 +307,9 @@ export default {
       if (!id) return;
       this.loading = true;
       try {
-        const detail = await getContractById(id);
-        this.detailRow = adaptContract(detail || {});
+        const detail = await getContractApprovalDetail(id, this.businessKey);
+        if (!detail) throw new Error('未获取到合同详情,请后端确认审批详情的返回');
+        this.detailRow = adaptContract(detail);
       } catch (e) {
         this.detailRow = null;
         this.$message.error(e.message || '合同详情加载失败');

+ 26 - 12
src/views/bpm/handleTask/components/hrRemoveContractManagement/hrRemoveContractDetail.vue

@@ -70,10 +70,13 @@
 </template>
 
 <script>
-import { getContractById } from '@/api/hr';
+import { getContractApprovalDetail } from '@/api/hr';
 import { getByCode } from '@/api/system/dictionary-data';
 import { parseAttachmentIds } from '@/utils/attachment';
 
+/** 本组件只服务「劳动合同解除终止审批」,businessKey 固定 */
+const TERMINATION_BUSINESS_KEY = 'hr_contract_termination_approval';
+
 /** 业务类型:接口参数为 TERMINATE / END(见劳动合同解除终止接口) */
 const TERMINATION_TYPE_LABELS = {
   TERMINATE: '解除',
@@ -113,8 +116,13 @@ function pickTerminationFileIds(record = {}) {
 export default {
   name: 'HrRemoveContractDetail',
   props: {
+    /** 流程业务主键:解除终止审批即解除终止单主键(不是合同主键) */
     businessId: {
       default: ''
+    },
+    /** 业务标识,默认取本组件对应的流程 */
+    businessKey: {
+      default: TERMINATION_BUSINESS_KEY
     }
   },
   data() {
@@ -146,8 +154,11 @@ export default {
       // 原因编码字典单独拉取,失败不影响详情展示
       this.loadTerminationReasons();
       try {
-        const detail = await getContractById(id);
-        this.detailRow = this.adaptTermination(detail || {});
+        const contract = await getContractApprovalDetail(id, this.businessKey);
+        if (!contract) {
+          throw new Error('未获取到合同信息,请后端确认审批详情的返回');
+        }
+        this.detailRow = this.adaptTermination(contract, id);
       } catch (e) {
         this.detailRow = null;
         this.$message.error(e.message || '解除/终止详情加载失败');
@@ -156,19 +167,22 @@ export default {
       }
     },
     /**
-     * 合同详情接口返回该合同全部解除/终止记录(按创建时间倒序)。
-     * 审批单对应的是「最近一次解除终止单」terminationId,取不到时退回最新一条。
+     * 审批详情统一走 GET /hr/contracts/approval-detail:
+     * 服务端按 businessKey + businessId(解除终止单主键)解析出原合同,
+     * 返回合同完整档案(含 terminations 台账),前端按主键精确取本条解除单。
      */
-    adaptTermination(contract = {}) {
+    adaptTermination(contract = {}, terminationId = '') {
       const list = Array.isArray(contract.terminations)
         ? contract.terminations
         : [];
-      const record =
-        list.find(
-          (item) => String(item.id) === String(contract.terminationId)
-        ) ||
-        list[0] ||
-        {};
+      const record = list.find(
+        (item) => String(item.id) === String(terminationId)
+      );
+      if (!record) {
+        throw new Error(
+          `合同的解除终止台账中未找到解除单(id: ${terminationId}),请后端确认 approval-detail 是否返回该解除单`
+        );
+      }
       return {
         id: record.id ?? '',
         employeeName: contract.employeeName || '',

+ 1 - 1
src/views/bpm/handleTask/components/saleOrder/accountstatement/accountDetailTable.vue

@@ -382,7 +382,7 @@
           },
           {
             minWidth: 80,
-            prop: 'color',
+            prop: 'colorKey',
             label: '颜色',
             align: 'center',
             showOverflowTooltip: true

+ 1 - 1
src/views/bpm/handleTask/components/saleOrder/accountstatement/page.vue

@@ -82,7 +82,7 @@ export default {
       dataForm: {
         sourceType: '',
         dateType: '',
-        queryDimension: '',
+        queryDimension: 1,
         dateValue: '',
         contactId: '',
         contactName: '',

+ 2 - 2
vue.config.js

@@ -44,9 +44,9 @@ module.exports = {
         // target: 'http://192.168.1.251:18186',
         // target: 'http://192.168.1.251:18086',
         // target: 'http://192.168.1.3:18086',
-        // target: 'http://aiot.zoomwin.com.cn:51001/api',
+        target: 'http://aiot.zoomwin.com.cn:51001/api',
         // target: 'http://192.168.1.3:18086',
-        target: 'http://192.168.1.147:18086', // 陈兵
+        // target: 'http://192.168.1.147:18086', // 陈兵
         // target: 'http://192.168.1.116:18086', // 赵沙金
         // target: 'http://192.168.1.113:18086', // 郭丹