Переглянути джерело

fix: 修改bug,还有成本核定

shiyanyu 3 тижнів тому
батько
коміт
642212d81b

+ 9 - 0
src/api/costFormManage.js

@@ -91,6 +91,15 @@ export function getCostFormDataStorageTables(data) {
 }
 
 // 添加成本核定表模板
+
+// 根据任务ID获取核定模板创建信息(createmode/createtemplateid)
+export function getCostVerifyTemplateDetailByTaskId(params) {
+  return request({
+    url: `${url}/costVerifyTemplate/v1/getDetailByTaskId`,
+    method: 'get',
+    params,
+  })
+}
 export function addCostVerifyForm(data) {
   return request({
     url: `${url}/costVerifyTemplate/v1/save`,

+ 3 - 3
src/views/EntDeclaration/auditTaskManagement/taskFillIn.vue

@@ -985,7 +985,7 @@
         // 可选:直接打开补充材料弹窗
         if (options && options.openMaterialDialog) {
           this.getTaskRequirementPage()
-          this.materialDialogVisible = true
+          // this.materialDialogVisible = true
         }
       },
       // 关闭弹窗方法
@@ -1836,7 +1836,7 @@
             // 设置 loading 状态
             this.loading.materialSubmit = true
             // 这里可以添加提交逻辑
-            console.log('补充材料表单数据:', this.materialForm)
+            // console.log('补充材料表单数据:', this.materialForm)
             addOrUpdateTaskRequirement({
               taskId: this.taskId,
               projectId: this.projectId,
@@ -1848,7 +1848,7 @@
               templateId: this.materialForm.templateId,
             })
               .then((res) => {
-                console.log('补充材料提交成功', res)
+                // console.log('补充材料提交成功', res)
                 if (res && res.code === 200) {
                   this.loading.materialSubmit = false
                   Message.success('补充材料提交成功')

+ 9 - 5
src/views/costAudit/auditInfo/auditManage/collectiveMain.vue

@@ -256,10 +256,14 @@
                 :file-list="fileList"
                 accept=".doc,.docx,.pdf"
               >
-                <el-button size="small" type="primary">选择文件</el-button>
-                <div slot="tip" class="el-upload__tip">
-                  只能上传doc、docx、pdf格式文件
-                </div>
+                <el-tooltip
+                  effect="dark"
+                  placement="top"
+                  :open-delay="200"
+                  content="仅支持 doc/docx/pdf,最多1个,单个≤50MB"
+                >
+                  <el-button size="small" type="primary">选择文件</el-button>
+                </el-tooltip>
               </el-upload>
               <div v-if="fileList.length > 0" class="file-name">
                 <a
@@ -688,7 +692,7 @@
             key: 1,
             // sendType: sendTypeStr,
             content: this.additionalParams.content,
-            childTaskId: childTaskId,
+            auditedUnitIds: childTaskId,
           }
 
           const response = await getReviewTask(params)

+ 424 - 55
src/views/costAudit/auditInfo/auditManage/costAudit.vue

@@ -65,7 +65,7 @@
         </el-row>
       </el-form>
       <el-button
-        v-if="!auditForm.surveyTemplateId"
+        v-if="!hasUploadData"
         type="primary"
         size="small"
         :loading="loading"
@@ -73,7 +73,12 @@
       >
         生成核定表
       </el-button>
-      <el-button type="primary" size="small" @click="handleSaveTemplate">
+      <el-button
+        v-if="!hasUploadData"
+        type="primary"
+        size="small"
+        @click="handleSaveTemplate"
+      >
         保存核定模版
       </el-button>
       <el-button type="primary" size="small" @click="handleExportTemplate">
@@ -252,6 +257,7 @@
         </template>
       </el-table-column>
       <el-table-column
+        v-if="!hasUploadData"
         prop="action"
         label="操作"
         width="100"
@@ -268,6 +274,7 @@
             <i class="el-icon el-icon-circle-plus"></i>
           </el-button>
           <el-button
+            v-if="scope.row.parentid != '-1'"
             type="text"
             title="删除行"
             @click="handleDeleteItem(scope.row)"
@@ -287,6 +294,7 @@
     getActiveCostVerifyFormList,
     getActiveCostVerifyFormListByType,
     getCostFormVersionsByTemplateId,
+    getCostVerifyTemplateDetailByTaskId,
     batchSaveOrUpdate,
   } from '@/api/costFormManage'
   import {
@@ -370,6 +378,11 @@
         // 成本审核数据
         costAuditData: [],
         project: {},
+        // 是否已有上传数据(用于控制“生成核定表”按钮显示隐藏)
+        hasUploadData: false,
+        // 防重与去重:避免重复请求 getSurveyDetail
+        echoInProgress: false,
+        lastEchoSignature: '',
         // 年份到各列prop的映射
         yearPropMap: {},
         // 字典缓存(当未使用 dictMixin 批量加载时备用)
@@ -386,7 +399,198 @@
         return cols.filter((c) => c && c.showVisible !== '0')
       },
     },
+    watch: {
+      // 直接监听最终的模板ID:一旦有值(或变更),拉取最新版本数据回显
+      'auditForm.surveyTemplateId'(val) {
+        if (
+          val &&
+          !this._loadingTemplate &&
+          val !== this._lastLoadedTemplateId
+        ) {
+          this.loadTemplateDataForEdit(val)
+        }
+      },
+      // 选择“根据调查表生成”时,选择了 dataTable 就将其作为当前模板ID并回显
+      'auditForm.dataTable'(val) {
+        if (this.auditForm && this.auditForm.templateType === '1' && val) {
+          this.auditForm.surveyTemplateId = val
+        }
+      },
+      // 选择“根据历史核定模板”时,选择了 historyTemplate 就将其作为当前模板ID并回显
+      'auditForm.historyTemplate'(val) {
+        if (this.auditForm && this.auditForm.templateType === '2' && val) {
+          this.auditForm.surveyTemplateId = val
+        }
+      },
+    },
+    mounted() {
+      // 进入页签时,不论是否已有ID,都尝试解析并加载一次
+      this.getDetail()
+    },
+    activated() {
+      // keep-alive 场景下,激活时同样尝试解析并加载
+      this.getDetail()
+    },
     methods: {
+      // 尝试从多来源解析模板ID
+      _resolveTemplateId() {
+        // 1) 优先:已确定的 surveyTemplateId
+        if (this.auditForm && this.auditForm.surveyTemplateId)
+          return this.auditForm.surveyTemplateId
+        // 2) 根据当前来源选择项
+        if (
+          this.auditForm &&
+          this.auditForm.templateType === '1' &&
+          this.auditForm.dataTable
+        )
+          return this.auditForm.dataTable
+        if (
+          this.auditForm &&
+          this.auditForm.templateType === '2' &&
+          this.auditForm.historyTemplate
+        )
+          return this.auditForm.historyTemplate
+        // 3) 从选中项目中兜底
+        const sp = this.selectedProject || {}
+        if (sp.surveyTemplateId || sp.surveytemplateid)
+          return sp.surveyTemplateId || sp.surveytemplateid
+        if (sp.templateId || sp.templateid)
+          return sp.templateId || sp.templateid
+        // 4) 其他可能传入的字段(尽量不报错)
+        if (sp.costSurveyTemplateId) return sp.costSurveyTemplateId
+        return ''
+      },
+      // 供父组件在切到“成本审核”标签时调用,按照当前模板ID拉取版本并回显
+      async getDetail() {
+        // 1) 优先通过 taskId 获取 createmode/createtemplateid,然后按模板ID加载,满足“先调 getDetailByTaskId 再调版本并回显”
+        const loadedByTask = await this.loadFromTaskId()
+        if (loadedByTask) return
+
+        // 2) 按需:不带模板ID直接拉一次版本列表,满足“直接调”要求
+        await this.loadVersionsWithoutId()
+
+        // 然后再尝试解析模板ID以获取表头+更完整的数据(若可用)
+        let id = this._resolveTemplateId()
+        if (!id) {
+          // 兜底:尝试取一个启用的核定模板作为展示
+          try {
+            const res = await getActiveCostVerifyFormList()
+            const list = Array.isArray(res?.value) ? res.value : []
+            const first = list && list[0]
+            id =
+              (first &&
+                (first.surveyTemplateId || first.templateId || first.id)) ||
+              ''
+            if (id && this.auditForm) this.auditForm.surveyTemplateId = id
+          } catch (e) {
+            // ignore
+          }
+        }
+        if (id) await this.loadTemplateDataForEdit(id)
+      },
+      // 先通过任务ID获取模板创建信息,再按模板ID加载版本与表头,实现“先调 getDetailByTaskId 再调 listByTemplateId 并回显”
+      async loadFromTaskId() {
+        try {
+          const taskId =
+            (this.selectedProject && this.selectedProject.taskId) ||
+            this.id ||
+            ''
+          console.log('[CostAudit] loadFromTaskId called with taskId:', taskId)
+          if (!taskId) return false
+          const res = await getCostVerifyTemplateDetailByTaskId({ id: taskId })
+          console.log('[CostAudit] getDetailByTaskId response:', res)
+          if (!res || res.code !== 200) return false
+          const v = res.value || {}
+          // 兼容不同字段命名:createTemplateId/createMode 或 createtemplateid/createmode
+          const createMode = v.createMode != null ? v.createMode : v.createmode
+          // 生成模板依赖模型id(用于UI来源选择的回显)
+          const createTemplateId =
+            v.createTemplateId ||
+            v.createtemplateid ||
+            v.templateId ||
+            v.templateid ||
+            ''
+          // 用于版本/表头查询的 surveyTemplateId,优先取接口直接返回
+          const surveyTplId = v.surveyTemplateId || v.surveytemplateid || ''
+          // 若拿到模板ID,则记录并按模板ID完整加载(表头+数据+版本)
+          if (createTemplateId || surveyTplId) {
+            console.log('[CostAudit] resolved template from task:', {
+              createTemplateId,
+              surveyTplId,
+              createMode,
+            })
+            if (this.auditForm) {
+              // 后续版本/表头请求一律使用 surveyTemplateId(若缺失则回退到 createTemplateId)
+              this.auditForm.surveyTemplateId = surveyTplId || createTemplateId
+              if (createMode != null) {
+                // 回显来源类型:1 固定表(成本调查表),2 历史成本审核表
+                const modeStr = String(createMode)
+                this.auditForm.templateType = modeStr
+                // 先加载对应下拉选项,再设置选中值,保证界面能正确显示中文标签
+                if (modeStr === '1') {
+                  try {
+                    await this.loadSurveyFormOptions()
+                  } catch (e) {}
+                  this.auditForm.dataTable = createTemplateId
+                  this.auditForm.historyTemplate = ''
+                } else if (modeStr === '2') {
+                  try {
+                    await this.loadHistoryTemplateOptions()
+                  } catch (e) {}
+                  this.auditForm.historyTemplate = createTemplateId
+                  this.auditForm.dataTable = ''
+                }
+              }
+            }
+            // 使用 watcher 触发加载,避免与 watcher 重复调用
+            return true
+          }
+          return false
+        } catch (e) {
+          console.error('[CostAudit] loadFromTaskId error:', e)
+          return false
+        }
+      },
+      // 不传模板ID直接拉取版本数据(只做数据回显,不加载表头)
+      async loadVersionsWithoutId() {
+        try {
+          const taskId =
+            (this.selectedProject && this.selectedProject.taskId) ||
+            this.id ||
+            ''
+          const versionsRes = await getCostFormVersionsByTemplateId({ taskId })
+          if (versionsRes && versionsRes.code === 200) {
+            const list = Array.isArray(versionsRes.value)
+              ? versionsRes.value
+              : (versionsRes.value && versionsRes.value.itemlist) || []
+            // 若能从版本数据中推断出模板ID,则走完整加载(表头+数据)确保表格正确回显
+            const first = list && list[0]
+            const inferredId =
+              (first &&
+                (first.templateId || first.surveyTemplateId || first.id)) ||
+              ''
+            if (inferredId) {
+              // 记录并按模板ID完整加载
+              if (this.auditForm) this.auditForm.surveyTemplateId = inferredId
+              await this.loadTemplateDataForEdit(inferredId)
+            } else {
+              // 否则仅以返回的列表进行数据回显(前提:已有列配置)
+              const parsedDataRes = { value: { itemlist: list } }
+              this.parseAndDisplayTableData(parsedDataRes)
+              this.computeApprovedForAllRows && this.computeApprovedForAllRows()
+            }
+          }
+        } catch (e) {
+          // ignore
+        }
+      },
+      // 供父组件直接指定模板ID进行加载
+      loadByTemplateId(id) {
+        if (id) {
+          this.auditForm.surveyTemplateId = id
+          this.loadTemplateDataForEdit(id)
+        }
+      },
       handleTemplateTypeChange() {
         if (this.auditForm && this.auditForm.templateType === '1') {
           this.auditForm.historyTemplate = ''
@@ -518,10 +722,21 @@
         try {
           const id = surveyTemplateId || this.auditForm?.surveyTemplateId || ''
           if (!id) return
+          // 防重:避免同一ID并发重复加载
+          this._loadingTemplate = true
+          const taskId =
+            (this.selectedProject && this.selectedProject.taskId) ||
+            this.id ||
+            ''
           // 并行获取:表头配置 + 版本数据(明细) + 模板详情(兜底)
           const [tableHeadersRes, versionsRes, detailRes] = await Promise.all([
             getlistBySurveyTemplateId({ surveyTemplateId: id }),
-            getCostFormVersionsByTemplateId({ surveyTemplateId: id }),
+            // 兼容后端不同参数命名(有环境期望 surveyTemplateId,有环境期望 templateId)
+            getCostFormVersionsByTemplateId({
+              templateId: id,
+              surveyTemplateId: id,
+              taskId,
+            }),
             getVerifyTemplateDetail({ id }),
           ])
 
@@ -543,16 +758,165 @@
             parsedDataRes = detailRes
           }
 
+          // 确保下拉列表包含当前模板,便于中文名称正确回显
+          try {
+            const tplName =
+              (detailRes &&
+                detailRes.value &&
+                (detailRes.value.surveyTemplateName ||
+                  detailRes.value.templatename ||
+                  detailRes.value.name ||
+                  detailRes.value.title)) ||
+              ''
+            const curType = this.auditForm && this.auditForm.templateType
+            if (curType === '1') {
+              const exists =
+                Array.isArray(this.surveyFormList) &&
+                this.surveyFormList.some(
+                  (it) => (it.surveyTemplateId || it.templateId || it.id) === id
+                )
+              if (!exists) {
+                this.surveyFormList = this.surveyFormList || []
+                this.surveyFormList.push({
+                  surveyTemplateId: id,
+                  surveyTemplateName: tplName || '固定表模板',
+                })
+              }
+            } else if (curType === '2') {
+              const exists =
+                Array.isArray(this.auditFormList) &&
+                this.auditFormList.some(
+                  (it) => (it.surveyTemplateId || it.templateId || it.id) === id
+                )
+              if (!exists) {
+                this.auditFormList = this.auditFormList || []
+                this.auditFormList.push({
+                  surveyTemplateId: id,
+                  surveyTemplateName: tplName || '历史核定模板',
+                })
+              }
+            }
+          } catch (e) {}
+
           if (parsedDataRes) {
             this.parseAndDisplayTableData(parsedDataRes)
           } else {
             this.costAuditData = []
           }
 
+          // 追加:调用 getSurveyDetail 回显已上传的数据;若有数据则覆盖版本数据并隐藏“生成核定表”按钮
+          await this.tryEchoUploadData({
+            surveyTemplateId: id,
+            taskId,
+            type: 3,
+          })
+
           // 依据当前数据触发一次联动计算
           this.computeApprovedForAllRows()
         } catch (e) {
           console.error('加载核定模板数据失败:', e)
+        } finally {
+          this._loadingTemplate = false
+          const finalId =
+            surveyTemplateId || this.auditForm?.surveyTemplateId || ''
+          if (finalId) this._lastLoadedTemplateId = finalId
+        }
+      },
+      // 调用上传数据查询接口进行数据回显,若存在数据则覆盖显示并隐藏生成按钮
+      async tryEchoUploadData({ surveyTemplateId, taskId, type, force } = {}) {
+        try {
+          const stid =
+            surveyTemplateId || this.auditForm?.surveyTemplateId || ''
+          const tid =
+            taskId ||
+            (this.selectedProject && this.selectedProject.taskId) ||
+            this.id ||
+            ''
+          const t = type || 3
+          if (!stid || !tid) {
+            this.hasUploadData = false
+            return
+          }
+          const sig = `${stid}|${tid}|${t}`
+          if (!force && this.echoInProgress && this.lastEchoSignature === sig) {
+            return
+          }
+          if (!force && this.lastEchoSignature === sig && this.hasUploadData) {
+            return
+          }
+          this.echoInProgress = true
+          const res = await getSurveyDetail({
+            surveyTemplateId: stid,
+            taskId: tid,
+            type: t,
+          })
+          // 兼容不同返回结构:value.itemlist 或 value.itemsList 或 直接 value 数组
+          let list = []
+          if (res && res.code === 200) {
+            const v = res.value || res.data || res
+            if (Array.isArray(v)) list = v
+            else if (v && Array.isArray(v.itemlist)) list = v.itemlist
+            else if (v && Array.isArray(v.itemsList)) list = v.itemsList
+          }
+          this.hasUploadData = Array.isArray(list) && list.length > 0
+          if (this.hasUploadData) {
+            // 将“单元格列表(list)”按 rowid 聚合为“行对象数组”
+            const headers = Array.isArray(this.tableHeadersRes)
+              ? this.tableHeadersRes
+              : []
+            const nameToHeader = new Map()
+            headers.forEach((h) => {
+              if (h && (h.fieldName || h.label)) {
+                nameToHeader.set(String(h.fieldName || h.label), h)
+              }
+            })
+            const rowsById = new Map()
+            list.forEach((cell) => {
+              const rowId =
+                cell && (cell.rowid != null ? String(cell.rowid) : '')
+              if (!rowId) return
+              if (!rowsById.has(rowId)) {
+                rowsById.set(rowId, {
+                  rowid: rowId,
+                  parentid:
+                    cell.parentId != null ? String(cell.parentId) : '-1',
+                  isChild:
+                    cell.parentId != null &&
+                    cell.parentId !== -1 &&
+                    String(cell.parentId) !== '-1',
+                })
+              }
+              const row = rowsById.get(rowId)
+              const rkey = cell.rkey != null ? String(cell.rkey) : ''
+              const rvalue = cell.rvalue != null ? String(cell.rvalue) : ''
+              const header = nameToHeader.get(rkey)
+              if (header && header.fieldEname) {
+                row[header.fieldEname] = rvalue
+                // 兼容 parseAndDisplayTableData 对中文列名读取
+                row[header.fieldName] = rvalue
+              }
+              // 保留基础键值,便于后续保存
+              row.rkey = rkey
+              row.rvalue = rvalue
+            })
+            const transformed = Array.from(rowsById.values())
+            const parsed = { value: { itemlist: transformed } }
+            this.parseAndDisplayTableData(parsed)
+            this.computeApprovedForAllRows && this.computeApprovedForAllRows()
+            // 记录 uploadId(若返回里包含)
+            if (
+              res &&
+              res.value &&
+              (res.value.uploadId || res.value.uploadid)
+            ) {
+              this.auditForm.uploadId = res.value.uploadId || res.value.uploadid
+            }
+          }
+          this.lastEchoSignature = sig
+        } catch (e) {
+          this.hasUploadData = false
+        } finally {
+          this.echoInProgress = false
         }
       },
       // 单元格输入联动:当账面值或审核调整值变化时,自动计算核定值
@@ -676,17 +1040,17 @@
           }
 
           // 若表头未包含“单位”列,则追加;已包含则不重复添加
-          const hasUnitCol = this.costAuditcolumn.some(
-            (c) => c && (c.label === '单位' || c.fieldName === '单位')
-          )
-          if (!hasUnitCol) {
-            this.costAuditcolumn.push({
-              prop: 'unit',
-              label: '单位',
-              width: '80px',
-              align: 'center',
-            })
-          }
+          // const hasUnitCol = this.costAuditcolumn.some(
+          //   (c) => c && (c.label === '单位' || c.fieldName === '单位')
+          // )
+          // if (!hasUnitCol) {
+          //   this.costAuditcolumn.push({
+          //     prop: 'unit',
+          //     label: '单位',
+          //     width: '80px',
+          //     align: 'center',
+          //   })
+          // }
           // 检查tableHeadersRes数组是否包含年账面值
           const hasBookValueColumn = this.checkHasBookValueColumn()
 
@@ -992,7 +1356,6 @@
           if (res && res.code === 200) {
             this.$message.success('保存成功')
             this.loadTemplateData && this.loadTemplateData()
-            await this.tryEchoUploadData()
           } else {
             this.$message.error((res && res.message) || '保存失败')
           }
@@ -1213,7 +1576,17 @@
               return
             }
             this.$message.success('导入成功')
-            this.loadTemplateData()
+            await this.tryEchoUploadData({
+              surveyTemplateId: this.auditForm.surveyTemplateId,
+              taskId:
+                (this.selectedProject &&
+                  (this.selectedProject.taskId ||
+                    this.selectedProject.taskID)) ||
+                this.id,
+              type: 3,
+              force: true,
+            })
+            this.computeApprovedForAllRows && this.computeApprovedForAllRows()
             // this.$emit('refresh', this.project.projectId) // 通知父组件刷新
           } catch (error) {
             // 错误处理
@@ -1238,52 +1611,57 @@
           background: 'rgba(0, 0, 0, 0.7)',
         })
 
-        // 调用新的导出API
-        downloadTemplate({
-          surveyTemplateId: this.auditForm.surveyTemplateId,
-          versionId: this.tableHeadersRes[0].versionId || '',
-          type: 3,
-        })
+        // 参数与 CostSurveyTab.vue 对齐:带上 surveyTemplateId、versionId、type,并追加 taskId(如有)
+        const surveyTemplateId =
+          (this.auditForm && this.auditForm.surveyTemplateId) || ''
+        const versionId =
+          (Array.isArray(this.tableHeadersRes) &&
+            this.tableHeadersRes[0] &&
+            (this.tableHeadersRes[0].versionId ||
+              this.tableHeadersRes[0].templateVersionId ||
+              this.tableHeadersRes[0].version)) ||
+          ''
+        const params = { surveyTemplateId, versionId, type: 3 }
+        const taskId =
+          (this.selectedProject &&
+            (this.selectedProject.taskId || this.selectedProject.taskID)) ||
+          this.id
+        if (taskId) params.taskId = taskId
+
+        downloadTemplate(params)
           .then((res) => {
-            // 从响应头获取文件名(如果有)
+            const headers = (res && res.headers) || {}
+            const contentDisposition =
+              headers['content-disposition'] || headers['Content-Disposition']
             let fileName = `成本审核模板_${new Date()
               .toLocaleString()
               .replace(/[:\s]/g, '_')}.xlsx`
-            if (res.headers && res.headers['content-disposition']) {
-              const contentDisposition = res.headers['content-disposition']
-              const match = contentDisposition.match(/filename=([^;]+)/i)
-              if (match && match[1]) {
-                fileName = decodeURIComponent(match[1].replace(/['"]/g, ''))
-              }
+            if (contentDisposition) {
+              const match = contentDisposition.match(
+                /filename\*=UTF-8''([^;]+)|filename=([^;]+)/i
+              )
+              const raw = (match && (match[1] || match[2])) || ''
+              if (raw) fileName = decodeURIComponent(raw.replace(/['"]/g, ''))
             }
+            if (!/\.[a-zA-Z0-9]+$/.test(fileName)) fileName += '.xlsx'
 
-            // 使用a标签方式下载文件
-            const blobData = new Blob([res.data], {
-              type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
-            })
-
-            // 创建URL对象
-            const url = window.URL.createObjectURL(blobData)
-
-            // 创建a标签
+            const blobData = (res && res.data) || res
+            const blob =
+              blobData instanceof Blob ? blobData : new Blob([blobData])
+            const url = window.URL.createObjectURL(blob)
             const a = document.createElement('a')
             a.style.display = 'none'
             a.href = url
-            a.download = fileName // 设置下载文件名
-
-            // 添加到DOM并触发点击
+            a.download = fileName
             document.body.appendChild(a)
             a.click()
-            // 关闭加载状态
             loading.close()
-            // 清理
             setTimeout(() => {
               document.body.removeChild(a)
-              window.URL.revokeObjectURL(url) // 释放URL对象,避免内存泄漏
+              window.URL.revokeObjectURL(url)
             }, 100)
           })
           .catch((error) => {
-            // 关闭加载状态
             loading.close()
             console.error('文件下载失败:', error)
           })
@@ -1685,16 +2063,7 @@
         this.sanitizeNumberInput(row, cfg)
       },
       // 父组件在切换到“成本审核”Tab时会调用该方法
-      // 这里做安全兜底:若已有模板ID则加载数据;否则静默返回,等待上游选择后再加载
-      getDetail() {
-        const sid = this.auditForm && this.auditForm.surveyTemplateId
-        if (sid) {
-          // 优先使用回显加载流程
-          if (typeof this.loadTemplateData === 'function') {
-            this.loadTemplateData(sid)
-          }
-        }
-      },
+      // 保留上方 async getDetail() 作为唯一入口,避免重复定义
       computeDateType(item) {
         const fmt =
           item && item.format ? String(item.format).trim().toLowerCase() : ''

+ 71 - 2
src/views/costAudit/auditInfo/auditManage/details.vue

@@ -55,6 +55,7 @@
         >
           <cost-audit
             :id="id"
+            :key="costAuditKey"
             ref="costAudit"
             :selected-project="selectedProject"
             :current-node="currentNode"
@@ -261,6 +262,7 @@
         buttonData: [], //资料初审按钮数据
         activeTab: 'submitData', // 默认选中报送资料标签页
         opinionKey: 0, // 用于强制重渲染成本审核意见子组件
+        costAuditKey: 0, // 用于强制重渲染成本审核子组件,避免保留上次状态
         // 报送资料数据(从接口获取后下发给子组件)
         submitMaterials: [],
         // 成本调查表数据
@@ -324,7 +326,8 @@
         if (newVal && this.id) {
           // 每次打开强制刷新“成本审核意见”子组件,避免保留上次状态
           this.opinionKey++
-          // 使用 $nextTick 确保 props 已更新
+          // 每次打开强制重建“成本审核”子组件,避免保留上次状态
+          this.costAuditKey++
           this.$nextTick(() => {
             // 设置标签页
             this.setActiveTab()
@@ -334,6 +337,22 @@
             if (this.activeTab === 'submitData') {
               this.loadSubmitMaterials()
             }
+            // 若程序设置的活动标签页为“成本审核”,需要主动触发子组件加载版本数据
+            if (this.activeTab === 'costAudit') {
+              this.$nextTick(() => {
+                if (
+                  this.$refs.costAudit &&
+                  this.$refs.costAudit.loadFromTaskId
+                ) {
+                  this.$refs.costAudit.loadFromTaskId()
+                } else if (
+                  this.$refs.costAudit &&
+                  this.$refs.costAudit.getDetail
+                ) {
+                  this.$refs.costAudit.getDetail()
+                }
+              })
+            }
           })
         }
       },
@@ -345,6 +364,22 @@
             this.setActiveTab()
             // 重新获取按钮数据
             this.getPreliminaryReviewButton()
+            // 如果当前应显示“成本审核”,主动触发加载
+            if (this.activeTab === 'costAudit') {
+              this.$nextTick(() => {
+                if (
+                  this.$refs.costAudit &&
+                  this.$refs.costAudit.loadFromTaskId
+                ) {
+                  this.$refs.costAudit.loadFromTaskId()
+                } else if (
+                  this.$refs.costAudit &&
+                  this.$refs.costAudit.getDetail
+                ) {
+                  this.$refs.costAudit.getDetail()
+                }
+              })
+            }
           })
         }
       },
@@ -371,6 +406,22 @@
             if (this.activeTab === 'submitData') {
               this.loadSubmitMaterials()
             }
+            // 若当前为成本审核标签,主动加载
+            if (this.activeTab === 'costAudit') {
+              this.$nextTick(() => {
+                if (
+                  this.$refs.costAudit &&
+                  this.$refs.costAudit.loadFromTaskId
+                ) {
+                  this.$refs.costAudit.loadFromTaskId()
+                } else if (
+                  this.$refs.costAudit &&
+                  this.$refs.costAudit.getDetail
+                ) {
+                  this.$refs.costAudit.getDetail()
+                }
+              })
+            }
           })
         }
       },
@@ -386,6 +437,19 @@
           if (this.activeTab === 'submitData') {
             this.loadSubmitMaterials()
           }
+          // 如果默认即处于成本审核页签,也要主动触发加载
+          if (this.activeTab === 'costAudit') {
+            this.$nextTick(() => {
+              if (this.$refs.costAudit && this.$refs.costAudit.loadFromTaskId) {
+                this.$refs.costAudit.loadFromTaskId()
+              } else if (
+                this.$refs.costAudit &&
+                this.$refs.costAudit.getDetail
+              ) {
+                this.$refs.costAudit.getDetail()
+              }
+            })
+          }
         })
       }
     },
@@ -460,10 +524,15 @@
         if (tab && tab.name === 'costAudit' && this.id) {
           // 加载成本审核列表
           this.$nextTick(() => {
-            this.$refs.costAudit.getDetail()
+            if (this.$refs.costAudit && this.$refs.costAudit.loadFromTaskId) {
+              this.$refs.costAudit.loadFromTaskId()
+            } else if (this.$refs.costAudit && this.$refs.costAudit.getDetail) {
+              this.$refs.costAudit.getDetail()
+            }
           })
         }
       },
+
       async loadSubmitMaterials() {
         try {
           const resp = await getTaskRequirementList(this.id)