Prechádzať zdrojové kódy

修改bug,监审立项管理的问题,完善任务详情页面

cb_luzhixia 1 mesiac pred
rodič
commit
842956a906
24 zmenil súbory, kde vykonal 1577 pridanie a 641 odobranie
  1. 8 0
      src/api/taskCustomizedRelease.js
  2. 17 0
      src/api/taskProgressManage.js
  3. 17 20
      src/components/costAudit/AuditEntityFormtDialog.vue
  4. 0 1
      src/mixins/useDict.js
  5. 1 0
      src/views/costAudit/baseInfo/auditEntityManage/index.vue
  6. 2 0
      src/views/costAudit/baseInfo/auditReviewDocManage/index.vue
  7. 1 1
      src/views/costAudit/baseInfo/catalogManage/index.vue
  8. 10 4
      src/views/costAudit/baseInfo/costFormManage/infoMaintain.vue
  9. 2 1
      src/views/costAudit/baseInfo/costVerifyManage/index.vue
  10. 5 2
      src/views/costAudit/baseInfo/financeSheetManage/infoMaintain.vue
  11. 98 35
      src/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/auditNoticeTab.vue
  12. 32 6
      src/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/basicInfoTab.vue
  13. 11 3
      src/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/index.js
  14. 29 21
      src/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/index.vue
  15. 11 23
      src/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/materialTab.vue
  16. 12 25
      src/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/surveyTab.vue
  17. 16 4
      src/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/tabs.vue
  18. 46 45
      src/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/workflowTab.vue
  19. 146 0
      src/views/costAudit/projectInfo/auditTaskManage/taskProgressManage/conclusionTab.vue
  20. 44 26
      src/views/costAudit/projectInfo/auditTaskManage/taskProgressManage/detailTabs.vue
  21. 238 153
      src/views/costAudit/projectInfo/auditTaskManage/taskProgressManage/index.vue
  22. 470 0
      src/views/costAudit/projectInfo/auditTaskManage/taskProgressManage/meetingTab.vue
  23. 156 88
      src/views/costAudit/projectInfo/auditTaskManage/taskProgressManage/workflowTab.vue
  24. 205 183
      src/views/costAudit/projectInfo/auditTaskManage/taskQueryStatistics/index.vue

+ 8 - 0
src/api/taskCustomizedRelease.js

@@ -2,6 +2,14 @@ import request from '@/utils/request'
 
 const url = window.context.form
 
+// 获取监审立项信息详情
+export function getCostProjectDetail(params) {
+  return request({
+    url: `${url}/api/costProjectApproval/v1/getDetail`,
+    method: 'get',
+    params,
+  })
+}
 /**
  * 根据id获取监审工作方案数据详情
  * @param {Object} params - 请求参数

+ 17 - 0
src/api/taskProgressManage.js

@@ -12,3 +12,20 @@ export function taskList(data) {
     data,
   })
 }
+
+export function getDeliberatePageList(data) {
+  return request({
+    url: `${url}/api/costProjectDeliberate/v1/pageList`,
+    method: 'POST',
+    data,
+  })
+}
+
+// 根据项目id获取监审项目结论表数据详情
+export function getConclusionDetail(params) {
+  return request({
+    url: `${url}/api/costProjectConclusion/v1/getDetail`,
+    method: 'get',
+    params,
+  })
+}

+ 17 - 20
src/components/costAudit/AuditEntityFormtDialog.vue

@@ -170,11 +170,11 @@
                   @change="handleAccountChange"
                 >
                   <el-option
-                    v-for="item in accountList"
-                    :key="item.value"
-                    :label="item.label"
-                    :value="item.value"
-                  />
+                    v-for="(item, index) in userList"
+                    :key="index"
+                    :label="item.fullname"
+                    :value="item.userId"
+                  ></el-option>
                 </el-select>
               </el-form-item>
             </el-col>
@@ -213,7 +213,7 @@
   import { regionMixin, catalogMixin, commonMixin } from '@/mixins/useDict'
   // 引入弹窗组件
   import CostAuditDialog from '@/components/costAudit/CostAuditDialog'
-
+  import { getAllUserList } from '@/api/uc'
   export default {
     name: 'AuditEntityFormtDialog',
     // 注册组件
@@ -273,18 +273,7 @@
           },
         ],
         // 账号列表
-        accountList: [
-          {
-            label: '账号1',
-            value: '1',
-            password: '123456',
-          },
-          {
-            label: '账号2',
-            value: '2',
-            password: '123123',
-          },
-        ],
+        userList: [],
         // 状态选项
         statusOptions: [
           {
@@ -471,6 +460,13 @@
     },
     // 组件方法
     methods: {
+      getUser() {
+        getAllUserList()
+          .then((res) => {
+            this.userList = res.value || []
+          })
+          .catch(() => {})
+      },
       // 重置表单
       resetForm() {
         this.formData = {
@@ -505,6 +501,7 @@
           // 过滤掉状态为停用的数据
           this.allUnits = this.allUnits.filter((item) => item.status == 1)
         })
+        this.getUser()
       },
       // 加载单位详情
       loadUnitDetail() {
@@ -539,8 +536,8 @@
       handleAccountChange(val) {
         if (val) {
           // 根据选择的账号自动填充密码
-          const selectedAccount = this.accountList.find(
-            (item) => item.value === val
+          const selectedAccount = this.userList.find(
+            (item) => item.userId === val
           )
           if (selectedAccount) {
             this.$set(this.formData, 'password', selectedAccount.password)

+ 0 - 1
src/mixins/useDict.js

@@ -359,7 +359,6 @@ export const commonMixin = {
 
       for (const option of options) {
         if (option[idKey] === id) {
-          console.log('找到的项:', option)
           return option
         }
 

+ 1 - 0
src/views/costAudit/baseInfo/auditEntityManage/index.vue

@@ -164,6 +164,7 @@
             width: 180,
             align: 'center',
             fixed: 'right',
+            showOverflowTooltip: false,
             // 操作按钮配置
             actions: [
               {

+ 2 - 0
src/views/costAudit/baseInfo/auditReviewDocManage/index.vue

@@ -950,6 +950,8 @@
           if (valid) {
             if (!this.isDisabled) {
               this.handleSave()
+            } else {
+              this.activeStep = 1
             }
           } else {
             this.$message.error('请填写完整的基础信息')

+ 1 - 1
src/views/costAudit/baseInfo/catalogManage/index.vue

@@ -1343,7 +1343,7 @@
 
             // 移除不需要的属性
             this.tableListData = this.removeItemFromTree(this.tableListData)
-            this.tableData - []
+            this.tableData = []
             // 直接返回所有顶级目录的子项元素,扁平化处理
             // 先清空数组,避免数据积累
             this.tableData = []

+ 10 - 4
src/views/costAudit/baseInfo/costFormManage/infoMaintain.vue

@@ -148,7 +148,12 @@
     </el-dialog>
 
     <!-- 添加/修改弹窗 -->
-    <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="600px">
+    <el-dialog
+      :title="dialogTitle"
+      :visible.sync="dialogVisible"
+      width="600px"
+      :close-on-click-modal="false"
+    >
       <el-form
         ref="dataForm"
         :model="dataForm"
@@ -382,6 +387,7 @@
                   </div>
                   <!-- 默认情况 -->
                   <el-input
+                    v-else
                     v-model="scope.row.format"
                     :placeholder="getFormatPlaceholder(scope.row.fieldType)"
                     size="small"
@@ -2048,7 +2054,7 @@
         this.viewDetail = true
         this.detailForm = { ...row }
         // this.detailDialogVisible = true
-        this.handleEditContent(row)
+        this.handleEditContent(row, this.viewDetail)
       },
       // 添加子项方法
       handleAddChildItem(index, type, parentRow) {
@@ -2294,8 +2300,8 @@
       },
 
       // 内容维护
-      handleEditContent(row) {
-        this.viewDetail = false
+      handleEditContent(row, viewDetail) {
+        this.viewDetail = viewDetail || false
         this.versionId = row.id
 
         // 显示加载状态

+ 2 - 1
src/views/costAudit/baseInfo/costVerifyManage/index.vue

@@ -211,6 +211,7 @@
           class="mt20"
           :current-page.sync="searchForm.pageNum"
           :page-size="searchForm.pageSize"
+          :page-sizes="[50, 100]"
           layout="total, sizes, prev, pager, next, jumper"
           :total="pagination.total"
           @current-change="handleCurrentChange"
@@ -473,7 +474,7 @@
           catalogId: '',
           keyword: '',
           pageNum: 1,
-          pageSize: 10,
+          pageSize: 50,
         },
         catalogIdProps: {
           filterable: true,

+ 5 - 2
src/views/costAudit/baseInfo/financeSheetManage/infoMaintain.vue

@@ -191,6 +191,7 @@
       :visible.sync="contentEditDialogVisible"
       width="75%"
       class="content-edit-dialog"
+      :close-on-click-modal="false"
     >
       <div class="content-edit-container">
         <div class="table-header-info">
@@ -382,6 +383,7 @@
                   </div>
                   <!-- 默认情况 -->
                   <el-input
+                    v-else
                     v-model="scope.row.format"
                     :placeholder="getFormatPlaceholder(scope.row.fieldType)"
                     size="small"
@@ -2048,7 +2050,7 @@
         this.viewDetail = true
         this.detailForm = { ...row }
         // this.detailDialogVisible = true
-        this.handleEditContent(row)
+        this.handleEditContent(row, this.viewDetail)
       },
 
       // 添加子项方法
@@ -2298,7 +2300,8 @@
       },
 
       // 内容维护
-      handleEditContent(row) {
+      handleEditContent(row, viewDetail) {
+        this.viewDetail = viewDetail || false
         this.versionId = row.id
 
         // 显示加载状态

+ 98 - 35
src/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/auditNoticeTab.vue

@@ -131,14 +131,14 @@
       @cancel="handleCancel"
       @confirm="handleConfirm"
     >
-      <div class="document-edit-container mt20">
+      <div class="document-edit-container">
         <!-- 左侧:文书参数设置 -->
         <div class="document-params">
           <h4>文书参数设置:</h4>
           <el-form
             v-loading="loading.saveDocument"
             :model="document"
-            label-width="100px"
+            label-width="160px"
             size="small"
           >
             <el-form-item label="选择模板:">
@@ -160,7 +160,7 @@
               <el-input
                 v-model="document.documentNumber"
                 placeholder="请选择通知书文号"
-                style="width: 78%"
+                style="width: 74%"
               ></el-input>
               <!-- disabled -->
               <el-button
@@ -178,6 +178,7 @@
                 placeholder="请选择被监审单位"
                 style="width: 100%"
                 clearable
+                multiple
               >
                 <el-option
                   v-for="item in allUnits"
@@ -187,6 +188,13 @@
                 ></el-option>
               </el-select>
             </el-form-item>
+            <el-form-item label="是否推送被监审单位:">
+              <!-- 是否推送被监审单位 -->
+              <el-radio-group v-model="document.isPush">
+                <el-radio label="1">是</el-radio>
+                <el-radio label="0">否</el-radio>
+              </el-radio-group>
+            </el-form-item>
             <!-- <el-form-item label="被监审单位:">
               <el-select
                 v-model="document.enterpriseId"
@@ -330,7 +338,7 @@
           documentId: '',
           documentWhId: '',
           documentNumber: '',
-          enterpriseId: '',
+          enterpriseId: [],
           dataList: [],
         },
         loading: {
@@ -347,7 +355,18 @@
         dialogWidth: '70%',
         fileUrl: '',
         selectDocumentWhData: [],
-        selectDocumentWhColumns: [
+        selectDocumentWhPagination: {
+          currentPage: 1,
+          pageSize: 10,
+          total: 0,
+        },
+        selectDocumentWhSelection: [],
+        costDocumentTemplateFiles: [],
+      }
+    },
+    computed: {
+      selectDocumentWhColumns() {
+        return [
           {
             prop: 'whType',
             label: '文号分类',
@@ -383,15 +402,8 @@
             formatter: (row) =>
               this.getDictName('whGenerateType', row.generateType),
           },
-        ],
-        selectDocumentWhPagination: {
-          currentPage: 1,
-          pageSize: 10,
-          total: 0,
-        },
-        selectDocumentWhSelection: [],
-        costDocumentTemplateFiles: [],
-      }
+        ]
+      },
     },
     // 添加watch监听project变化,确保项目数据更新时重新加载数据
     watch: {
@@ -411,7 +423,31 @@
     },
     methods: {
       getEnterpriseName(row) {
-        return this.allUnits.find((item) => item.id == row.unitId)?.unitName
+        // 处理enterpriseId,无论是数组还是逗号分隔的字符串
+        let enterpriseIds = []
+        if (Array.isArray(row.enterpriseId)) {
+          enterpriseIds = row.enterpriseId
+        } else if (typeof row.enterpriseId === 'string') {
+          // 处理逗号分隔的字符串
+          enterpriseIds = row.enterpriseId
+            .split(',')
+            .map((id) => id.trim())
+            .filter((id) => id)
+        } else if (row.enterpriseId) {
+          // 处理其他可能的非空值
+          enterpriseIds = [row.enterpriseId]
+        }
+
+        if (enterpriseIds.length > 0) {
+          // 返回多个企业名称,用逗号分隔
+          return enterpriseIds
+            .map(
+              (id) => this.allUnits.find((item) => item.unitId == id)?.unitName
+            )
+            .filter((name) => name)
+            .join(', ')
+        }
+        return '-'
       },
       getDocumenType(row) {
         return this.documentData.documentTypes.find(
@@ -440,7 +476,7 @@
           documentId: '',
           documentWhId: '',
           documentNumber: '',
-          enterpriseId: '',
+          enterpriseId: [],
         }
         this.costProjectDocumentFiles = []
       },
@@ -513,6 +549,15 @@
       },
       // 保存文档
       handleSaveDocument() {
+        // 验证是否选择了企业
+        if (
+          !this.document.enterpriseId ||
+          this.document.enterpriseId.length === 0
+        ) {
+          this.$message.error('请至少选择一个被监审单位!')
+          return
+        }
+
         this.loading.saveDocument = true
         if (this.document.id) {
           updateCostProjectDocument({
@@ -525,7 +570,7 @@
             // isPushed: this.document.isPushed,
             projectId: this.project.projectId,
             // electronicDocumentUrl: '',
-            enterpriseId: this.document.enterpriseId,
+            enterpriseId: this.document.enterpriseId.join(','), // 保存时转换为逗号分隔的字符串
             // feedbackDocumentUrl: '',
             // feedbackTime: '',
             // generateTime: '',
@@ -533,7 +578,7 @@
             .then((res) => {
               this.loading.saveDocument = false
               this.$message.success('保存成功!')
-              this.dialogVisible = false
+              this.documentDialogVisible = false
               this.activeView = ''
               this.$emit('refresh', this.project.projectId)
             })
@@ -541,24 +586,29 @@
               this.loading.saveDocument = false
             })
         } else {
-          addCostProjectDocument({
-            // documentAlias: this.document.documentAlias,
-            projectId: this.project.projectId,
-            documentId: this.document.documentId,
-            documentNumber: this.document.documentNumber,
-            documentWhId: this.document.documentWhId,
-            costProjectDocumentFiles: this.costProjectDocumentFiles || [],
-            enterpriseId: this.document.enterpriseId,
-            // electronicDocumentUrl: '',
-            // feedbackDocumentUrl: '',
-            // feedbackTime: '',
-            // generateTime: '',
-            // isPushed: '0',
-            // orderNum: 0,
-            // pushTime: '',
-            // scanDocumentUrl: '',
+          // 处理多选逻辑,如果选择了多个单位,为每个单位创建一个文档记录
+          const promises = this.document.enterpriseId.map((enterpriseId) => {
+            return addCostProjectDocument({
+              // documentAlias: this.document.documentAlias,
+              projectId: this.project.projectId,
+              documentId: this.document.documentId,
+              documentNumber: this.document.documentNumber,
+              documentWhId: this.document.documentWhId,
+              costProjectDocumentFiles: this.costProjectDocumentFiles || [],
+              enterpriseId: enterpriseId,
+              // electronicDocumentUrl: '',
+              // feedbackDocumentUrl: '',
+              // feedbackTime: '',
+              // generateTime: '',
+              isPushed: this.document.isPushed,
+              // orderNum: 0,
+              // pushTime: '',
+              // scanDocumentUrl: '',
+            })
           })
-            .then((res) => {
+
+          Promise.all(promises)
+            .then(() => {
               this.loading.saveDocument = false
               this.$message.success('保存成功!')
               this.dialogVisible = false
@@ -575,6 +625,7 @@
         if (this.activeView === 'form') {
           this.documentDialogVisible = false
         } else {
+          this.activeView = 'form'
           this.dialogVisible = false
         }
       },
@@ -682,8 +733,20 @@
         this.documentDialogVisible = true
         this.activeView = 'form'
         this.loadOpts()
+        // 确保enterpriseId是数组格式,处理可能的逗号分隔字符串
+        const enterpriseId = row.enterpriseId
+          ? Array.isArray(row.enterpriseId)
+            ? row.enterpriseId
+            : typeof row.enterpriseId === 'string'
+            ? row.enterpriseId
+                .split(',')
+                .map((id) => id.trim())
+                .filter((id) => id) // 将逗号分隔字符串转换为数组
+            : [row.enterpriseId]
+          : []
         this.document = {
           ...row,
+          enterpriseId,
         }
       },
 

+ 32 - 6
src/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/basicInfoTab.vue

@@ -37,12 +37,21 @@
 
       <!-- 被监审单位 -->
       <el-form-item label="被监审单位" prop="auditedUnitName">
-        <el-input
-          v-model="formData.basicInfo.auditedUnitName"
+        <el-select
+          v-model="formData.basicInfo.auditedUnitId"
+          placeholder="请选择单位"
+          clearable
+          multiple
           style="width: 100%"
-          placeholder="请输入被监审单位"
           readonly
-        />
+        >
+          <el-option
+            v-for="unit in unitList"
+            :key="unit.unitId"
+            :label="unit.unitName"
+            :value="unit.unitId"
+          />
+        </el-select>
       </el-form-item>
 
       <!-- 监审主体 -->
@@ -236,6 +245,7 @@
   import UploadComponent from '@/components/costAudit/UploadComponent.vue'
   import CatalogCascader from '@/views/costAudit/projectInfo/auditProjectManage/annualReviewPlan/CatalogCascader.vue'
   import { getDefaultDem, getOrgListByDemId } from '@/api/annualReviewPlan'
+  import { getAllUnitList } from '@/api/auditEntityManage'
   export default {
     name: 'BasicInfoTab',
     components: {
@@ -258,6 +268,7 @@
         OrgList: [],
         accordingFileList: [],
         otherFileList: [],
+        unitList: [],
       }
     },
     // 添加watch监听project变化,确保项目数据更新时重新加载数据
@@ -266,9 +277,11 @@
         handler() {
           if (this.project && this.project.projectId) {
             this.formData.basicInfo = this.project
-            console.log(this.project)
+            this.formData.basicInfo.auditedUnitId = this.project.auditedUnitId
+              ? this.project.auditedUnitId.split(',')
+              : []
             this.formData.basicInfo.auditPeriodArray = this.project.auditPeriod
-              .split(',')
+              .split(',')
               .map((year) => ({ value: year }))
             this.formData.basicInfo.auditTeamMembers =
               this.project.projectMembers.split(',')
@@ -283,12 +296,25 @@
         deep: true,
         immediate: true,
       },
+      activeTab: {
+        handler() {
+          console.log('activeTab', this.activeTab)
+          if (this.activeTab === 'basicInfo') {
+          }
+        },
+      },
     },
     mounted() {
+      this.getAllUnitList()
       this.getUser()
       this.getDefaultDem()
     },
     methods: {
+      getAllUnitList() {
+        getAllUnitList().then((res) => {
+          this.unitList = res.value || []
+        })
+      },
       // 获取默认维度
       getDefaultDem() {
         getDefaultDem().then((res) => {

+ 11 - 3
src/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/index.js

@@ -1,4 +1,5 @@
 import {
+  getCostProjectDetail,
   getCostProjectScenarioDetail,
   getCostProjectDocumentPageList,
   getCostProjectMaterialPageList,
@@ -134,7 +135,7 @@ export const taskMixin = {
         list: [],
         pagination: {
           currentPage: 1,
-          pageSize: 10,
+          pageSize: 50,
           total: 0,
         },
         materialDialogTitle: '添加',
@@ -210,7 +211,7 @@ export const taskMixin = {
         list: [],
         pagination: {
           currentPage: 1,
-          pageSize: 10,
+          pageSize: 50,
           total: 0,
         },
         surveyColumns: [
@@ -441,7 +442,7 @@ export const taskMixin = {
       // 可添加标签页切换时的逻辑
       switch (this.activeTab) {
         case 'basicInfo':
-          this.formData.basicInfo = this.project
+          this.getBasicInfo()
           break
         case 'scenario':
           this.getScenarioData()
@@ -462,6 +463,13 @@ export const taskMixin = {
           break
       }
     },
+    getBasicInfo() {
+      getCostProjectDetail({
+        id: this.project.projectId,
+      }).then((res) => {
+        this.formData.basicInfo = res.value || this.project
+      })
+    },
     // 获取监审工作方案数据
     getScenarioData() {
       getCostProjectScenarioDetail({

+ 29 - 21
src/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/index.vue

@@ -56,7 +56,7 @@
             </span>
           </template>
           <template #auditedUnitId="{ row }">
-            {{ UnitNameMap[row.auditedUnitId] }}
+            {{ getUnitName(row.auditedUnitId) }}
           </template>
           <template #status="{ row }">
             {{ row.status | statusFilter }}
@@ -157,7 +157,7 @@
   import CostAuditTable from '@/components/costAudit/CostAuditTable.vue'
   import taskFormulate from './tabs.vue'
   import { publishCostProjectApproval } from '@/api/auditInitiation'
-  import { getAuditedUnitDetail } from '@/api/auditEntityManage'
+  import { getAllUnitList } from '@/api/auditEntityManage'
   import { taskMixin } from './index.js'
   import { getAllUserList } from '@/api/uc'
   import {
@@ -237,6 +237,7 @@
           ],
         },
         userList: [],
+        unitList: [],
       }
     },
     computed: {
@@ -307,6 +308,31 @@
           this.userList = res.value || []
         })
       },
+      getAllUnitList() {
+        getAllUnitList().then((res) => {
+          this.unitList = res.value || []
+          // 过滤掉状态为停用的数据
+          // this.unitList = this.unitList.filter((item) => item.status == 1)
+        })
+      },
+      getUnitName(unitId) {
+        // 直接处理unitId值,而不是row对象
+        if (unitId && typeof unitId === 'string' && unitId.includes(',')) {
+          // 如果包含逗号,分割成数组并查找对应的unitName
+          const unitIds = unitId.split(',')
+          return unitIds
+            .map((id) => {
+              const unit = this.unitList.find((item) => item.unitId == id)
+              return unit ? unit.unitName : '无'
+            })
+            .filter((name) => name) // 过滤空值
+            .join(',')
+        } else {
+          // 单个unitId的情况
+          const unit = this.unitList.find((item) => item.unitId == unitId)
+          return unit ? unit.unitName : '无'
+        }
+      },
       // 查询
       handleSearch() {
         getDataList({
@@ -316,7 +342,7 @@
         }).then((res) => {
           this.taskList = res.value.value.records
           this.pagination.total = res.value.value.total
-          this.batchGetUnitNames()
+          this.getAllUnitList()
         })
       },
       handleReset() {
@@ -377,24 +403,6 @@
           this.handleSearch()
         })
       },
-      //获取被监审单位名称
-      batchGetUnitNames() {
-        this.taskList.forEach((row) => {
-          const unitId = row.auditedUnitId
-          getAuditedUnitDetail({ unitId: unitId })
-            .then((res) => {
-              if (res && res.value && res.value.unitName) {
-                // 缓存名称
-                this.$set(this.UnitNameMap, unitId, res.value.unitName)
-              }
-            })
-            .catch((err) => {
-              console.error('获取被监审单位主体名称失败', err)
-              this.$set(this.UnitNameMap, unitId, '获取失败')
-            })
-            .finally(() => {})
-        })
-      },
 
       // 查看
       handleView(row) {

+ 11 - 23
src/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/materialTab.vue

@@ -90,31 +90,19 @@
         ],
       }
     },
-    // 添加watch监听project变化,确保项目数据更新时重新加载材料数据
     watch: {
-      project: {
-        handler() {
-          if (
-            this.project &&
-            this.project.projectId &&
-            this.materialData.list.length === 0
-          ) {
-            this.getMaterialData()
-          }
-        },
-        deep: true,
-        immediate: true,
-      },
-    },
-    mounted() {
-      if (
-        this.project &&
-        this.project.projectId &&
-        this.materialData.list.length === 0
-      ) {
-        this.getMaterialData()
-      }
+      // 监听project变化,当项目信息更新时重新获取材料数据
+      // project: {
+      //   handler(newVal) {
+      //     if (newVal && newVal.projectId) {
+      //       this.getMaterialData()
+      //     }
+      //   },
+      //   deep: true,
+      //   immediate: true
+      // }
     },
+    mounted() {},
     methods: {
       // 排序变更
       handleSortChange(row) {

+ 12 - 25
src/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/surveyTab.vue

@@ -32,6 +32,17 @@
         type: Object,
         default: () => {},
       },
+      isView: {
+        type: Boolean,
+        default: false,
+      },
+      surveyData: {
+        type: Object,
+        default: () => ({
+          list: [],
+          surveyColumns: [],
+        }),
+      },
     },
     data() {
       return {
@@ -51,31 +62,7 @@
         },
       }
     },
-    // 添加watch监听project变化,确保项目数据更新时重新加载数据
-    watch: {
-      project: {
-        handler() {
-          if (
-            this.project &&
-            this.project.projectId &&
-            this.surveyData.list.length === 0
-          ) {
-            this.getSurveyData()
-          }
-        },
-        deep: true,
-        immediate: true,
-      },
-    },
-    mounted() {
-      if (
-        this.project &&
-        this.project.projectId &&
-        this.surveyData.list.length === 0
-      ) {
-        this.getSurveyData()
-      }
-    },
+    mounted() {},
     methods: {
       // 查看成本调查表内容弹窗
       handleViewTemplate(data) {

+ 16 - 4
src/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/tabs.vue

@@ -38,7 +38,7 @@
       >
         <!-- 监审立项信息 -->
         <el-tab-pane label="监审立项信息" name="basicInfo">
-          <basicInfoTab :project="project" :is-view="isView" />
+          <basicInfoTab :project="formData.basicInfo" :is-view="isView" />
         </el-tab-pane>
 
         <!-- 监审工作方案 -->
@@ -122,17 +122,29 @@
 
         <!-- 报送资料要求 -->
         <el-tab-pane label="报送资料要求" name="material">
-          <materialTab :project="project" :is-view="isView"></materialTab>
+          <materialTab
+            :project="project"
+            :is-view="isView"
+            :material-data="materialData"
+          ></materialTab>
         </el-tab-pane>
 
         <!-- 成本调查表 -->
         <el-tab-pane label="成本调查表" name="survey">
-          <surveyTab :project="project" :is-view="isView"></surveyTab>
+          <surveyTab
+            :project="project"
+            :is-view="isView"
+            :survey-data="surveyData"
+          ></surveyTab>
         </el-tab-pane>
 
         <!-- 监审工作流程 -->
         <el-tab-pane label="监审工作流程" name="workflow">
-          <workflowTab :project="project" :is-view="isView"></workflowTab>
+          <workflowTab
+            :project="project"
+            :is-view="isView"
+            :workflow-data="workflowData"
+          ></workflowTab>
         </el-tab-pane>
 
         <!-- 监审通知 -->

+ 46 - 45
src/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/workflowTab.vue

@@ -34,7 +34,7 @@
       </el-button>
     </div>
     <CostAuditTable
-      :table-data="workflowData.list"
+      :table-data="localWorkflowData.list"
       :columns="workflowData.listColumns"
       :show-index="true"
       :show-action-column="true"
@@ -79,7 +79,7 @@
         ></el-date-picker>
       </div>
       <CostAuditTable
-        :table-data="workflowData.stepList"
+        :table-data="localWorkflowData.stepList"
         :columns="workflowData.workflowColumns"
         :show-index="true"
         :show-pagination="true"
@@ -87,7 +87,7 @@
         :table-props="{
           maxHeight: '500',
         }"
-        :pagination="workflowData.pagination"
+        :pagination="localWorkflowData.pagination"
         @pagination-change="handlePaginationChange"
       >
         <template #mainUserId="{ row }">
@@ -292,35 +292,30 @@
         type: Boolean,
         default: false,
       },
+      workflowData: {
+        type: Object,
+        default: () => ({
+          list: [],
+          detailInfo: {},
+        }),
+      },
     },
     data() {
-      return {}
+      return {
+        localWorkflowData: { ...this.workflowData },
+      }
     },
     computed: {},
-    // 添加watch监听project变化,确保项目数据更新时重新加载数据
     watch: {
-      project: {
-        handler() {
-          if (
-            this.project &&
-            this.project.projectId &&
-            this.workflowData.list.length === 0
-          ) {
-            this.getWorkflow()
-          }
+      workflowData: {
+        handler(newVal) {
+          this.localWorkflowData = { ...newVal }
         },
         deep: true,
-        immediate: true,
       },
     },
     mounted() {
-      if (
-        this.project &&
-        this.project.projectId &&
-        this.workflowData.list.length === 0
-      ) {
-        this.getWorkflow()
-      }
+      this.localWorkflowData = { ...this.workflowData }
     },
     methods: {
       formatterUserList(userId) {
@@ -329,25 +324,27 @@
       handleSetWorkflow() {
         this.getUser()
         this.dialogs.setStepDialogVisible = true
-        if (this.workflowData.list.length > 0) {
-          this.workflowData.stepList = this.workflowData.list
-          this.workflowData.stepList = this.workflowData.list.map((item) => ({
-            ...item,
-            userId: item.userId ? item.userId.split(',') : [],
-            status: item.status ? item.status.split(',') : [],
-          }))
+        if (this.localWorkflowData.list.length > 0) {
+          this.localWorkflowData.stepList = this.localWorkflowData.list
+          this.localWorkflowData.stepList = this.localWorkflowData.list.map(
+            (item) => ({
+              ...item,
+              userId: item.userId ? item.userId.split(',') : [],
+              status: item.status ? item.status.split(',') : [],
+            })
+          )
         } else {
           getCostProjectNodeTmpletePageList({
-            pageNum: this.workflowData.pagination.currentPage,
-            pageSize: this.workflowData.pagination.pageSize,
+            pageNum: this.localWorkflowData.pagination.currentPage,
+            pageSize: this.localWorkflowData.pagination.pageSize,
             processId: '1',
           }).then((res) => {
-            this.workflowData.stepList = res.value.records.map((item) => ({
+            this.localWorkflowData.stepList = res.value.records.map((item) => ({
               ...item,
               userId: item.userId ? item.userId.split(',') : [],
               status: item.status ? item.status.split(',') : [],
             }))
-            this.workflowData.pagination.total = res.value.total
+            this.localWorkflowData.pagination.total = res.value.total
           })
         }
       },
@@ -374,20 +371,24 @@
         this.$refs[formName].validate((valid) => {
           if (valid) {
             if (type == 'list') {
-              this.workflowData.list = this.workflowData.list.map((item) => {
-                if (
-                  item.processNodeKey ==
-                  this.formData.currentStep.processNodeKey
-                ) {
-                  return {
-                    ...item,
-                    ...this.formData.currentStep,
-                    userId: this.formData.currentStep.userId.join(','),
-                    status: this.formData.currentStep.status.join(','),
+              this.localWorkflowData.list = this.localWorkflowData.list.map(
+                (item) => {
+                  if (
+                    item.processNodeKey ==
+                    this.formData.currentStep.processNodeKey
+                  ) {
+                    return {
+                      ...item,
+                      ...this.formData.currentStep,
+                      userId: this.formData.currentStep.userId.join(','),
+                      status: this.formData.currentStep.status.join(','),
+                    }
                   }
+                  return item
                 }
-                return item
-              })
+              )
+              // 触发自定义事件通知父组件数据已更新
+              this.$emit('update:workflowData', { ...this.localWorkflowData })
               this.handleSaveSetStep('list')
             }
           } else {

+ 146 - 0
src/views/costAudit/projectInfo/auditTaskManage/taskProgressManage/conclusionTab.vue

@@ -0,0 +1,146 @@
+<template>
+  <!-- 出具结论内容 -->
+  <div class="conclusion-section">
+    <el-button type="primary" style="margin-bottom: 20px" :disabled="isView">
+      保存
+    </el-button>
+
+    <el-form
+      ref="conclusionForm"
+      :model="conclusionForm"
+      label-width="150px"
+      class="conclusion-form"
+      :disabled="isView"
+    >
+      <el-row>
+        <el-col :span="24">
+          <el-form-item label="定价成本构成">
+            <el-input
+              v-model="conclusionForm.pricingCostStructure"
+              type="textarea"
+              :rows="4"
+              placeholder="填写 (非必填)"
+              style="width: 100%"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <el-row>
+        <el-col :span="24">
+          <el-form-item label="审核的内容和方法">
+            <el-input
+              v-model="conclusionForm.auditContentMethod"
+              type="textarea"
+              :rows="4"
+              placeholder="填写 (非必填)"
+              style="width: 100%"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <el-row>
+        <el-col :span="24">
+          <el-form-item label="成本费用项目核销(减)情况及理由">
+            <el-input
+              v-model="conclusionForm.costDeductionReason"
+              type="textarea"
+              :rows="4"
+              placeholder="填写 (非必填)"
+              style="width: 100%"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <el-row>
+        <el-col :span="24">
+          <el-form-item label="成本监审结论">
+            <el-input
+              v-model="conclusionForm.costAuditConclusion"
+              type="textarea"
+              :rows="4"
+              placeholder="填写 (非必填)"
+              style="width: 100%"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <el-row>
+        <el-col :span="24">
+          <el-form-item label="违约情况说明">
+            <el-input
+              v-model="conclusionForm.defaultConditions"
+              type="textarea"
+              :rows="4"
+              placeholder="填写 (非必填)"
+              style="width: 100%"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <el-row>
+        <el-col :span="24">
+          <el-form-item label="其他需要说明的事项">
+            <el-input
+              v-model="conclusionForm.otherExplanations"
+              type="textarea"
+              :rows="4"
+              placeholder="填写 (非必填)"
+              style="width: 100%"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+  </div>
+</template>
+
+<script>
+  import { getConclusionDetail } from '@/api/taskProgressManage'
+  export default {
+    name: 'Conclusion',
+    props: {
+      project: {
+        type: Object,
+        default: () => {},
+      },
+      isView: {
+        type: Boolean,
+        default: false,
+      },
+    },
+    data() {
+      return {
+        conclusionForm: {
+          pricingCostStructure: '',
+          auditContentMethod: '',
+          costDeductionReason: '',
+          costAuditConclusion: '',
+          defaultConditions: '',
+          otherExplanations: '',
+          conclusionStatus: '',
+          projectId: '',
+        },
+      }
+    },
+    mounted() {
+      this.getConclusionDetail()
+    },
+    methods: {
+      getConclusionDetail() {
+        getConclusionDetail({
+          projectId: this.project.projectId,
+        }).then((res) => {
+          if (res.code === 200) {
+            this.conclusionForm = res.value
+          }
+        })
+      },
+    },
+  }
+</script>
+<style lang="scss" scoped></style>

+ 44 - 26
src/views/costAudit/projectInfo/auditTaskManage/taskProgressManage/detailTabs.vue

@@ -13,13 +13,19 @@
     </div>
 
     <!-- 标签页 -->
-    <el-tabs v-model="activeTab" class="detail-tabs">
+    <el-tabs
+      v-model="activeTab"
+      class="detail-tabs"
+      @tab-click="handleTabClick"
+    >
       <el-tab-pane label="监审立项信息" name="basicInfo">
-        <basicInfoTab :project="currentDetailTask" :is-view="isView" />
+        <basicInfoTab :project="formData.basicInfo" :is-view="isView" />
       </el-tab-pane>
+      <!-- 监审工作方案 -->
       <el-tab-pane label="监审工作方案" name="scenario">
         <el-form
-          :model="workPlan"
+          v-loading="scenarioData.saveScenario"
+          :model="formData.workPlan"
           label-width="150px"
           label-position="top"
           style="width: 50%"
@@ -27,7 +33,7 @@
         >
           <el-form-item label="监审项目基本情况" class="form-section">
             <el-input
-              v-model="workPlan.basicInfo"
+              v-model="formData.workPlan.basicInfo"
               type="textarea"
               :rows="5"
               placeholder="(非必填写)"
@@ -42,7 +48,7 @@
             class="form-section"
           >
             <el-input
-              v-model="workPlan.scopeContent"
+              v-model="formData.workPlan.scopeContent"
               type="textarea"
               :rows="5"
               placeholder="(非必填写)"
@@ -54,7 +60,7 @@
 
           <el-form-item label="监审的步骤和方法" class="form-section">
             <el-input
-              v-model="workPlan.stepsMethods"
+              v-model="formData.workPlan.stepsMethods"
               type="textarea"
               :rows="5"
               placeholder="(非必填写)"
@@ -66,7 +72,7 @@
 
           <el-form-item label="其他有关内容" class="form-section">
             <el-input
-              v-model="workPlan.otherContent"
+              v-model="formData.workPlan.otherContent"
               type="textarea"
               :rows="5"
               placeholder="(非必填写)"
@@ -83,7 +89,7 @@
                 :upload-mode="'multiple'"
                 :max-size="50 * 1024 * 1024"
                 :allowed-types="['xlsx', 'xls', 'doc', 'docx', 'pdf']"
-                :files-list="workPlan.attachmentIds"
+                :files-list="formData.workPlan.attachmentIds"
                 button-text="上传附件"
                 :is-disabled="isView"
               />
@@ -92,25 +98,34 @@
         </el-form>
       </el-tab-pane>
       <el-tab-pane label="报送资料要求" name="material">
-        <materialTab :project="currentDetailTask" :is-view="isView" />
+        <materialTab
+          :project="project"
+          :is-view="isView"
+          :material-data="materialData"
+        />
       </el-tab-pane>
       <el-tab-pane label="成本调查表" name="survey">
-        <surveyTab :project="currentDetailTask" :is-view="isView" />
+        <surveyTab
+          :project="project"
+          :is-view="isView"
+          :survey-data="surveyData"
+        />
       </el-tab-pane>
       <el-tab-pane label="监审文书" name="auditNotice">
         <auditNoticeTab
-          :project="currentDetailTask"
+          :project="project"
           :is-view="isView"
           :document-data="documentData"
         />
       </el-tab-pane>
-      <el-tab-pane label="集体审议" name="discussion"></el-tab-pane>
-      <el-tab-pane label="出具结论" name="conclusion"></el-tab-pane>
+      <el-tab-pane label="集体审议" name="discussion">
+        <meetingTab :project="project" :is-view="isView" />
+      </el-tab-pane>
+      <el-tab-pane label="出具结论" name="conclusion">
+        <conclusionTab :project="project" :is-view="isView"></conclusionTab>
+      </el-tab-pane>
       <el-tab-pane label="工作流程明细" name="process" class="process-tab">
-        <workflowTab
-          :project="currentDetailTask"
-          :is-view="isView"
-        ></workflowTab>
+        <workflowTab :project="project" :is-view="isView"></workflowTab>
       </el-tab-pane>
     </el-tabs>
   </div>
@@ -119,16 +134,24 @@
   import basicInfoTab from '@/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/basicInfoTab.vue'
   import materialTab from '@/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/materialTab.vue'
   import surveyTab from '@/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/surveyTab.vue'
+  import meetingTab from './meetingTab.vue'
+  import conclusionTab from './conclusionTab.vue'
   import workflowTab from './workflowTab.vue'
   import auditNoticeTab from '@/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/auditNoticeTab.vue'
+  import UploadComponent from '@/components/costAudit/UploadComponent.vue'
+  import { taskMixin } from '@/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/index.js'
   export default {
     components: {
       basicInfoTab,
       materialTab,
       surveyTab,
+      meetingTab,
+      conclusionTab,
       workflowTab,
       auditNoticeTab,
+      UploadComponent,
     },
+    mixins: [taskMixin],
     props: {
       project: {
         type: Object,
@@ -141,16 +164,7 @@
     },
     data() {
       return {
-        // 监审工作方案表单
-        workPlan: {
-          basicInfo: '',
-          scopeContent: '',
-          stepsMethods: '',
-          otherContent: '',
-          attachmentIds: [],
-        },
         activeTab: 'process', // 默认选中工作流程明细标签
-        currentDetailTask: null,
         documentData: {
           documentTypes: [],
           selectedDoc: 'notice',
@@ -218,6 +232,10 @@
         },
       }
     },
+    mounted() {
+      this.handleTabClick()
+    },
+
     methods: {
       handleDetailClose() {
         this.$emit('detailClose')

+ 238 - 153
src/views/costAudit/projectInfo/auditTaskManage/taskProgressManage/index.vue

@@ -41,133 +41,59 @@
         </el-form>
       </div>
       <!-- 数据表格 -->
-      <el-table
+      <cost-audit-table
         v-loading="loading"
-        :data="tableData"
-        border
-        style="width: 100%"
-        row-key="id"
-        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
-        default-expand-all
+        :table-data="tableData"
+        :columns="tableColumns"
+        :border="true"
         :row-class-name="getRowClassName"
+        :show-pagination="false"
+        :table-props="{
+          rowKey: 'id',
+          treeProps: { children: 'children', hasChildren: 'hasChildren' },
+          defaultExpandAll: true,
+        }"
       >
-        <el-table-column
-          prop="serialNumber"
-          label="序号"
-          width="60"
-          align="center"
-        >
-          <template slot-scope="scope">
-            <span v-if="scope.row.pid == 0">
-              {{ scope.row.parentIndex }}
-            </span>
-          </template>
-        </el-table-column>
-        <el-table-column
-          prop="year"
-          label="立项年度"
-          width="100"
-          align="center"
-        >
-          <template slot-scope="scope">
-            <span v-if="scope.row.year">{{ scope.row.year }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column
-          prop="projectName"
-          label="成本监审项目名称"
-          align="center"
-          show-overflow-tooltip
-        ></el-table-column>
-        <el-table-column
-          prop="auditedUnitName"
-          label="被监审单位"
-          align="center"
-          show-overflow-tooltip
-        ></el-table-column>
-        <el-table-column
-          prop="auditPeriod"
-          label="监审期间"
-          width="150"
-          align="center"
-        ></el-table-column>
-        <el-table-column
-          prop="sourceType"
-          label="立项来源"
-          width="120"
-          align="center"
-        >
-          <template slot-scope="scope">
-            {{ getDictName('projectProposal', scope.row.sourceType) }}
-          </template>
-        </el-table-column>
-        <el-table-column
-          prop="auditType"
-          label="监审形式"
-          width="120"
-          align="center"
-        >
-          <template slot-scope="scope">
-            {{ getDictName('auditType', scope.row.auditType) }}
-          </template>
-        </el-table-column>
-        <el-table-column prop="status" label="状态" width="100" align="center">
-          <template slot-scope="scope">
-            <span :style="scope.row.style">{{ scope.row.status }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column prop="warning" label="预警" width="80" align="center">
-          <template slot-scope="scope">
-            <span
-              v-if="scope.row.warning === 'red'"
-              class="warning-point red"
-            ></span>
-            <span
-              v-else-if="scope.row.warning === 'yellow'"
-              class="warning-point yellow"
-            ></span>
+        <!-- 预警列自定义内容 -->
+        <template #warning="{ row }">
+          <span v-if="row.warning === 'red'" class="warning-point red"></span>
+          <span
+            v-else-if="row.warning === 'yellow'"
+            class="warning-point yellow"
+          ></span>
+        </template>
+
+        <!-- 操作列自定义内容 -->
+        <template #action="{ row }">
+          <template v-if="row.isSubTask">
+            <el-button
+              size="mini"
+              type="text"
+              @click="handleViewTaskDetail(row)"
+            >
+              查看
+            </el-button>
           </template>
-        </el-table-column>
-        <el-table-column label="操作" width="220" align="center">
-          <template slot-scope="scope">
-            <template v-if="scope.row.isSubTask">
-              <el-button
-                size="mini"
-                type="text"
-                @click="handleViewTaskDetail(scope.row)"
-              >
-                查看
-              </el-button>
-            </template>
-            <template v-else>
-              <el-button
-                size="mini"
-                type="text"
-                @click="handleViewTaskDetail(scope.row)"
-              >
-                详情
-              </el-button>
-              <el-button
-                size="mini"
-                type="text"
-                @click="handlePause(scope.row)"
-              >
-                中止
-              </el-button>
-              <el-button
-                size="mini"
-                type="text"
-                @click="handleDelegate(scope.row)"
-              >
-                代办
-              </el-button>
-              <el-button size="mini" type="text" @click="handleUrge(scope.row)">
-                督办
-              </el-button>
-            </template>
+          <template v-else>
+            <el-button
+              size="mini"
+              type="text"
+              @click="handleViewTaskDetail(row)"
+            >
+              详情
+            </el-button>
+            <el-button size="mini" type="text" @click="handlePause(row)">
+              中止
+            </el-button>
+            <el-button size="mini" type="text" @click="handleDelegate(row)">
+              代办
+            </el-button>
+            <el-button size="mini" type="text" @click="handleUrge(row)">
+              督办
+            </el-button>
           </template>
-        </el-table-column>
-      </el-table>
+        </template>
+      </cost-audit-table>
     </div>
     <!-- 详情内容 -->
     <div v-if="activeView == 'detail'" class="detail-content">
@@ -196,12 +122,12 @@
           </el-form-item>
         </el-form>
       </div>
-      <span slot="footer" class="dialog-footer">
+      <div slot="footer" class="dialog-footer">
         <el-button type="primary" @click="handlePauseFormSubmit">
           确定
         </el-button>
         <el-button @click="handlePauseFormCancel">取消</el-button>
-      </span>
+      </div>
     </el-dialog>
 
     <!-- 任务督办弹窗 -->
@@ -218,12 +144,14 @@
             <el-select
               v-model="urgeForm.remindPerson"
               placeholder="请选择选择督办人员"
+              style="width: 100%"
             >
               <el-option
-                label="张**、李**、王**"
-                value="张**、李**、王**"
+                v-for="(item, index) in userList"
+                :key="index"
+                :label="item.fullname"
+                :value="item.userId"
               ></el-option>
-              <!-- 其他选项 -->
             </el-select>
           </el-form-item>
           <el-form-item label="督办要求:">
@@ -235,17 +163,17 @@
             ></el-input>
           </el-form-item>
           <el-form-item label="发送方式:">
-            <el-radio-group v-model="urgeForm.sendType">
-              <el-radio label="站内消息">站内消息</el-radio>
-              <el-radio label="短信通知">短信通知</el-radio>
-            </el-radio-group>
+            <el-checkbox-group v-model="urgeForm.sendType">
+              <el-checkbox label="站内消息">站内消息</el-checkbox>
+              <el-checkbox label="短信通知">短信通知</el-checkbox>
+            </el-checkbox-group>
           </el-form-item>
         </el-form>
       </div>
-      <span slot="footer" class="dialog-footer">
+      <div slot="footer" class="dialog-footer">
         <el-button @click="handleUrgeCancel">取消</el-button>
         <el-button type="primary" @click="handleUrgeSubmit">发送</el-button>
-      </span>
+      </div>
     </el-dialog>
 
     <!-- 任务代办弹窗 -->
@@ -262,10 +190,14 @@
             <el-select
               v-model="delegateForm.agentPerson"
               placeholder="请选择代理人员"
+              style="width: 100%"
             >
-              <el-option label="张**" value="张**"></el-option>
-              <el-option label="李**" value="李**"></el-option>
-              <!-- 其他选项 -->
+              <el-option
+                v-for="(item, index) in userList"
+                :key="index"
+                :label="item.fullname"
+                :value="item.userId"
+              ></el-option>
             </el-select>
           </el-form-item>
           <el-form-item label="代为内容:">
@@ -277,17 +209,17 @@
             ></el-input>
           </el-form-item>
           <el-form-item label="发送方式:">
-            <el-radio-group v-model="delegateForm.sendType">
-              <el-radio label="站内消息">站内消息</el-radio>
-              <el-radio label="短信通知">短信通知</el-radio>
-            </el-radio-group>
+            <el-checkbox-group v-model="delegateForm.sendType">
+              <el-checkbox label="站内消息">站内消息</el-checkbox>
+              <el-checkbox label="短信通知">短信通知</el-checkbox>
+            </el-checkbox-group>
           </el-form-item>
         </el-form>
       </div>
-      <span slot="footer" class="dialog-footer">
+      <div slot="footer" class="dialog-footer">
         <el-button @click="handleDelegateCancel">取消</el-button>
         <el-button type="primary" @click="handleDelegateSubmit">发送</el-button>
-      </span>
+      </div>
     </el-dialog>
   </div>
 </template>
@@ -296,10 +228,13 @@
   import { taskList } from '@/api/taskProgressManage'
   import { dictMixin } from '@/mixins/useDict'
   import detailTabs from './detailTabs.vue'
-
+  import { getAllUnitList } from '@/api/auditEntityManage'
+  import CostAuditTable from '@/components/costAudit/CostAuditTable.vue'
+  import { getAllUserList } from '@/api/uc'
   export default {
     components: {
       detailTabs,
+      CostAuditTable,
     },
     mixins: [dictMixin],
     data() {
@@ -317,6 +252,91 @@
         },
         currentDetailTask: {},
         tableData: [],
+        // 表格列配置
+        tableColumns: [
+          {
+            prop: 'serialNumber',
+            label: '序号',
+            width: 60,
+            align: 'center',
+            formatter: (row) => {
+              return row.pid == 0 ? row.parentIndex : ''
+            },
+          },
+          {
+            prop: 'year',
+            label: '立项年度',
+            width: 100,
+            align: 'center',
+            formatter: (row) => {
+              return row.year || ''
+            },
+          },
+          {
+            prop: 'projectName',
+            label: '成本监审项目名称',
+            align: 'left',
+            headerAlign: 'center',
+            showOverflowTooltip: true,
+          },
+          {
+            prop: 'auditedUnitId',
+            label: '被监审单位',
+            align: 'left',
+            headerAlign: 'center',
+            showOverflowTooltip: true,
+            formatter: (row) => {
+              return this.getUnitName(row.auditedUnitId)
+            },
+          },
+          {
+            prop: 'auditPeriod',
+            label: '监审期间',
+            width: 150,
+            align: 'center',
+          },
+          {
+            prop: 'sourceType',
+            label: '立项来源',
+            width: 100,
+            align: 'center',
+            formatter: (row) => {
+              return this.getDictName('projectProposal', row.sourceType)
+            },
+          },
+          {
+            prop: 'auditType',
+            label: '监审形式',
+            width: 100,
+            align: 'center',
+            formatter: (row) => {
+              return this.getDictName('auditType', row.auditType)
+            },
+          },
+          {
+            prop: 'status',
+            label: '状态',
+            width: 100,
+            align: 'center',
+            formatter: (row) => {
+              return this.getStatusName(row.status)
+            },
+          },
+          {
+            prop: 'warning',
+            label: '预警',
+            width: 80,
+            align: 'center',
+            slotName: 'warning',
+          },
+          {
+            prop: 'action',
+            label: '操作',
+            width: 220,
+            align: 'center',
+            slotName: 'action',
+          },
+        ],
         // 弹窗状态
         showPauseConfirm: false,
         showPauseForm: false,
@@ -338,18 +358,68 @@
           content: '',
           sendType: '站内消息',
         },
+        unitList: [],
+        userList: [],
       }
     },
     mounted() {
+      this.getAllUnitList()
+      this.getUser()
       this.generateTableData()
     },
     methods: {
+      getUser() {
+        getAllUserList()
+          .then((res) => {
+            this.userList = res.value || []
+          })
+          .catch(() => {})
+      },
+      getStatusName(status) {
+        // 100待提交、200审核中、400办结、300中止
+        switch (status) {
+          case '100':
+            return '待提交'
+          case '200':
+            return '审核中'
+          case '400':
+            return '办结'
+          case '300':
+            return '中止'
+          default:
+            return ''
+        }
+      },
+      getAllUnitList() {
+        getAllUnitList().then((res) => {
+          this.unitList = res.value || []
+        })
+      },
+      getUnitName(unitId) {
+        // 直接处理unitId值,而不是row对象
+        if (unitId && typeof unitId === 'string' && unitId.includes(',')) {
+          // 如果包含逗号,分割成数组并查找对应的unitName
+          const unitIds = unitId.split(',')
+          return unitIds
+            .map((id) => {
+              const unit = this.unitList.find((item) => item.unitId == id)
+              return unit ? unit.unitName : ''
+            })
+            .filter((name) => name) // 过滤空值
+            .join(',')
+        } else {
+          // 单个unitId的情况
+          const unit = this.unitList.find((item) => item.unitId == unitId)
+          return unit ? unit.unitName : ''
+        }
+      },
       generateTableData() {
         taskList({
           projectName: this.searchForm.projectName,
           year: this.searchForm.year,
         }).then((res) => {
           this.tableData = res.value
+          // 移除不需要的属性
           this.tableData = this.removeItemFromTree(this.tableData)
           let parentIndex = 1
           this.tableData.forEach((item, index) => {
@@ -359,26 +429,22 @@
           })
         })
       },
-      handleReset() {
-        this.searchForm = {
-          projectName: '',
-          year: '',
-        }
-        this.generateTableData()
-      },
       removeItemFromTree(treeData) {
         // 边界条件检查
         if (!treeData || !Array.isArray(treeData)) {
           return []
         }
+
         // 创建新数组,避免修改原数据
         return treeData.map((item) => {
           // 创建当前节点的副本
           const newItem = { ...item }
+
           // 如果有hasChildren属性则删除
           if ('hasChildren' in newItem) {
             delete newItem.hasChildren
           }
+
           // 递归处理子节点 先检查children是否存在且为数组
           if (
             newItem.children &&
@@ -387,9 +453,18 @@
           ) {
             newItem.children = this.removeItemFromTree(newItem.children)
           }
+
           return newItem
         })
       },
+      handleReset() {
+        this.searchForm = {
+          projectName: '',
+          year: '',
+        }
+        this.generateTableData()
+      },
+
       getRowClassName({ row }) {
         if (row.isSubTask) {
           return 'sub-task-row'
@@ -445,6 +520,11 @@
       handleUrge(row) {
         console.log('任务督办:', row)
         this.currentTask = row
+        this.urgeForm = {
+          remindPerson: '',
+          content: '',
+          sendType: [],
+        }
         this.showUrgeForm = true
       },
       handleUrgeCancel() {
@@ -452,17 +532,22 @@
         this.urgeForm = {
           remindPerson: '',
           content: '',
-          sendType: '站内消息',
+          sendType: [],
         }
       },
       handleUrgeSubmit() {
-        console.log('提交督办:', this.urgeForm)
+        // 提交前将数组转换为逗号分隔字符串
+        const submitForm = { ...this.urgeForm }
+        if (Array.isArray(submitForm.sendType)) {
+          submitForm.sendType = submitForm.sendType.join(',')
+        }
+        console.log('提交督办:', submitForm)
         // 这里可以添加提交逻辑
         this.showUrgeForm = false
         this.urgeForm = {
           remindPerson: '',
           content: '',
-          sendType: '站内消息',
+          sendType: [],
         }
         this.currentTask = null
         this.$message.success('督办信息已发送')

+ 470 - 0
src/views/costAudit/projectInfo/auditTaskManage/taskProgressManage/meetingTab.vue

@@ -0,0 +1,470 @@
+<template>
+  <!-- 集体审议内容 -->
+  <div class="meeting-section">
+    <!-- 系统记录 -->
+    <div class="system-records">
+      <el-button
+        style="margin-bottom: 20px"
+        plain
+        type="success"
+        icon="el-icon-circle-plus"
+        :disabled="isView"
+        @click="addMeetingRecord"
+      >
+        添加记录
+      </el-button>
+      <CostAuditTable
+        :table-data="meetingRecords"
+        :columns="tableColumns"
+        :show-index="true"
+        :border="true"
+        style="width: 100%"
+        :shouw-pagination="true"
+      >
+        <!-- 附件列自定义内容 -->
+        <template #attachments="{ row }">
+          <el-button
+            type="text"
+            size="small"
+            @click="viewMeetingAttachment(row)"
+          >
+            查看
+          </el-button>
+        </template>
+        <!-- 操作列自定义内容 -->
+        <template #action="{ row }">
+          <el-button
+            type="text"
+            size="small"
+            @click="handleViewMeetingRecord(row)"
+          >
+            查看
+          </el-button>
+          <el-button
+            :disabled="isView"
+            type="text"
+            size="small"
+            @click="editMeetingRecord(row)"
+          >
+            修改
+          </el-button>
+          <el-button
+            type="text"
+            size="small"
+            class="delete-btn"
+            :disabled="isView"
+            @click="deleteMeetingRecord(row.id)"
+          >
+            删除
+          </el-button>
+        </template>
+      </CostAuditTable>
+    </div>
+    <!-- 集体审议记录表单 -->
+    <el-dialog
+      title="集体审议记录"
+      :visible.sync="meetingDialogVisible"
+      width="60%"
+      class="meeting-form-section"
+    >
+      <el-form
+        ref="meetingForm"
+        :model="meetingForm"
+        label-width="120px"
+        class="meeting-form"
+        :disabled="isView"
+      >
+        <el-row :gutter="20">
+          <el-col :span="24">
+            <el-form-item label="审议形式">
+              <el-input
+                v-model="meetingForm.deliberationForm"
+                placeholder="请填写"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="审议时间开始">
+              <el-date-picker
+                v-model="meetingForm.beginTime"
+                type="datetime"
+                placeholder="选择开始时间"
+                style="width: 100%"
+                format="yyyy-MM-dd HH:mm"
+                value-format="yyyy-MM-dd HH:mm"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="审议时间结束">
+              <el-date-picker
+                v-model="meetingForm.endTime"
+                type="datetime"
+                placeholder="选择结束时间"
+                style="width: 100%"
+                format="yyyy-MM-dd HH:mm"
+                value-format="yyyy-MM-dd HH:mm"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="地点">
+              <el-input
+                v-model="meetingForm.location"
+                placeholder="请填写"
+                style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="主持人">
+              <el-select
+                v-model="meetingForm.hostPerson"
+                placeholder="请选择人员"
+                style="width: 100%"
+              >
+                <el-option
+                  v-for="person in personList"
+                  :key="person.id"
+                  :label="person.name"
+                  :value="person.name"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="记录人">
+              <el-select
+                v-model="meetingForm.recordPerson"
+                placeholder="请选择人员"
+                style="width: 100%"
+              >
+                <el-option
+                  v-for="person in personList"
+                  :key="person.id"
+                  :label="person.name"
+                  :value="person.name"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row>
+          <el-col :span="24">
+            <el-form-item label="参加人员">
+              <el-input
+                v-model="meetingForm.participants"
+                placeholder="请填写"
+                style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row>
+          <el-col :span="24">
+            <el-form-item label="审议项目">
+              <el-input
+                v-model="meetingForm.projectName"
+                placeholder="自动获取项目名称"
+                style="width: 100%"
+                disabled
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row>
+          <el-col :span="24">
+            <el-form-item label="监审单位id">
+              <el-input
+                v-model="meetingForm.enterpriseId"
+                placeholder="自动获取监审单位id"
+                style="width: 100%"
+                disabled
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row>
+          <el-col :span="24">
+            <el-form-item label="审议情况">
+              <el-input
+                v-model="meetingForm.deliberationContent"
+                type="textarea"
+                :rows="4"
+                placeholder="填写"
+                style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row>
+          <el-col :span="24">
+            <el-form-item label="审议结论意见">
+              <el-input
+                v-model="meetingForm.conclusionOpinion"
+                type="textarea"
+                :rows="4"
+                placeholder="填写"
+                style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row>
+          <el-col :span="24">
+            <el-form-item label="审议记录附件">
+              <UploadComponent
+                :upload-mode="'multiple'"
+                :files-list="meetingAttachmentList"
+                button-text="选择文件"
+                :is-disabled="isView"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="saveMeetingRecord">确认</el-button>
+        <el-button @click="cancelMeetingRecord">取消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+  import CostAuditTable from '@/components/costAudit/CostAuditTable.vue'
+  import UploadComponent from '@/components/costAudit/UploadComponent.vue'
+  import { getDeliberatePageList } from '@/api/taskProgressManage'
+  import { get } from 'jquery'
+  export default {
+    name: 'MeetingTab',
+    components: { CostAuditTable, UploadComponent },
+    props: {
+      // 父组件传递的参数
+      project: {
+        type: Object,
+        default: () => {},
+      },
+      isView: {
+        type: Boolean,
+        default: false,
+      },
+    },
+    data() {
+      return {
+        meetingDialogVisible: false,
+        // 集体审议相关数据
+        meetingRecords: [
+          {
+            id: '1',
+            deliberationForm: '现场会议',
+            location: '******会议室',
+            hostPerson: '张****',
+            beginTime: '2025-5-21 16:30',
+            hasAttachment: true,
+            enterpriseId: '1',
+            projectId: '1',
+          },
+          {
+            id: '2',
+            deliberationForm: '现场会议',
+            location: '**********',
+            hostPerson: '***********',
+            beginTime: '***********',
+            hasAttachment: true,
+            enterpriseId: '2',
+            projectId: '1',
+          },
+          {
+            id: '3',
+            deliberationForm: '**********',
+            location: '**********',
+            hostPerson: '***********',
+            beginTime: '***********',
+            hasAttachment: true,
+            enterpriseId: '3',
+            projectId: '1',
+          },
+        ],
+
+        // 集体审议表单数据
+        meetingForm: {
+          deliberationForm: '',
+          beginTime: '',
+          endTime: '',
+          location: '',
+          hostPerson: '',
+          recordPerson: '',
+          participants: '',
+          projectName: '',
+          enterpriseId: '',
+          deliberationContent: '',
+          conclusionOpinion: '',
+          attachmentName: '**********审议记录.doc',
+          attachmentIds: '',
+        },
+        // 附件列表
+        meetingAttachmentList: [],
+        // 业务文件夹
+        businessFolder: 'meeting_attachment',
+        // 表格列配置
+        tableColumns: [
+          {
+            prop: 'deliberationForm',
+            label: '审议形式',
+            align: 'left',
+            width: 100,
+          },
+          {
+            prop: 'location',
+            label: '地点',
+            align: 'left',
+          },
+          {
+            prop: 'hostPerson',
+            label: '主持人',
+            align: 'center',
+            width: 120,
+          },
+          {
+            prop: 'beginTime',
+            label: '审议时间',
+            align: 'center',
+            width: 150,
+          },
+          {
+            prop: 'attachments',
+            label: '附件',
+            align: 'center',
+            width: 60,
+            slotName: 'attachments',
+          },
+          {
+            prop: 'action',
+            label: '操作',
+            align: 'center',
+            width: 150,
+            slotName: 'action',
+            showOverflowTooltip: false,
+          },
+        ],
+        // 人员选择列表
+        personList: [
+          { id: '1', name: '张**' },
+          { id: '2', name: '李**' },
+          { id: '3', name: '王**' },
+        ],
+      }
+    },
+    mounted() {
+      this.getMeetingRecords()
+    },
+    methods: {
+      addMeetingRecord() {
+        this.meetingForm = {
+          deliberationForm: '',
+          beginTime: '',
+          endTime: '',
+          location: '',
+          hostPerson: '',
+          recordPerson: '',
+          participants: '',
+          projectName: '',
+          enterpriseId: '',
+          deliberationContent: '',
+          conclusionOpinion: '',
+          attachmentName: '',
+          attachmentIds: '',
+        }
+        // 清空附件列表
+        this.meetingAttachmentList = []
+        this.meetingDialogVisible = true
+      },
+      getMeetingRecords() {
+        getDeliberatePageList({
+          projectId: this.project.id,
+          pageNum: 1,
+          pageSize: 50,
+        }).then((res) => {
+          this.meetingRecords = res.value.value.records
+        })
+      },
+      handleEditMeetingRecord(row) {
+        this.meetingForm = {
+          ...row,
+        }
+        // 处理附件列表回显
+        if (row.attachmentIds) {
+          this.meetingAttachmentList = row.attachmentIds
+            .split(',')
+            .map((id) => ({
+              id: id,
+              fileName: row.attachmentName,
+              status: 'success',
+            }))
+        } else {
+          this.meetingAttachmentList = []
+        }
+        this.meetingDialogVisible = true
+      },
+      handleDeleteMeetingRecord(row) {},
+      handleViewMeetingRecord(row) {
+        this.meetingForm = {
+          ...row,
+        }
+        // 处理附件列表回显
+        if (row.attachmentIds) {
+          this.meetingAttachmentList = row.attachmentIds
+            .split(',')
+            .map((id) => ({
+              id: id,
+              fileName: row.attachmentName,
+              status: 'success',
+            }))
+        } else {
+          this.meetingAttachmentList = []
+        }
+        this.meetingDialogVisible = true
+      },
+      handleCancelMeetingRecord() {},
+      handleSaveMeetingRecord() {},
+      // 移除附件
+      removeMeetingAttachment(index, removedFile, fileList) {
+        this.meetingAttachmentList = fileList
+        // 更新附件ID和名称
+        this.updateAttachmentInfo(fileList)
+      },
+      // 保存附件
+      saveMeetingAttachments(fileList) {
+        this.meetingAttachmentList = fileList
+        // 更新附件ID和名称
+        this.updateAttachmentInfo(fileList)
+      },
+      // 更新附件信息到表单
+      updateAttachmentInfo(fileList) {
+        if (fileList.length > 0) {
+          // 提取附件ID,多个附件用逗号分隔
+          this.meetingForm.attachmentIds = fileList
+            .map((file) => file.id)
+            .join(',')
+          // 设置第一个附件名称作为显示
+          this.meetingForm.attachmentName = fileList[0].fileName
+        } else {
+          this.meetingForm.attachmentIds = ''
+          this.meetingForm.attachmentName = ''
+        }
+      },
+    },
+  }
+</script>
+<style lang="scss" scoped>
+  @import '@/styles/costAudit.scss';
+</style>

+ 156 - 88
src/views/costAudit/projectInfo/auditTaskManage/taskProgressManage/workflowTab.vue

@@ -25,109 +25,49 @@
     </div>
 
     <!-- 流程明细表格 -->
-    <el-table
-      :data="processDetails"
-      border
+    <CostAuditTable
+      :table-data="processDetails"
+      :columns="tableColumns"
+      :show-index="true"
+      :border="true"
       style="width: 100%; margin-top: 20px"
     >
-      <el-table-column
-        type="index"
-        label="序号"
-        width="80"
-        align="center"
-      ></el-table-column>
-      <el-table-column
-        prop="processNodeValue"
-        label="流程环节"
-        width="120"
-        align="center"
-      ></el-table-column>
-      <el-table-column
-        prop="nodeType"
-        label="环节类型"
-        width="100"
-        align="center"
-      >
-        <template slot-scope="scope">
-          {{ getDictName('processNodeType', scope.row.nodeType) }}
-        </template>
-      </el-table-column>
-      <el-table-column
-        prop="mainUserName"
-        label="主办人员"
-        align="center"
-      ></el-table-column>
-      <el-table-column
-        prop="userName"
-        label="从办人员"
-        align="center"
-      ></el-table-column>
-      <el-table-column
-        prop="mainUserNameOpinion"
-        label="办理意见"
-        align="center"
-      ></el-table-column>
-      <el-table-column
-        prop="plannedAuditStartDate"
-        label="要求办结期限"
-        width="120"
-        align="center"
-      ></el-table-column>
-      <el-table-column
-        prop="plannedAuditStartDate"
-        label="开始时间"
-        width="140"
-        align="center"
-      ></el-table-column>
-      <el-table-column
-        prop="plannedAuditEndDate"
-        label="结束时间"
-        width="140"
-        align="center"
-      ></el-table-column>
-      <el-table-column label="操作" width="100" align="center">
-        <template slot-scope="scope">
-          <el-button
-            size="small"
-            type="text"
-            @click="handleStepExplain(scope.row)"
-          >
-            环节说明
-          </el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <!-- 环节说明弹窗 -->
+      <!-- 操作列自定义内容 -->
+      <template #action="{ row }">
+        <el-button size="small" type="text" @click="handleStepExplain(row)">
+          环节明细
+        </el-button>
+      </template>
+    </CostAuditTable>
+    <!-- 环节明细弹窗 -->
     <el-dialog
-      title="环节明"
+      title="环节明细"
       :visible.sync="showStepExplainDialog"
-      width="50%"
+      width="60%"
       :modal="true"
       :close-on-click-modal="false"
     >
       <div class="dialog-content">
-        <el-form ref="stepExplainForm" :model="stepExplainForm">
-          <el-form-item label="说明内容:">
-            <el-input
-              v-model="stepExplainForm.content"
-              type="textarea"
-              rows="8"
-              placeholder="请输入环节说明内容"
-              disabled
-            ></el-input>
-          </el-form-item>
-        </el-form>
+        <CostAuditTable
+          :table-data="executionDetails"
+          :columns="executionTableColumns"
+          :show-index="true"
+          :border="true"
+          style="width: 100%"
+        />
+      </div>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="handleStepExplainClose">关闭</el-button>
       </div>
-      <span slot="footer" class="dialog-footer">
-        <el-button @click="handleStepExplainClose">确定</el-button>
-      </span>
     </el-dialog>
   </div>
 </template>
 <script>
   import { dictMixin } from '@/mixins/useDict'
+  import CostAuditTable from '@/components/costAudit/CostAuditTable.vue'
   export default {
     name: 'ProcessDetail',
+    components: { CostAuditTable },
     mixins: [dictMixin],
     props: {
       // 父组件传递的参数
@@ -245,6 +185,132 @@
         stepExplainForm: {
           content: '',
         },
+        // 执行事项明细数据
+        executionDetails: [
+          {
+            source: '外部',
+            executor: '太原市通用自来水公司',
+            task: '提交材料',
+            execTime: '2025-10-22 09:33',
+            remark: '文字文字文字文字文字',
+          },
+          {
+            source: '内部',
+            executor: '价格科/李梅',
+            task: '通过材料审核',
+            execTime: '2025-10-23 10:10',
+            remark: '文字文字文字文字文字',
+          },
+          {
+            source: '外部',
+            executor: '太原市通用自来水公司',
+            task: '补充成本监审材料',
+            execTime: '2025-10-23 15:08',
+            remark: '补充材料意见补充材料意见',
+          },
+          {
+            source: '内部',
+            executor: '监审部/张国兴',
+            task: '通过实地审核',
+            execTime: '2025-10-23 15:08',
+            remark: '文字文字文字文字文字',
+          },
+          {
+            source: '内部',
+            executor: '监审部/张国兴',
+            task: '告知成本监审初步意见',
+            execTime: '2025-10-23 15:08',
+            remark: '文字文字文字文字文字',
+          },
+        ],
+        // 表格列配置
+        tableColumns: [
+          {
+            prop: 'processNodeValue',
+            label: '流程环节',
+            width: 120,
+            align: 'center',
+          },
+          {
+            prop: 'nodeType',
+            label: '环节类型',
+            width: 100,
+            align: 'center',
+            formatter: (row) =>
+              this.getDictName('processNodeType', row.nodeType),
+          },
+          {
+            prop: 'mainUserName',
+            label: '主办人员',
+            align: 'center',
+          },
+          {
+            prop: 'userName',
+            label: '从办人员',
+            align: 'center',
+          },
+          {
+            prop: 'mainUserNameOpinion',
+            label: '办理意见',
+            align: 'center',
+          },
+          {
+            prop: 'plannedAuditStartDate',
+            label: '要求办结期限',
+            width: 120,
+            align: 'center',
+          },
+          {
+            prop: 'plannedAuditStartDate',
+            label: '开始时间',
+            width: 140,
+            align: 'center',
+          },
+          {
+            prop: 'plannedAuditEndDate',
+            label: '结束时间',
+            width: 140,
+            align: 'center',
+          },
+          {
+            prop: 'action',
+            label: '操作',
+            width: 100,
+            align: 'center',
+            slotName: 'action',
+          },
+        ],
+        // 执行事项表格列配置
+        executionTableColumns: [
+          {
+            prop: 'source',
+            label: '执行来源',
+            width: 100,
+            align: 'center',
+          },
+          {
+            prop: 'executor',
+            label: '执行人',
+            width: 150,
+            align: 'center',
+          },
+          {
+            prop: 'task',
+            label: '执行事项',
+            align: 'center',
+          },
+          {
+            prop: 'execTime',
+            label: '执行时间',
+            width: 150,
+            align: 'center',
+          },
+          {
+            prop: 'remark',
+            label: '备注',
+            align: 'center',
+          },
+        ],
       }
     },
     methods: {
@@ -263,4 +329,6 @@
     },
   }
 </script>
-<style scoped></style>
+<style lang="scss" scoped>
+  @import '@/styles/costAudit.scss';
+</style>

+ 205 - 183
src/views/costAudit/projectInfo/auditTaskManage/taskQueryStatistics/index.vue

@@ -65,90 +65,37 @@
       <div class="statistics-info">
         <span>
           在办事项:
-          <span class="pending-count">**</span>
+          <span class="pending-count">{{ pendingCount }}</span>
         </span>
         <span>
           已结事项:
-          <span class="completed-count">**</span>
+          <span class="completed-count">{{ completedCount }}</span>
         </span>
       </div>
 
       <!-- 数据表格 -->
-      <el-table
+      <cost-audit-table
         v-loading="loading"
-        :data="tableData"
-        border
-        style="width: 100%"
+        :table-data="tableData"
+        :columns="tableColumns"
+        :border="true"
         :row-class-name="getRowClassName"
+        :show-pagination="false"
+        :table-props="{
+          rowKey: 'id',
+          treeProps: { children: 'children', hasChildren: 'hasChildren' },
+          defaultExpandAll: true,
+        }"
       >
-        <el-table-column
-          prop="serialNumber"
-          label="序号"
-          width="60"
-          align="center"
-        ></el-table-column>
-        <el-table-column
-          prop="planYear"
-          label="立项年度"
-          width="100"
-          align="center"
-        ></el-table-column>
-        <el-table-column
-          prop="region"
-          label="立项地区"
-          width="100"
-          align="center"
-        ></el-table-column>
-        <el-table-column
-          prop="projectName"
-          label="成本监审项目名称"
-          align="center"
-          show-overflow-tooltip
-        >
-          <template slot-scope="scope">
-            <span :style="scope.row.style">{{ scope.row.projectName }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column
-          prop="auditedUnit"
-          label="被监审单位"
-          align="center"
-          show-overflow-tooltip
-        ></el-table-column>
-        <el-table-column
-          prop="auditPeriod"
-          label="监审期间"
-          width="150"
-          align="center"
-        ></el-table-column>
-        <el-table-column
-          prop="planSource"
-          label="立项来源"
-          width="120"
-          align="center"
-        ></el-table-column>
-        <el-table-column
-          prop="auditType"
-          label="监审形式"
-          width="120"
-          align="center"
-        ></el-table-column>
-        <el-table-column
-          prop="status"
-          label="状态"
-          width="100"
-          align="center"
-        ></el-table-column>
-        <el-table-column label="操作" width="80" align="center">
-          <template slot-scope="scope">
-            <el-button size="mini" type="text" @click="handleView(scope.row)">
-              查看
-            </el-button>
-          </template>
-        </el-table-column>
-      </el-table>
+        <!-- 操作列自定义模板 -->
+        <template #operation="{ row }">
+          <el-button size="mini" type="text" @click="handleView(row)">
+            查看
+          </el-button>
+        </template>
+      </cost-audit-table>
     </div>
 
     <!-- 详情内容 -->
@@ -164,110 +111,31 @@
 <script>
   import { dictMixin, regionMixin } from '@/mixins/useDict'
   import detailTabs from '@/views/costAudit/projectInfo/auditTaskManage/taskProgressManage/detailTabs.vue'
+  import { taskList } from '@/api/taskProgressManage'
+  import { getAllUnitList } from '@/api/auditEntityManage'
+  import CostAuditTable from '@/components/costAudit/CostAuditTable.vue'
 
   export default {
     components: {
       detailTabs,
+      CostAuditTable,
     },
     mixins: [dictMixin, regionMixin],
     data() {
       return {
         dictData: {
           auditType: [], //监审形式
+          projectProposal: [], //立项来源
         },
         activeView: 'list',
         loading: false,
+        isView: true,
         searchForm: {
           year: '',
           areaCode: '',
           status: '全部',
           projectName: '',
         },
-        projectList: [
-          // 示例数据
-          {
-            id: 1,
-            serialNumber: 1,
-            planYear: '2025年',
-            region: '山西省',
-            projectName: '省内油气管道运输成本监审',
-            auditedUnit: '山西省油气管道公司、太原市油气公司',
-            auditPeriod: '2022-2024年',
-            planSource: '年度计划外',
-            auditType: '定调价监审',
-            status: '实地审核',
-            isSubTask: false,
-            subTasks: [
-              {
-                id: 101,
-                serialNumber: '',
-                planYear: '',
-                region: '',
-                projectName: '子任务',
-                auditedUnit: '山西省油气管道公司',
-                auditPeriod: '2022-2024年',
-                planSource: '',
-                auditType: '',
-                status: '审核中',
-                isSubTask: true,
-              },
-              {
-                id: 102,
-                serialNumber: '',
-                planYear: '',
-                region: '',
-                projectName: '子任务',
-                auditedUnit: '太原市油气公司',
-                auditPeriod: '2022-2024年',
-                planSource: '',
-                auditType: '',
-                status: '审核通过',
-                isSubTask: true,
-              },
-            ],
-          },
-          {
-            id: 2,
-            serialNumber: 2,
-            planYear: '2024年',
-            region: '太原市',
-            projectName: '太原市电网输配电成本监审',
-            auditedUnit: '太原市热电厂、****热电厂',
-            auditPeriod: '2021-2023年',
-            planSource: '年度计划内',
-            auditType: '定期监审',
-            status: '办结',
-            isSubTask: false,
-            subTasks: [
-              {
-                id: 201,
-                serialNumber: '',
-                planYear: '',
-                region: '',
-                projectName: '子任务',
-                auditedUnit: '太原市热电厂',
-                auditPeriod: '2021-2023年',
-                planSource: '',
-                auditType: '',
-                status: '办结',
-                isSubTask: true,
-              },
-              {
-                id: 202,
-                serialNumber: '',
-                planYear: '',
-                region: '',
-                projectName: '子任务',
-                auditedUnit: '****热电厂',
-                auditPeriod: '2021-2023年',
-                planSource: '',
-                auditType: '',
-                status: '办结',
-                isSubTask: true,
-              },
-            ],
-          },
-        ],
         tableData: [],
         // 统计数据
         statistics: {
@@ -275,11 +143,102 @@
           completed: 0,
         },
         currentDetailTask: {},
+        unitList: [],
+        // 表格列配置
+        tableColumns: [
+          {
+            prop: 'serialNumber',
+            label: '序号',
+            width: 60,
+            align: 'center',
+            formatter: (row) => {
+              return row.pid == 0 ? row.parentIndex : ''
+            },
+          },
+          {
+            prop: 'year',
+            label: '立项年度',
+            width: 100,
+            align: 'center',
+            formatter: (row) => {
+              return row.year || ''
+            },
+          },
+          {
+            prop: 'region',
+            label: '立项地区',
+            width: 100,
+            align: 'center',
+          },
+          {
+            prop: 'projectName',
+            label: '成本监审项目名称',
+            showOverflowTooltip: true,
+          },
+          {
+            prop: 'auditedUnitId',
+            label: '被监审单位',
+            showOverflowTooltip: true,
+            formatter: (row) => {
+              return this.getUnitName(row.auditedUnitId)
+            },
+          },
+          {
+            prop: 'auditPeriod',
+            label: '监审期间',
+            width: 150,
+            align: 'center',
+          },
+          {
+            prop: 'sourceType',
+            label: '立项来源',
+            width: 120,
+            align: 'center',
+            formatter: (row) => {
+              return this.getDictName('projectProposal', row.sourceType)
+            },
+          },
+          {
+            prop: 'auditType',
+            label: '监审形式',
+            width: 120,
+            align: 'center',
+            formatter: (row) => {
+              return this.getDictName('auditType', row.auditType)
+            },
+          },
+          {
+            prop: 'status',
+            label: '状态',
+            width: 100,
+            align: 'center',
+            formatter: (row) => {
+              return this.getStatusName(row.status)
+            },
+          },
+          {
+            prop: 'operation',
+            label: '操作',
+            width: 80,
+            align: 'center',
+            slotName: 'operation',
+          },
+        ],
       }
     },
+    computed: {
+      pendingCount() {
+        // 计算在办任务数量(非办结状态)
+        return this.tableData.filter((item) => item.status !== 400).length
+      },
+      completedCount() {
+        // 计算办结任务数量
+        return this.tableData.filter((item) => item.status === 400).length
+      },
+    },
     mounted() {
+      this.getAllUnitList()
       this.generateTableData()
-      this.calculateStatistics()
     },
     methods: {
       handleReset() {
@@ -291,21 +250,94 @@
         }
         this.generateTableData()
       },
+      getAllUnitList() {
+        getAllUnitList().then((res) => {
+          this.unitList = res.value || []
+        })
+      },
+      getUnitName(unitId) {
+        // 直接处理unitId值
+        if (unitId && typeof unitId === 'string' && unitId.includes(',')) {
+          // 如果包含逗号,分割成数组并查找对应的unitName
+          const unitIds = unitId.split(',')
+          return unitIds
+            .map((id) => {
+              const unit = this.unitList.find((item) => item.unitId == id)
+              return unit ? unit.unitName : ''
+            })
+            .filter((name) => name) // 过滤空值
+            .join('、')
+        } else {
+          // 单个unitId的情况
+          const unit = this.unitList.find((item) => item.unitId == unitId)
+          return unit ? unit.unitName : ''
+        }
+      },
+      getStatusName(status) {
+        // 100待提交、200审核中、400办结、300中止
+        switch (status) {
+          case '100':
+            return '待提交'
+          case '200':
+            return '审核中'
+          case '400':
+            return '办结'
+          case '300':
+            return '中止'
+          default:
+            return status
+        }
+      },
       generateTableData() {
-        // 将主任务和子任务展平为表格数据
-        const data = []
-        this.projectList.forEach((project) => {
-          data.push(project)
-          if (project.subTasks && project.subTasks.length > 0) {
-            project.subTasks.forEach((subTask) => {
-              data.push({
-                ...subTask,
-                style: { paddingLeft: '40px' },
-              })
+        this.loading = true
+        taskList({
+          projectName: this.searchForm.projectName,
+          year: this.searchForm.year,
+        })
+          .then((res) => {
+            this.tableData = res.value
+            // 移除不需要的属性
+            this.tableData = this.removeItemFromTree(this.tableData)
+            let parentIndex = 1
+            this.tableData.forEach((item, index) => {
+              if (item.pid == 0) {
+                item.parentIndex = parentIndex++
+              }
             })
+            this.loading = false
+          })
+          .catch(() => {
+            this.loading = false
+            this.$message.error('获取数据失败')
+          })
+      },
+      removeItemFromTree(treeData) {
+        // 边界条件检查
+        if (!treeData || !Array.isArray(treeData)) {
+          return []
+        }
+
+        // 创建新数组,避免修改原数据
+        return treeData.map((item) => {
+          // 创建当前节点的副本
+          const newItem = { ...item }
+
+          // 如果有hasChildren属性则删除
+          if ('hasChildren' in newItem) {
+            delete newItem.hasChildren
+          }
+
+          // 递归处理子节点 先检查children是否存在且为数组
+          if (
+            newItem.children &&
+            Array.isArray(newItem.children) &&
+            newItem.children.length > 0
+          ) {
+            newItem.children = this.removeItemFromTree(newItem.children)
           }
+
+          return newItem
         })
-        this.tableData = data
       },
       getRowClassName({ row }) {
         if (row.isSubTask) {
@@ -314,6 +346,7 @@
         return ''
       },
       handleView(row) {
+        console.log('查看任务:', row)
         this.currentDetailTask = row
         this.activeView = 'detail'
       },
@@ -325,24 +358,12 @@
         let pendingCount = 0
         let completedCount = 0
 
-        this.projectList.forEach((project) => {
-          // 计算主任务
-          if (project.status === '办结') {
+        this.tableData.forEach((item) => {
+          if (item.status === '办结') {
             completedCount++
           } else {
             pendingCount++
           }
-
-          // 计算子任务
-          if (project.subTasks && project.subTasks.length > 0) {
-            project.subTasks.forEach((subTask) => {
-              if (subTask.status === '办结') {
-                completedCount++
-              } else {
-                pendingCount++
-              }
-            })
-          }
         })
 
         this.statistics = {
@@ -372,6 +393,7 @@
 
   .statistics-info {
     text-align: right;
+    margin-bottom: 20px;
   }
 
   .statistics-info span {