Browse Source

fix:编写综合查询页面-调用列表接口和显示详情弹窗,处理状态码是401的错误跳转登录页面

luzhixia 3 weeks ago
parent
commit
d9640c6279

+ 31 - 1
src/components/costAudit/CostAuditTable.vue

@@ -14,6 +14,7 @@
         :span-method="spanMethod || undefined"
         v-bind="tableProps"
         :row-class-name="processedRowClassName"
+        :row-style="processedRowStyle"
         @selection-change="handleSelectionChange"
         @row-click="handleRowClick"
         @row-dblclick="handleRowDblClick"
@@ -71,7 +72,7 @@
             <span v-else>{{ column.label }}</span>
           </template>
 
-          <template #default="{ row }">
+          <template #default="{ row, $index }">
             <!-- 处理格式化函数 -->
             <span
               v-if="column.formatter && typeof column.formatter === 'function'"
@@ -105,6 +106,7 @@
               :name="column.slotName"
               :row="row"
               :column="column"
+              :index="$index"
             />
             <span v-else>
               {{ row[column.prop] }}
@@ -285,6 +287,12 @@
         type: [Function, String],
         default: () => '',
       },
+
+      // 行样式函数或对象
+      rowStyle: {
+        type: [Function, Object],
+        default: () => ({}),
+      },
     },
 
     computed: {
@@ -327,6 +335,28 @@
           return [externalClass, internalClass].filter(Boolean).join(' ')
         }
       },
+
+      // 处理行样式
+      processedRowStyle() {
+        return ({ row, rowIndex }) => {
+          // 处理外部传入的样式
+          let externalStyle = {}
+          if (typeof this.rowStyle === 'function') {
+            externalStyle = this.rowStyle({ row, rowIndex })
+          } else if (typeof this.rowStyle === 'object') {
+            externalStyle = this.rowStyle
+          }
+
+          // 处理内部状态样式
+          let internalStyle = {}
+          if (row.status === 0) {
+            internalStyle = { opacity: 0.6, cursor: 'not-allowed' }
+          }
+
+          // 合并样式
+          return { ...externalStyle, ...internalStyle }
+        }
+      },
     },
 
     methods: {

+ 14 - 15
src/utils/request.js

@@ -54,21 +54,20 @@ const handleCode = (code, msg) => {
       }
       break
     case noPermissionCode:
-      store.getters['user/accessToken'] &&
-        store
-          .dispatch('user/logout')
-          .then(() => {
-            if (recordRoute) {
-              const fullPath = router.currentRoute.fullPath
-              router.push(`/login?redirect=${fullPath}`)
-            } else {
-              router.push('/login')
-            }
-          })
-          .catch(() => {
-            // logout时可能因为token过期报401错误,此时用href跳转到login页面
-            window.location.href = '/login'
-          })
+      store
+        .dispatch('user/logout')
+        .then(() => {
+          if (recordRoute) {
+            const fullPath = router.currentRoute.fullPath
+            router.push(`/login?redirect=${fullPath}`)
+          } else {
+            router.push('/login')
+          }
+        })
+        .catch(() => {
+          // logout时可能因为token过期报401错误,此时用href跳转到login页面
+          window.location.href = '/login'
+        })
       break
     default:
       if (Number(code) === 500) {

+ 5 - 3
src/views/costAudit/baseInfo/auditDocNoManage/index.vue

@@ -289,7 +289,8 @@
                       placeholder="请输入"
                       type="number"
                       min="1"
-                      max="20"
+                      max="99999"
+                      show-word-limit
                     ></el-input>
                   </el-form-item>
                 </el-col>
@@ -303,6 +304,7 @@
                       placeholder="请输入"
                       type="number"
                       min="0"
+                      max="99999"
                       show-word-limit
                     ></el-input>
                   </el-form-item>
@@ -404,7 +406,7 @@
           alias: '',
           currentValue: '',
           rulePattern: '{prefixText}成审 {year} {currentValue}号',
-          generateType: '',
+          generateType: 'incremental',
           serialLength: 5,
           initialValue: 1,
           // step: 1,
@@ -598,7 +600,7 @@
           alias: '',
           currentValue: '',
           rulePattern: '{prefixText}成审 {year} {currentValue}号',
-          generateType: '',
+          generateType: 'incremental',
           serialLength: 5,
           initialValue: 1,
           // step: 1,

+ 10 - 3
src/views/costAudit/baseInfo/costFormManage/index.vue

@@ -229,12 +229,18 @@
               target: 'formData.surveyTemplateNameYw',
             }"
             placeholder="请输入调查表名称"
+            clearable
+            maxlength="30"
+            show-word-limit
           />
         </template>
         <template #surveyTemplateNameYw>
           <el-input
             v-model="formData.surveyTemplateNameYw"
             placeholder="请输入调查表英文名称"
+            clearable
+            maxlength="30"
+            show-word-limit
           />
         </template>
         <template #templateType>
@@ -251,7 +257,7 @@
         <template #remarks>
           <el-input v-model="formData.remarks" type="textarea"
           placeholder="请输入说明,填写调查表的业务说明、填报指引等内容" type:
-          rows='4' maxlength="200" />
+          rows='4' maxlength="500" show-word-limit />
         </template>
       </CostAuditForm>
     </CostAuditDialog>
@@ -334,7 +340,7 @@
           ],
           surveyTemplateName: [
             { required: true, message: '请输入调查表名称', trigger: 'blur' },
-            { max: 50, message: '长度不能超过50个字符', trigger: 'blur' },
+            { max: 30, message: '长度不能超过30个字符', trigger: 'blur' },
           ],
           surveyTemplateNameYw: [
             {
@@ -433,8 +439,9 @@
             props: {
               type: 'textarea',
               rows: 4,
-              maxlength: 200,
+              maxlength: 500,
               placeholder: '请输入说明,填写调查表的业务说明、填报指引等内容',
+              showWordLimit: true,
             },
           },
         ]

+ 7 - 1
src/views/costAudit/baseInfo/financeSheetManage/index.vue

@@ -230,12 +230,18 @@
               target: 'formData.surveyTemplateNameYw',
             }"
             placeholder="请输入财务表名称"
+            clearable
+            maxlength="30"
+            show-word-limit
           />
         </template>
         <template #surveyTemplateNameYw>
           <el-input
             v-model="formData.surveyTemplateNameYw"
             placeholder="请输入财务表英文名称"
+            clearable
+            maxlength="30"
+            show-word-limit
           />
         </template>
         <template #templateType>
@@ -252,7 +258,7 @@
         <template #remarks>
           <el-input v-model="formData.remarks" type="textarea"
           placeholder="请输入说明,填写财务表的业务说明、填报指引等内容" type:
-          rows='4' maxlength="200" />
+          rows='4' maxlength="500" show-word-limit />
         </template>
       </CostAuditForm>
     </CostAuditDialog>

+ 155 - 27
src/views/costAudit/baseInfo/statistics/comprehensiveQuery.vue

@@ -7,7 +7,8 @@
           <el-input
             v-model="searchForm.projectName"
             placeholder="请输入项目名称"
-            style="width: 150px"
+            style="width: 200px"
+            clearable
           ></el-input>
         </el-form-item>
         <el-form-item label="监审期间:">
@@ -16,6 +17,7 @@
             type="year"
             placeholder="选择开始年份"
             style="width: 150px"
+            clearable
           ></el-date-picker>
           <span style="margin: 0 5px">~</span>
           <el-date-picker
@@ -23,13 +25,15 @@
             type="year"
             placeholder="选择结束年份"
             style="width: 150px"
+            clearable
           ></el-date-picker>
         </el-form-item>
         <el-form-item label="被监审单位:">
           <el-input
             v-model="searchForm.auditedUnit"
             placeholder="请输入被监审单位"
-            style="width: 150px"
+            style="width: 200px"
+            clearable
           ></el-input>
         </el-form-item>
         <el-form-item label="立项年度:">
@@ -38,6 +42,7 @@
             type="year"
             placeholder="选择立项年度"
             style="width: 150px"
+            clearable
           ></el-date-picker>
         </el-form-item>
         <el-form-item>
@@ -62,21 +67,35 @@
         :columns="columns"
         :pagination="pagination"
         :show-pagination="true"
-        :show-index="true"
+        :show-index="false"
         :border="true"
-        :stripe="true"
+        :stripe="false"
         :span-method="handleSpanMethod"
-        :processed-row-class-name="processedRowClassName"
+        :row-style="rowStyle"
         @pagination-change="handlePaginationChange"
       >
+        <template #index="{ row, index }">
+          {{ getParentNodeIndex(row, index) }}
+        </template>
+
         <!-- 项目名称链接 -->
         <template #projectName="{ row }">
-          <a href="javascript:;" class="link-text">{{ row.projectName }}</a>
+          <a
+            href="javascript:;"
+            class="link-text"
+            @click="handleViewTaskDetail(row)"
+          >
+            {{ row.projectName }}
+          </a>
         </template>
 
         <!-- 下载按钮组 -->
         <template #download="{ row }">
-          <el-button type="text" size="small" @click="handleDownloadTask(row)">
+          <el-button
+            type="text"
+            size="small"
+            @click="handleMessage(row, 'chengben')"
+          >
             监审任务
           </el-button>
           <el-button type="text" size="small" @click="handleDownloadFile(row)">
@@ -85,19 +104,46 @@
         </template>
       </cost-audit-table>
     </div>
+
+    <!-- 成本监审任务制定弹窗(用于“任务详情”只读查看) -->
+    <task-customized-release-dialog
+      :visible.sync="taskReleaseDialogVisible"
+      :project="project"
+      :is-view="true"
+      @backToList="taskReleaseDialogVisible = false"
+      @close="taskReleaseDialogVisible = false"
+    />
+    <!-- 成本监审信息弹窗(用于“查看”按钮) -->
+    <cbjs-info
+      :id="cbjsInfoData && cbjsInfoData.id"
+      :selected-project="cbjsInfoData"
+      :visible.sync="cbjsInfoVisible"
+      :current-node="cbjsInfoData && cbjsInfoData.currentNode"
+      :current-status="cbjsInfoData && cbjsInfoData.status"
+    />
   </div>
 </template>
 
 <script>
   import CostAuditTable from '@/components/costAudit/CostAuditTable.vue'
   import { getReviewTaskList } from '@/api/audit/auditIndex'
+  import { dictMixin } from '@/mixins/useDict'
+  import TaskCustomizedReleaseDialog from '@/components/task/TaskCustomizedReleaseDialog.vue'
+  import cbjsInfo from '@/components/task/cbjsInfo.vue'
+  import { getCostProjectDetail } from '@/api/taskCustomizedRelease.js'
   export default {
     name: 'ComprehensiveQuery',
     components: {
       CostAuditTable,
+      TaskCustomizedReleaseDialog,
+      cbjsInfo,
     },
+    mixins: [dictMixin],
     data() {
       return {
+        dictData: {
+          auditType: [], //监审形式
+        },
         // 搜索表单数据
         searchForm: {
           projectName: '',
@@ -113,6 +159,12 @@
         // 表格列配置
         columns: [
           {
+            prop: 'index',
+            label: '序号',
+            width: 100,
+            slotName: 'index',
+          },
+          {
             prop: 'year',
             label: '立项年度',
             width: 100,
@@ -126,6 +178,8 @@
             prop: 'projectName',
             label: '成本监审项目名称',
             slotName: 'projectName',
+            align: 'left',
+            headerAlign: 'center',
           },
           {
             prop: 'auditObject',
@@ -134,16 +188,19 @@
           {
             prop: 'auditPeriod',
             label: '监审期间',
-            width: 120,
+            width: 200,
           },
           {
             prop: 'auditType',
             label: '监审形式',
             width: 120,
+            formatter: (row) => this.getDictName('auditType', row.auditType),
           },
           {
             prop: 'orgName',
             label: '监审主体',
+            align: 'left',
+            headerAlign: 'center',
           },
           {
             label: '下载',
@@ -157,6 +214,13 @@
           pageSize: 10,
           total: 5,
         },
+        // 任务详情弹窗相关
+        taskReleaseDialogVisible: false,
+        project: {},
+        isView: true,
+        // 成本监审信息弹窗相关
+        cbjsInfoVisible: false,
+        cbjsInfoData: null,
       }
     },
     mounted() {
@@ -180,7 +244,6 @@
           if (response.state && response.value) {
             // 获取记录列表
             const records = response.value.records || []
-            console.log('原始数据:', records)
             // 展平数据并添加行合并标记
             this.auditProjectList = []
             this.rowSpanMap = {} // 用于存储需要合并的行数
@@ -225,8 +288,6 @@
 
             // 设置总行数
             this.pagination.total = this.auditProjectList.length
-            console.log('处理后的数据:', this.auditProjectList)
-            console.log('行合并映射:', this.rowSpanMap)
           } else {
             this.auditProjectList = []
             this.rowSpanMap = {}
@@ -282,30 +343,97 @@
         // 这里实现下载逻辑
         this.$message.success('监审卷宗功能待实现')
       },
-      // 处理表格行合并
+      // 查看任务详情
+      handleViewTaskDetail(row) {
+        // 使用成本监审任务制定弹窗(只读)
+        this.openTaskReleaseDialog(row)
+      },
+      // 打开成本监审任务制定弹窗(只读查看)
+      openTaskReleaseDialog(row) {
+        if (!row) return
+        const projectId = row.projectId || row.id || ''
+        if (!projectId) {
+          this.$message &&
+            this.$message.warning &&
+            this.$message.warning('缺少项目ID,无法查看详情')
+          return
+        }
+        this.isView = true
+        getCostProjectDetail({ id: projectId })
+          .then((res) => {
+            this.project = (res && res.value) || {}
+            this.taskReleaseDialogVisible = true
+          })
+          .catch(() => {
+            // 回退:接口失败时至少展示当前行数据
+            this.project = row || {}
+            this.taskReleaseDialogVisible = true
+          })
+      },
+      // 查看成本监审信息
+      handleMessage(row, type) {
+        if (type === 'chengben') {
+          this.cbjsInfoData = row
+          this.cbjsInfoVisible = true
+        }
+      },
+      getParentNodeIndex(row, index) {
+        // 过滤出所有可见的行(isParent为false)
+        const visibleRows = this.auditProjectList.filter(
+          (item) => !item.isParent
+        )
+        // 查找当前行在可见行中的索引
+        const visibleIndex = visibleRows.findIndex((item) => item.id === row.id)
+        // 返回序号(索引+1),如果找不到则返回原始索引+1作为备选
+        return visibleIndex !== -1 ? visibleIndex + 1 : index + 1
+      },
+      // 隐藏所有 isParent 为 true 的父行
+      rowStyle({ row, rowIndex }) {
+        if (row.isParent) {
+          // display:none + height:0 + padding:0,彻底隐藏不占空间
+          return {
+            display: 'none',
+            height: '0px !important',
+            padding: '0px !important',
+            border: 'none !important',
+          }
+        }
+        return {}
+      },
+
+      // 处理合并单元格逻辑:父行隐藏后,让第一个子行承接合并逻辑
       handleSpanMethod({ row, column, rowIndex, columnIndex }) {
-        // 需要合并的列:立项年度、监审地区、成本监审项目名称
         const mergeColumns = ['year', 'areaName', 'projectName']
         const columnProp = column.property
-        // 如果是需要合并的列
         if (mergeColumns.includes(columnProp)) {
-          if (row.isParent) {
-            // 父项合并显示
-            const spanCount = this.rowSpanMap[row.id] || 1
-            return { rowspan: spanCount, colspan: 1 }
-          } else if (row.parentId) {
-            // 子项隐藏这些列
-            return { rowspan: 0, colspan: 0 }
+          // 找到当前子行对应的父行(如果父行已隐藏)
+          let parentRow = row.isParent
+            ? row
+            : this.auditProjectList.find((item) => item.id === row.parentId)
+          if (parentRow) {
+            const spanCount = this.rowSpanMap[parentRow.id] || 1
+            // 让第一个子行承接合并(父行隐藏,子行显示合并单元格)
+            if (
+              row.parentId === parentRow.id &&
+              this.isFirstChild(row.parentId, rowIndex)
+            ) {
+              return { rowspan: spanCount - 1, colspan: 1 } // spanCount-1 是子行数量
+            } else if (!row.isParent) {
+              // 其他子行隐藏合并列
+              return { rowspan: 0, colspan: 0 }
+            }
           }
         }
         return { rowspan: 1, colspan: 1 }
       },
-      processedRowClassName({ row, column, rowIndex, columnIndex }) {
-        // 需要合并的列:立项年度、监审地区、成本监审项目名称
-        const mergeColumns = ['year', 'areaName', 'projectName']
-        if (!mergeColumns.includes(column.property)) {
-          return row.isParent ? 'parent-row' : 'show-row'
-        }
+
+      // 新增辅助方法:判断是否是父行下的第一个子行
+      isFirstChild(parentId, currentIndex) {
+        const parentIndex = this.auditProjectList.findIndex(
+          (item) => item.id === parentId
+        )
+        // 第一个子行索引 = 父行索引 + 1
+        return currentIndex === parentIndex + 1
       },
     },
   }