Explorar o código

fix: 企业报送资料补充材料要求格式上传附件,可选择模版

shiyanyu hai 1 mes
pai
achega
11ea886436

+ 23 - 1
src/components/costAudit/CostAuditDialog.vue

@@ -13,7 +13,7 @@
     :close-on-press-escape="closeOnPressEscape"
     :show-close="showClose"
     :before-close="handleBeforeClose"
-    :z-index="9999"
+    :z-index="effectiveZIndex"
     v-bind="mergedDialogProps"
     @open="handleOpen"
     @close="handleClose"
@@ -45,6 +45,8 @@
 </template>
 
 <script>
+  import PopupManager from 'element-ui/lib/utils/popup'
+
   export default {
     name: 'CostAuditDialog',
     props: {
@@ -154,6 +156,11 @@
         default: true,
       },
     },
+    data() {
+      return {
+        currentZIndex: null,
+      }
+    },
     computed: {
       mergedDialogProps() {
         return {
@@ -162,6 +169,10 @@
           'append-to-body': true,
         }
       },
+      effectiveZIndex() {
+        // 使用动态计算的zIndex优先,否则使用传入的zIndex
+        return this.currentZIndex || this.zIndex
+      },
     },
     methods: {
       // 处理弹窗打开前的钩子
@@ -171,6 +182,17 @@
 
       // 处理弹窗打开
       handleOpen() {
+        // 打开时获取下一个可用的全局zIndex,确保位于最顶层
+        try {
+          const next =
+            PopupManager && typeof PopupManager.nextZIndex === 'function'
+              ? PopupManager.nextZIndex()
+              : this.zIndex || 2000
+          // 如果外部已传更高的zIndex,则取更高值
+          this.currentZIndex = Math.max(next, this.zIndex || 0)
+        } catch (e) {
+          this.currentZIndex = this.zIndex || 2000
+        }
         this.$emit('open')
       },
 

+ 33 - 3
src/views/EntDeclaration/auditTaskManagement/components/DataRequirementsTab.vue

@@ -109,7 +109,7 @@
       <el-table-column prop="operation" label="操作" width="220" align="center">
         <template slot-scope="scope">
           <template v-if="!scope.row.isCategoryHeader">
-            <template v-if="scope.row.formatRequired !== '3'">
+            <template v-if="String(scope.row.formatRequired) !== '3'">
               <el-button
                 v-if="scope.row.isUpload === 1 || scope.row.isUpload === '1'"
                 type="text"
@@ -134,12 +134,18 @@
                 type="text"
                 size="small"
                 :disabled="isViewMode"
-                @click="$emit('handleFileUpload', scope.row)"
+                @click="
+                  $emit(
+                    'handleFileUpload',
+                    scope.row,
+                    getUploadAccept(scope.row)
+                  )
+                "
               >
                 上传
               </el-button>
             </template>
-            <template v-if="scope.row.formatRequired == '3'">
+            <template v-else>
               <el-button
                 v-if="scope.row.isUpload === 1 || scope.row.isUpload === '1'"
                 type="text"
@@ -195,6 +201,30 @@
     },
 
     methods: {
+      // 根据资料类型返回上传accept白名单
+      getUploadAccept(row) {
+        const fmt = row && row.formatRequired
+        const fmtStr = fmt != null ? String(fmt).toLowerCase() : ''
+        if (
+          fmtStr === '1' ||
+          fmtStr.includes('doc') ||
+          fmtStr.includes('word') ||
+          fmtStr.includes('pdf') ||
+          fmtStr.includes('文档')
+        ) {
+          return '.pdf,.doc,.docx'
+        }
+        if (
+          fmtStr === '2' ||
+          fmtStr.includes('excel') ||
+          fmtStr.includes('xls') ||
+          fmtStr.includes('xlsx') ||
+          fmtStr.includes('表格')
+        ) {
+          return '.xls,.xlsx'
+        }
+        return '.pdf,.doc,.docx,.xls,.xlsx'
+      },
       getRowClassName(data) {
         if (data.row.isCategoryHeader) {
           return 'category-header-row'

+ 295 - 31
src/views/EntDeclaration/auditTaskManagement/taskFillIn.vue

@@ -4,6 +4,7 @@
     :size="drawerSize"
     :with-header="true"
     :modal="true"
+    style="z-index: 9000"
     :close-on-click-modal="false"
     :show-close="true"
     @close="handleDrawerClose"
@@ -146,6 +147,7 @@
         title="补充材料"
         :visible.sync="materialDialogVisible"
         width="600px"
+        style="z-index: 10000"
         :close-on-click-modal="false"
         :modal="false"
         append-to-body
@@ -214,10 +216,12 @@
               :file-list="materialForm.fileList"
               :limit="1"
               :on-exceed="handleMaterialExceed"
+              :accept="uploadAccept"
             >
               <el-button
                 v-show="
-                  !materialForm.fileList || materialForm.fileList.length === 0
+                  !isTemplateFormat &&
+                  (!materialForm.fileList || materialForm.fileList.length === 0)
                 "
                 size="small"
                 type="primary"
@@ -225,6 +229,15 @@
               >
                 选择文件
               </el-button>
+              <el-button
+                v-if="isTemplateFormat"
+                size="small"
+                type="primary"
+                :disabled="isViewMode"
+                @click.stop="openLegalDialog"
+              >
+                选择模版
+              </el-button>
               <!-- <div slot="tip" class="el-upload__tip">
                 最多上传1个文件,支持 pdf, doc, docx, xls, xlsx, csv 格式,单个文件不超过50MB
               </div> -->
@@ -253,6 +266,43 @@
         </div>
       </el-dialog>
 
+      <!-- 预置模版选择弹窗 -->
+      <!-- <legal-dialog
+        v-if="legalDialogMounted"
+        :visible.sync="legalDialogVisible"
+        @confirm="handleLegalConfirm"
+        @close="legalDialogVisible = false"
+      /> -->
+
+      <!-- 使用 CostAuditTable 的通用选择模版弹窗 -->
+      <CostAuditDialog
+        v-if="costAuditDialogVisible"
+        :title="'选择模板'"
+        :visible="costAuditDialogVisible"
+        width="50%"
+        style="z-index: 11000"
+        :close-on-click-modal="false"
+        :confirm-loading="costAuditSubmitting"
+        @confirm="submitCostAuditTemplate"
+        @cancel="costAuditDialogVisible = false"
+        @close="costAuditDialogVisible = false"
+      >
+        <cost-audit-table
+          :table-data="costTemplateData"
+          :columns="costTemplateColumns"
+          :show-selection="true"
+          :show-pagination="true"
+          :pagination="costTemplatePagination"
+          @pagination-change="handleCostTemplatePaginationChange"
+          @selection-change="handleCostTemplateSelectionChange"
+        >
+          <template #createTime="{ row }">
+            <div>{{ row.createTime ? row.createTime.split(' ')[0] : '-' }}</div>
+            <div>{{ row.createTime ? row.createTime.split(' ')[1] : '-' }}</div>
+          </template>
+        </cost-audit-table>
+      </CostAuditDialog>
+
       <!-- 在线填报弹窗 -->
       <OnlineFillDialog
         :visible.sync="onlineFillDialogVisible"
@@ -287,6 +337,10 @@
   import CostSurveyTab from './components/CostSurveyTab.vue'
   import AuditOpinionTab from './components/AuditOpinionTab.vue'
   import MessageNoticeTab from './components/MessageNoticeTab.vue'
+  import LegalDialog from '@/views/costAudit/baseInfo/catalogManage/legalDialog.vue'
+  import CostAuditDialog from '@/components/costAudit/CostAuditDialog'
+  import CostAuditTable from '@/components/costAudit/CostAuditTable.vue'
+  import { allcurrentCostSurveyList } from '@/api/financeSheetManage'
 
   export default {
     name: 'TaskFillIn',
@@ -299,6 +353,9 @@
       CostSurveyTab,
       AuditOpinionTab,
       MessageNoticeTab,
+      // LegalDialog,
+      CostAuditDialog,
+      CostAuditTable,
     },
     mixins: [dictMixin],
     props: {
@@ -623,6 +680,7 @@
           formatRequired: '',
           fileList: [],
           fileUrl: '',
+          templateId: '',
         },
         materialRules: {
           informationType: [
@@ -650,9 +708,94 @@
         // 在线填报弹窗相关数据
         onlineFillDialogVisible: false,
         currentSurveyData: null,
+        // 选择模版弹窗
+        legalDialogVisible: false,
+        legalDialogMounted: false,
+        // 使用 CostAuditTable 的选择弹窗
+        costAuditDialogVisible: false,
+        costAuditSubmitting: false,
+        costTemplateData: [],
+        selectedCostTemplates: [],
+        costTemplatePagination: {
+          currentPage: 1,
+          pageSize: 10,
+          total: 0,
+        },
+        costTemplateColumns: [
+          { prop: 'surveyTemplateName', label: '财务数据表名称' },
+          {
+            prop: 'templateType',
+            label: '模版类型',
+            width: '100px',
+            formatter: (row) => {
+              return row.templateType == '1'
+                ? '单记录'
+                : row.templateType == '2'
+                ? '固定表'
+                : '动态表'
+            },
+          },
+          { prop: 'status', label: '状态', width: '100px' },
+          {
+            prop: 'createTime',
+            label: '创建时间',
+            slotName: 'createTime',
+            width: '100px',
+          },
+        ],
       }
     },
     computed: {
+      // 是否选择了“预置模版”格式(通过名称或key含义判断,兼容后端字典差异)
+      isTemplateFormat() {
+        const raw = this.materialForm.formatRequired
+        const v = (raw == null ? '' : String(raw)).toLowerCase()
+        // 显式数值/字符串 3 代表预置模版
+        if (raw === 3 || raw === '3') return true
+        // 名称兜底匹配
+        return (
+          v.includes('template') ||
+          v.includes('preset') ||
+          v.includes('tpl') ||
+          v.includes('模版') ||
+          v.includes('模板')
+        )
+      },
+      // 是否为文档(pdf/word)
+      isDocumentFormat() {
+        const raw = this.materialForm.formatRequired
+        const v = (raw == null ? '' : String(raw)).toLowerCase()
+        // 显式数值/字符串 1 代表文档
+        if (raw === 1 || raw === '1') return true
+        return (
+          v.includes('doc') ||
+          v.includes('word') ||
+          v.includes('pdf') ||
+          v.includes('文档') ||
+          v.includes('word文档')
+        )
+      },
+      // 是否为Excel
+      isExcelFormat() {
+        const raw = this.materialForm.formatRequired
+        const v = (raw == null ? '' : String(raw)).toLowerCase()
+        // 显式数值/字符串 2 代表excel
+        if (raw === 2 || raw === '2') return true
+        return (
+          v.includes('excel') ||
+          v.includes('xls') ||
+          v.includes('xlsx') ||
+          v.includes('表格')
+        )
+      },
+      // 根据所选格式动态生成 accept
+      uploadAccept() {
+        if (this.isTemplateFormat) return ''
+        if (this.isDocumentFormat) return '.pdf,.doc,.docx'
+        if (this.isExcelFormat) return '.xls,.xlsx'
+        // 默认允许常见类型
+        return '.pdf,.doc,.docx,.xls,.xlsx,.csv'
+      },
       // 按类别分组的报送资料列表
       groupedDataRequirements() {
         if (
@@ -1379,11 +1522,28 @@
         this.$message.success('开始下载文件')
       },
       // 报送资料文件上传
-      async handleFileUpload(row) {
+      async handleFileUpload(row, acceptFromChild) {
+        // 预置模版:直接打开 CostAuditTable 弹窗选择模版
+        const fmt = row && row.formatRequired
+        const isTemplate =
+          String(fmt) === '3' ||
+          (typeof fmt === 'string' && fmt.toLowerCase().includes('模板'))
+        if (isTemplate) {
+          this.currentDataRequirementRow = row || null
+          this.loadCostTemplates()
+          this.selectedCostTemplates = []
+          this.costAuditDialogVisible = true
+          console.log('打开 CostAuditTable 弹窗选择模版')
+          return
+        }
+
+        // 非预置模版:走本地文件上传
         // 创建文件选择器
         const input = document.createElement('input')
         input.type = 'file'
-        input.accept = '.pdf,.doc,.docx,.xls,.xlsx,.csv' // 允许的文件类型
+        input.accept =
+          (typeof acceptFromChild === 'string' && acceptFromChild) ||
+          '.pdf,.doc,.docx,.xls,.xlsx,.csv' // 允许的文件类型(兜底)
 
         input.onchange = async (event) => {
           const file = event.target.files[0]
@@ -1490,8 +1650,11 @@
         this.$message.success('开始下载模版')
       },
       handleDataUpload(row) {
-        console.log('上传模版数据:', row)
-        // 实际开发中可添加基于模版的数据上传逻辑
+        // 预置模版:打开 CostAuditTable 弹窗进行模板选择
+        this.currentDataRequirementRow = row || null
+        this.loadCostTemplates()
+        this.selectedCostTemplates = []
+        this.costAuditDialogVisible = true
       },
       handleRemove(file, fileList) {
         console.log(file, fileList)
@@ -1588,6 +1751,7 @@
               informationRequire: this.materialForm.informationRequire,
               formatRequired: this.materialForm.formatRequired,
               fileUrl: this.materialForm.fileUrl,
+              templateId: this.materialForm.templateId,
             })
               .then((res) => {
                 console.log('补充材料提交成功', res)
@@ -1701,36 +1865,46 @@
 
       // 文件上传前验证
       beforeMaterialUpload(file) {
-        const allowedTypes = [
-          'application/pdf',
-          'application/msword',
-          'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
-          'application/vnd.ms-excel',
-          'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
-          'text/csv',
-        ]
-
-        const allowedExtensions = [
-          '.pdf',
-          '.doc',
-          '.docx',
-          '.xls',
-          '.xlsx',
-          '.csv',
-        ]
-        const fileExtension = '.' + file.name.split('.').pop().toLowerCase()
-
-        // 检查文件格式
-        const isCorrectType = allowedTypes.includes(file.type)
-        const isCorrectExtension = allowedExtensions.includes(fileExtension)
-
-        if (!isCorrectType && !isCorrectExtension) {
-          this.$message.error(
-            '只允许上传 pdf, doc, docx, xls, xlsx, csv 格式的文件!'
+        // 预置模版不允许在此上传
+        if (this.isTemplateFormat) {
+          this.$message.warning(
+            '“预置模版”不支持直接上传,请按模版入口添加材料'
           )
           return false
         }
 
+        const ext = '.' + file.name.split('.').pop().toLowerCase()
+        const mime = (file.type || '').toLowerCase()
+
+        // 文档格式
+        if (this.isDocumentFormat) {
+          const allowedExt = ['.pdf', '.doc', '.docx']
+          const allowedMime = [
+            'application/pdf',
+            'application/msword',
+            'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+          ]
+          const ok = allowedExt.includes(ext) || allowedMime.includes(mime)
+          if (!ok) {
+            this.$message.error('当前格式要求为文档,仅支持 pdf, doc, docx')
+            return false
+          }
+        }
+
+        // Excel 格式
+        if (this.isExcelFormat) {
+          const allowedExt = ['.xls', '.xlsx']
+          const allowedMime = [
+            'application/vnd.ms-excel',
+            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+          ]
+          const ok = allowedExt.includes(ext) || allowedMime.includes(mime)
+          if (!ok) {
+            this.$message.error('当前格式要求为表格,仅支持 xls, xlsx')
+            return false
+          }
+        }
+
         // 检查文件大小 (50MB)
         const isLt50M = file.size / 1024 / 1024 < 50
         if (!isLt50M) {
@@ -1813,6 +1987,96 @@
         }
       },
 
+      // 打开预置模版弹窗
+      openLegalDialog() {
+        // 需求:改用 CostAuditTable 弹窗选择模版
+        this.loadCostTemplates()
+        this.selectedCostTemplates = []
+        this.costAuditDialogVisible = true
+        console.log(
+          '打开 CostAuditTable 弹窗选择模版',
+          this.costAuditDialogVisible
+        )
+      },
+      // 接收模版弹窗选择结果
+      handleLegalConfirm(payload) {
+        // 兼容不同返回字段,将关键信息落到表单中
+        const url =
+          payload?.templateUrl ||
+          payload?.url ||
+          payload?.savePath ||
+          payload?.fileUrl ||
+          ''
+        if (url) {
+          // 将选中的模版链接记录在fileUrl,后端若有专属字段可按需调整
+          this.materialForm.fileUrl = url
+          // 在UI上体现已选择(以文件列表形式展示一个只读项)
+          this.materialForm.fileList = [
+            {
+              uid: 'tpl-' + Date.now(),
+              name: payload?.name || payload?.templateName || '已选择的模版',
+              status: 'success',
+              url: url,
+              response: payload,
+            },
+          ]
+          this.$message.success('已选择模版')
+        } else {
+          this.$message.info('未获取到模版链接')
+        }
+        this.legalDialogVisible = false
+      },
+
+      // 拉取模板列表(CostAuditTable用)
+      loadCostTemplates() {
+        allcurrentCostSurveyList({
+          pageNum: this.costTemplatePagination.currentPage,
+          pageSize: this.costTemplatePagination.pageSize,
+        }).then((res) => {
+          this.costTemplateData = res?.value?.records || res?.value || []
+          this.costTemplatePagination.total =
+            res?.value?.total || this.costTemplateData.length || 0
+        })
+      },
+      handleCostTemplatePaginationChange({ currentPage, pageSize }) {
+        this.costTemplatePagination.currentPage = currentPage
+        this.costTemplatePagination.pageSize = pageSize
+        this.loadCostTemplates()
+      },
+      handleCostTemplateSelectionChange(val) {
+        if (Array.isArray(val) && val.length > 1) {
+          this.$message.warning('最多只能选择一个模板')
+          return
+        }
+        this.selectedCostTemplates = val || []
+      },
+      submitCostAuditTemplate() {
+        if (
+          !this.selectedCostTemplates ||
+          this.selectedCostTemplates.length !== 1
+        ) {
+          this.$message.error('请选择一个模板')
+          return
+        }
+        const chosen = this.selectedCostTemplates[0]
+        const url = chosen?.templateUrl || chosen?.url || chosen?.savePath || ''
+        // 记录到表单
+        this.materialForm.fileUrl = url
+        this.materialForm.templateId =
+          chosen?.surveyTemplateId || chosen?.templateId || chosen?.id || ''
+        this.materialForm.fileList = [
+          {
+            uid: 'tpl-' + Date.now(),
+            name: chosen?.surveyTemplateName || '已选择的模版',
+            status: 'success',
+            url: url,
+            response: chosen,
+          },
+        ]
+        this.$message.success('已选择模版')
+        this.costAuditDialogVisible = false
+      },
+
       // 上传成功回调
       handleMaterialUploadSuccess(response, file, fileList) {
         // 更新文件列表,添加文件URL信息