Kaynağa Gözat

合同主体和附件单独分页打印,解析不了pdf问题

chenjun 4 hafta önce
ebeveyn
işleme
9a4523be67
23 değiştirilmiş dosya ile 1928 ekleme ve 4021 silme
  1. 0 3496
      public/pdf.worker.mjs
  2. 392 0
      scripts/add-export-to-nine-precautions-v2.js
  3. 383 0
      scripts/add-export-to-nine-precautions.js
  4. 60 0
      scripts/cleanup-nine-precautions-export.js
  5. 27 0
      scripts/remove-batch-dialog.js
  6. 3 1
      src/components/UploadFile/src/useUpload.ts
  7. 74 45
      src/views/elderly/apply/nine-precautions/MMSE/index.vue
  8. 74 16
      src/views/elderly/apply/nine-precautions/anti-entertainment/index.vue
  9. 70 33
      src/views/elderly/apply/nine-precautions/asphyxiation-by-choking/index.vue
  10. 70 59
      src/views/elderly/apply/nine-precautions/attack/index.vue
  11. 71 59
      src/views/elderly/apply/nine-precautions/commit-suicide/index.vue
  12. 74 62
      src/views/elderly/apply/nine-precautions/communication/index.vue
  13. 74 33
      src/views/elderly/apply/nine-precautions/daily-life/index.vue
  14. 74 33
      src/views/elderly/apply/nine-precautions/empyrosis/index.vue
  15. 74 33
      src/views/elderly/apply/nine-precautions/equilibrium/index.vue
  16. 74 33
      src/views/elderly/apply/nine-precautions/fall-down/index.vue
  17. 74 33
      src/views/elderly/apply/nine-precautions/fall-prevention-measures/index.vue
  18. 79 4
      src/views/elderly/apply/nine-precautions/nutritional-risk/index.vue
  19. 74 33
      src/views/elderly/apply/nine-precautions/pressure-sores/index.vue
  20. 29 12
      src/views/elderly/apply/nine-precautions/risk-disclosure-statement/index.vue
  21. 74 33
      src/views/elderly/apply/nine-precautions/wander-away/index.vue
  22. 1 1
      src/views/elderly/contracts/components/DocumentAttachmentBody.vue
  23. 3 2
      vite.config.ts

Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 3496
public/pdf.worker.mjs


+ 392 - 0
scripts/add-export-to-nine-precautions-v2.js

@@ -0,0 +1,392 @@
+const fs = require('fs')
+const path = require('path')
+const { execSync } = require('child_process')
+
+const baseDir = path.resolve(__dirname, '../src/views/elderly/apply/nine-precautions')
+
+const configs = [
+  {
+    dir: 'MMSE',
+    pageApi: 'mmseGetPage',
+    title: 'MMSE认知评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'info'
+  },
+  {
+    dir: 'anti-entertainment',
+    pageApi: 'entertainmentPage',
+    title: '防文娱活动意外评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'assessScore', title: '评估总得分' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'text'
+  },
+  {
+    dir: 'asphyxiation-by-choking',
+    pageApi: 'asphyxiationPage',
+    title: '防噎食评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'text'
+  },
+  {
+    dir: 'attack',
+    pageApi: 'attackRiskPage',
+    title: '攻击风险评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'info'
+  },
+  {
+    dir: 'commit-suicide',
+    pageApi: 'ngasrPage',
+    title: '自伤自杀风险评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'info'
+  },
+  {
+    dir: 'communication',
+    pageApi: 'perceptionPage',
+    title: '感知沟通评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'info'
+  },
+  {
+    dir: 'daily-life',
+    pageApi: 'dailyLifePage',
+    title: '日常生活活动能力评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'assessScore', title: '评估总得分' },
+      { key: 'riskLevelText', title: '结果等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'result'
+  },
+  {
+    dir: 'empyrosis',
+    pageApi: 'burnPreventionPage',
+    title: '防烫伤评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'assessScore', title: '评估总得分' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'text'
+  },
+  {
+    dir: 'equilibrium',
+    pageApi: 'equilibriumPage',
+    title: '平衡能力评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'assessScore', title: '评估总得分' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'text'
+  },
+  {
+    dir: 'fall-down',
+    pageApi: 'fallDownPage',
+    title: '跌倒风险评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'assessScore', title: '评估总得分' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'text'
+  },
+  {
+    dir: 'fall-prevention-measures',
+    pageApi: 'fallPreventionPage',
+    title: '防坠床评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'assessScore', title: '评估总得分' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'text'
+  },
+  {
+    dir: 'pressure-sores',
+    pageApi: 'pressureSoresPage',
+    title: '防压疮评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'assessScore', title: '评估总得分' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'text'
+  },
+  {
+    dir: 'nutritional-risk',
+    pageApi: 'nutritionalRiskPage',
+    title: '营养风险评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'assessScore', title: '量表总分' },
+      { key: 'riskLevelText', title: '评估结果' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'result'
+  },
+  {
+    dir: 'wander-away',
+    pageApi: 'wanderAwayPage',
+    title: '防走失风险评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'assessScore', title: '评估总得分' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'text'
+  }
+]
+
+function buildExportFunction(config) {
+  const { pageApi, title, columns, riskMode } = config
+  const headersStr = JSON.stringify(columns, null, 6)
+    .replace(/"/g, "'")
+    .replace(/\n      /g, '\n      ')
+
+  let riskLevelProcess = ''
+  if (riskMode === 'info') {
+    riskLevelProcess = `const riskInfo = getRiskLevelInfo(item.assessData)
+      row.riskLevelText = riskInfo.text || '-'`
+  } else if (riskMode === 'text') {
+    riskLevelProcess = `row.riskLevelText = getRiskLevelText(item.riskLevel) || '-'`
+  } else if (riskMode === 'result') {
+    riskLevelProcess = `row.riskLevelText = getResultLevelText(item.riskLevel) || '-'`
+  }
+
+  return `// 打开导出弹窗
+const handleImportCard = async () => {
+  exportLoading.value = true
+  try {
+    const queryP = {
+      pageNo: 1,
+      pageSize: 9999,
+      elderName: queryParams.elderName,
+      assessor: queryParams.assessor,
+      assessDate: queryParams.assessDate,
+      tenantIds: queryParams.tenantIds
+    }
+    const data = await ${pageApi}(queryP)
+    const exportData = data.list || []
+
+    if (exportData.length === 0) {
+      message.warning('暂无数据可导出')
+      return
+    }
+
+    const processedData = exportData.map((item) => {
+      const row: any = {
+        orgName: findLabelById(userStore.getOrgTenant.options, item.tenantId) || '',
+        elderName: item.elderName || '',
+        assessor: item.assessor || '',
+        assessDate: item.assessDate || '',
+        assessScore: item.assessScore ?? '',
+        creator: item.creator || ''
+      }
+      ${riskLevelProcess}
+      return row
+    })
+
+    const headers = ${headersStr}
+
+    exportWithExpandedObjectArrays(processedData, headers, \`${title}_\${new Date().getTime()}.xlsx\`, '${title}')
+    message.success('导出成功')
+  } catch (error) {
+    console.error('导出失败:', error)
+    message.error('导出失败,请重试')
+  } finally {
+    exportLoading.value = false
+  }
+}
+`
+}
+
+// 从 git 读取原始文件
+function readOriginal(relativePath) {
+  return execSync(`git show HEAD:${relativePath}`, {
+    cwd: path.resolve(__dirname, '..'),
+    encoding: 'utf-8'
+  })
+}
+
+function removeBlockByRegex(content, regex) {
+  const match = content.match(regex)
+  if (!match) return content
+  const start = match.index
+  let depth = 0
+  let end = start
+  for (let i = start; i < content.length; i++) {
+    if (content[i] === '{') depth++
+    if (content[i] === '}') {
+      depth--
+      if (depth === 0) {
+        end = i + 1
+        break
+      }
+    }
+  }
+  let before = content.slice(0, start)
+  let after = content.slice(end)
+  // 去掉后面多余的换行
+  if (after.startsWith('\n')) after = after.slice(1)
+  if (after.startsWith('\n')) after = after.slice(1)
+  return before + after
+}
+
+function processFile(config) {
+  const relativePath = `src/views/elderly/apply/nine-precautions/${config.dir}/index.vue`
+  const filePath = path.resolve(__dirname, '..', relativePath)
+  let content = readOriginal(relativePath)
+
+  // 1. 添加 ButtonImport 导入
+  const buttonAddImport = "import ButtonAdd from '@/components/ButtonAdd/src/ButtonAdd.vue'"
+  if (content.includes(buttonAddImport)) {
+    content = content.replace(
+      buttonAddImport,
+      `${buttonAddImport}\nimport ButtonImport from '@/components/ButtonImport/src/ButtonImport.vue'`
+    )
+  } else {
+    // nutritional-risk 没有 ButtonAdd import,ButtonAdd 是全局注册的
+    content = content.replace(
+      '<script setup lang="ts">',
+      '<script setup lang="ts">\nimport ButtonImport from \'@/components/ButtonImport/src/ButtonImport.vue\''
+    )
+  }
+
+  // 2. 添加 exportWithExpandedObjectArrays 导入
+  const apiImportMatch = content.match(/import \{[^}]+\} from '@\/api\/social-work'/)
+  if (apiImportMatch) {
+    const insertPos = apiImportMatch.index + apiImportMatch[0].length
+    content = content.slice(0, insertPos) + "\nimport { exportWithExpandedObjectArrays } from '@/utils/excel-export'" + content.slice(insertPos)
+  } else {
+    content = content.replace(
+      '<script setup lang="ts">',
+      '<script setup lang="ts">\nimport { exportWithExpandedObjectArrays } from \'@/utils/excel-export\''
+    )
+  }
+
+  // 3. 添加导出按钮
+  content = content.replace(
+    /<ButtonAdd @click="openForm\(undefined\)"\s*\/>/g,
+    '<ButtonAdd @click="openForm(undefined)" />\n      <ButtonImport @click="handleImportCard" />'
+  )
+  // 移除旧的注释导入按钮
+  content = content.replace(/\s*<!--\s*<ButtonImport[^>]*>\s*-->\s*/g, '\n')
+
+  // 4. 移除 BatchExportDialog
+  content = content.replace(
+    /\s*<!-- 通用批量导出弹窗 -->\s*<BatchExportDialog[\s\S]*?<\/BatchExportDialog>/,
+    ''
+  )
+
+  // 5. 移除旧的 handleImportCard / handleBatchExport / handleExport 空壳函数
+  content = removeBlockByRegex(
+    content,
+    /\/\/ 打开导出弹窗\s*const handleImportCard = async \(\) => \{/
+  )
+  content = removeBlockByRegex(
+    content,
+    /\/\/ 处理批量导出\s*const handleBatchExport = async \(batch: number, count: number\) => \{/
+  )
+  content = removeBlockByRegex(
+    content,
+    /const handleExport = \(\) => \{/
+  )
+
+  // 6. 精简状态管理为只保留 exportLoading
+  content = content.replace(
+    /\n\/\/ 状态管理\s*const showBatchExport = ref\(false\)\s*const exportConfig = ref\(\{[\s\S]*?description: \[\] as string\[\]\s*\}\)\s*const exportLoading = ref\(false\)\s*/,
+    '\nconst exportLoading = ref(false)\n'
+  )
+
+  // 7. 插入新的 handleImportCard 函数
+  const exportFunc = buildExportFunction(config)
+  const queryFormRefPattern = /const queryFormRef = ref\(\)\s*\/\/ 搜索的表单/
+  if (queryFormRefPattern.test(content)) {
+    content = content.replace(queryFormRefPattern, `const queryFormRef = ref() // 搜索的表单\n\n${exportFunc}`)
+  } else {
+    content = content.replace(
+      /const queryFormRef = ref\(\)\s*$/m,
+      `const queryFormRef = ref()\n\n${exportFunc}`
+    )
+  }
+
+  fs.writeFileSync(filePath, content, 'utf-8')
+  console.log(`已处理:${filePath}`)
+}
+
+configs.forEach(processFile)

+ 383 - 0
scripts/add-export-to-nine-precautions.js

@@ -0,0 +1,383 @@
+const fs = require('fs')
+const path = require('path')
+
+const baseDir = path.resolve(__dirname, '../src/views/elderly/apply/nine-precautions')
+
+const configs = [
+  {
+    dir: 'MMSE',
+    pageApi: 'mmseGetPage',
+    title: 'MMSE认知评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'info'
+  },
+  {
+    dir: 'anti-entertainment',
+    pageApi: 'entertainmentPage',
+    title: '防文娱活动意外评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'assessScore', title: '评估总得分' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'text'
+  },
+  {
+    dir: 'asphyxiation-by-choking',
+    pageApi: 'asphyxiationPage',
+    title: '防噎食评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'text'
+  },
+  {
+    dir: 'attack',
+    pageApi: 'attackRiskPage',
+    title: '攻击风险评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'info'
+  },
+  {
+    dir: 'commit-suicide',
+    pageApi: 'ngasrPage',
+    title: '自伤自杀风险评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'info'
+  },
+  {
+    dir: 'communication',
+    pageApi: 'perceptionPage',
+    title: '感知沟通评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'info'
+  },
+  {
+    dir: 'daily-life',
+    pageApi: 'dailyLifePage',
+    title: '日常生活活动能力评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'assessScore', title: '评估总得分' },
+      { key: 'riskLevelText', title: '结果等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'result'
+  },
+  {
+    dir: 'empyrosis',
+    pageApi: 'burnPreventionPage',
+    title: '防烫伤评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'assessScore', title: '评估总得分' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'text'
+  },
+  {
+    dir: 'equilibrium',
+    pageApi: 'equilibriumPage',
+    title: '平衡能力评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'assessScore', title: '评估总得分' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'text'
+  },
+  {
+    dir: 'fall-down',
+    pageApi: 'fallDownPage',
+    title: '跌倒风险评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'assessScore', title: '评估总得分' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'text'
+  },
+  {
+    dir: 'fall-prevention-measures',
+    pageApi: 'fallPreventionPage',
+    title: '防坠床评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'assessScore', title: '评估总得分' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'text'
+  },
+  {
+    dir: 'pressure-sores',
+    pageApi: 'pressureSoresPage',
+    title: '防压疮评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'assessScore', title: '评估总得分' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'text'
+  },
+  {
+    dir: 'nutritional-risk',
+    pageApi: 'nutritionalRiskPage',
+    title: '营养风险评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'assessScore', title: '量表总分' },
+      { key: 'riskLevelText', title: '评估结果' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'result'
+  },
+  {
+    dir: 'wander-away',
+    pageApi: 'wanderAwayPage',
+    title: '防走失风险评估',
+    columns: [
+      { key: 'orgName', title: '机构名称' },
+      { key: 'elderName', title: '长者姓名' },
+      { key: 'assessor', title: '评估人' },
+      { key: 'assessDate', title: '记录日期' },
+      { key: 'assessScore', title: '评估总得分' },
+      { key: 'riskLevelText', title: '风险等级' },
+      { key: 'creator', title: '记录人' }
+    ],
+    riskMode: 'text'
+  }
+]
+
+function buildExportFunction(config) {
+  const { pageApi, title, columns, riskMode } = config
+  const headersStr = JSON.stringify(columns, null, 6).replace(/"/g, "'")
+
+  let riskLevelProcess = ''
+  if (riskMode === 'info') {
+    riskLevelProcess = `const riskInfo = getRiskLevelInfo(item.assessData)
+      row.riskLevelText = riskInfo.text || '-'`
+  } else if (riskMode === 'text') {
+    riskLevelProcess = `row.riskLevelText = getRiskLevelText(item.riskLevel) || '-'`
+  } else if (riskMode === 'result') {
+    riskLevelProcess = `row.riskLevelText = getResultLevelText(item.riskLevel) || '-'`
+  }
+
+  return `
+// 打开导出弹窗
+const handleImportCard = async () => {
+  exportLoading.value = true
+  try {
+    const queryP = {
+      pageNo: 1,
+      pageSize: 9999,
+      elderName: queryParams.elderName,
+      assessor: queryParams.assessor,
+      assessDate: queryParams.assessDate,
+      tenantIds: queryParams.tenantIds
+    }
+    const data = await ${pageApi}(queryP)
+    const exportData = data.list || []
+
+    if (exportData.length === 0) {
+      message.warning('暂无数据可导出')
+      return
+    }
+
+    const processedData = exportData.map((item) => {
+      const row = {
+        orgName: findLabelById(userStore.getOrgTenant.options, item.tenantId) || '',
+        elderName: item.elderName || '',
+        assessor: item.assessor || '',
+        assessDate: item.assessDate || '',
+        assessScore: item.assessScore ?? '',
+        creator: item.creator || ''
+      }
+      ${riskLevelProcess}
+      return row
+    })
+
+    const headers = ${headersStr}
+
+    exportWithExpandedObjectArrays(processedData, headers, \`${title}_\${new Date().getTime()}.xlsx\`, '${title}')
+    message.success('导出成功')
+  } catch (error) {
+    console.error('导出失败:', error)
+    message.error('导出失败,请重试')
+  } finally {
+    exportLoading.value = false
+  }
+}
+`
+}
+
+function removeBlock(content, startRegex, endMarker) {
+  const startMatch = content.match(startRegex)
+  if (!startMatch) return content
+  const startIndex = startMatch.index
+  let depth = 0
+  let endIndex = startIndex
+  for (let i = startIndex; i < content.length; i++) {
+    if (content[i] === '{') depth++
+    if (content[i] === '}') {
+      depth--
+      if (depth === 0) {
+        endIndex = i + 1
+        break
+      }
+    }
+  }
+  // 包含到 endMarker 之前或之后的换行
+  let before = content.slice(0, startIndex)
+  let after = content.slice(endIndex)
+  if (after.startsWith('\n')) after = after.slice(1)
+  return before + after
+}
+
+function processFile(config) {
+  const filePath = path.join(baseDir, config.dir, 'index.vue')
+  if (!fs.existsSync(filePath)) {
+    console.log(`跳过:${filePath} 不存在`)
+    return
+  }
+
+  let content = fs.readFileSync(filePath, 'utf-8')
+
+  // 1. 添加 ButtonImport 导入(如果还没有)
+  if (!content.includes("import ButtonImport from '@/components/ButtonImport/src/ButtonImport.vue'")) {
+    content = content.replace(
+      "import ButtonAdd from '@/components/ButtonAdd/src/ButtonAdd.vue'",
+      "import ButtonAdd from '@/components/ButtonAdd/src/ButtonAdd.vue'\nimport ButtonImport from '@/components/ButtonImport/src/ButtonImport.vue'"
+    )
+  }
+
+  // 2. 添加 exportWithExpandedObjectArrays 导入
+  if (!content.includes("import { exportWithExpandedObjectArrays } from '@/utils/excel-export'")) {
+    const apiImportMatch = content.match(/import \{[^}]+\} from '@\/api\/social-work'/)
+    if (apiImportMatch) {
+      const insertPos = apiImportMatch.index + apiImportMatch[0].length
+      content = content.slice(0, insertPos) + "\nimport { exportWithExpandedObjectArrays } from '@/utils/excel-export'" + content.slice(insertPos)
+    } else {
+      content = content.replace(
+        '<script setup lang="ts">',
+        '<script setup lang="ts">\nimport { exportWithExpandedObjectArrays } from \'@/utils/excel-export\''
+      )
+    }
+  }
+
+  // 3. 添加导出按钮(紧跟 ButtonAdd 之后,并移除原有的注释导入按钮)
+  content = content.replace(
+    /<ButtonAdd @click="openForm\(undefined\)"\s*\/>/g,
+    '<ButtonAdd @click="openForm(undefined)" />\n      <ButtonImport @click="handleImportCard" />'
+  )
+  // 移除旧的注释按钮行
+  content = content.replace(/\s*<!--\s*<ButtonImport[^>]*>\s*-->\s*/g, '\n')
+
+  // 4. 移除 BatchExportDialog 组件
+  content = content.replace(
+    /\s*<!-- 通用批量导出弹窗 -->\s*<BatchExportDialog[\s\S]*?<\/BatchExportDialog>/,
+    ''
+  )
+
+  // 5. 移除已存在的 handleImportCard / handleBatchExport / handleExport 空壳函数
+  content = content.replace(
+    /\/\/ 打开导出弹窗\s*const handleImportCard = async \(\) => \{[\s\S]*?\}\s*/,
+    ''
+  )
+  content = removeBlock(
+    content,
+    /\/\/ 处理批量导出\s*const handleBatchExport = async \(batch: number, count: number\) => \{/,
+    ''
+  )
+  content = removeBlock(
+    content,
+    /const handleExport = \(\) => \{/,
+    ''
+  )
+
+  // 6. 精简状态管理为只保留 exportLoading
+  content = content.replace(
+    /\n\/\/ 状态管理\s*const showBatchExport = ref\(false\)\s*const exportConfig = ref\(\{[\s\S]*?description: \[\] as string\[\]\s*\}\)\s*const exportLoading = ref\(false\)\s*/,
+    '\nconst exportLoading = ref(false)\n'
+  )
+
+  // 7. 插入新的 handleImportCard 函数
+  const exportFunc = buildExportFunction(config)
+  // 优先在 queryFormRef 定义后插入
+  const queryFormRefPattern = /const queryFormRef = ref\(\)\s*\/\/ 搜索的表单/
+  if (queryFormRefPattern.test(content)) {
+    content = content.replace(queryFormRefPattern, `const queryFormRef = ref() // 搜索的表单\n${exportFunc}`)
+  } else {
+    content = content.replace(
+      /const queryFormRef = ref\(\)\s*$/m,
+      `const queryFormRef = ref()\n${exportFunc}`
+    )
+  }
+
+  fs.writeFileSync(filePath, content, 'utf-8')
+  console.log(`已处理:${filePath}`)
+}
+
+configs.forEach(processFile)

+ 60 - 0
scripts/cleanup-nine-precautions-export.js

@@ -0,0 +1,60 @@
+const fs = require('fs')
+const path = require('path')
+
+const baseDir = path.resolve(__dirname, '../src/views/elderly/apply/nine-precautions')
+const dirs = fs.readdirSync(baseDir).filter(d => fs.statSync(path.join(baseDir, d)).isDirectory())
+
+dirs.forEach(dir => {
+  const filePath = path.join(baseDir, dir, 'index.vue')
+  if (!fs.existsSync(filePath)) return
+  let content = fs.readFileSync(filePath, 'utf-8')
+  let modified = false
+
+  // 1. 移除 BatchExportDialog 组件(支持有无注释前缀)
+  const batchDialogRegex = /(\s*<!-- 通用批量导出弹窗 -->\s*)?<BatchExportDialog[\s\S]*?<\/BatchExportDialog>/
+  if (batchDialogRegex.test(content)) {
+    content = content.replace(batchDialogRegex, '')
+    modified = true
+  }
+
+  // 2. 修复 ButtonAdd 后未自动导入 ButtonImport 的情况( nutritional-risk 等)
+  if (content.includes('<ButtonImport') && !content.includes("import ButtonImport from '@/components/ButtonImport/src/ButtonImport.vue'")) {
+    // 在 script 标签后的第一行 import 处插入
+    content = content.replace(
+      '<script setup lang="ts">',
+      '<script setup lang="ts">\nimport ButtonImport from \'@/components/ButtonImport/src/ButtonImport.vue\''
+    )
+    modified = true
+  }
+
+  // 3. 移除旧的空壳 handleImportCard / handleBatchExport 残留
+  const oldHandleRegex = /\/\/ 打开导出弹窗\s*const handleImportCard = async \(\) => \{[\s\S]*?\}\s*/
+  if (oldHandleRegex.test(content)) {
+    content = content.replace(oldHandleRegex, '')
+    modified = true
+  }
+
+  // 4. 整理 headers 缩进:将 6 空格缩进的单引号 key/title 改为 2 空格
+  content = content.replace(/\n            'key': /g, "\n      'key': ")
+  content = content.replace(/\n            'title': /g, "\n      'title': ")
+
+  // 5. 修正 div 闭合标签缩进:将 ButtonImport 后的 </div> 单独一行并正确缩进
+  content = content.replace(
+    /(<ButtonImport @click="handleImportCard" \/>)\n      <!--      <el-button @click="inputH" type="success">.*<\/el-button>-->\n<\/div>/g,
+    '$1\n    </div>'
+  )
+
+  // 兜底:把 "-->\n</div>" 替换为 "-->\n    </div>"
+  content = content.replace(/-->\n<\/div>/g, '-->\n    </div>')
+
+  // 6. 将 exportData.map 中的 const row = { ... } 改为 const row: any = { ... }
+  content = content.replace(
+    /const processedData = exportData\.map\(\(item\) => \{\n      const row = \{/g,
+    'const processedData = exportData.map((item) => {\n      const row: any = {'
+  )
+
+  if (modified || content !== fs.readFileSync(filePath, 'utf-8')) {
+    fs.writeFileSync(filePath, content, 'utf-8')
+    console.log(`已清理:${filePath}`)
+  }
+})

+ 27 - 0
scripts/remove-batch-dialog.js

@@ -0,0 +1,27 @@
+const fs = require('fs')
+const path = require('path')
+
+const baseDir = path.resolve(__dirname, '../src/views/elderly/apply/nine-precautions')
+const dirs = fs.readdirSync(baseDir).filter(d => fs.statSync(path.join(baseDir, d)).isDirectory())
+
+dirs.forEach(dir => {
+  const filePath = path.join(baseDir, dir, 'index.vue')
+  if (!fs.existsSync(filePath)) return
+  let content = fs.readFileSync(filePath, 'utf-8')
+  const original = content
+
+  // 移除 BatchExportDialog 组件:可能是自闭合或成对标签
+  content = content.replace(
+    /\s*<!--[^>]*批量导出[^>]*-->\s*<BatchExportDialog[\s\S]*?\/>/,
+    ''
+  )
+  content = content.replace(
+    /\s*<BatchExportDialog[\s\S]*?\/>/,
+    ''
+  )
+
+  if (content !== original) {
+    fs.writeFileSync(filePath, content, 'utf-8')
+    console.log(`已移除 BatchExportDialog:${filePath}`)
+  }
+})

+ 3 - 1
src/components/UploadFile/src/useUpload.ts

@@ -203,7 +203,9 @@ export const pdfFileToImageFiles = async (
   const { scale = 2, quality = 0.92 } = options
   const pdfjsLib = await import('pdfjs-dist')
   const pdfjs: any = pdfjsLib
-  pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorkerUrl
+  // 用版本号做 query 参数防缓存:文件名固定(兼容云端 nginx 配置),
+  // 但 URL 随 pdfjs 版本变化,避免主库升级后浏览器命中旧版本 worker 缓存导致版本不匹配
+  pdfjs.GlobalWorkerOptions.workerSrc = `${pdfjsWorkerUrl}?v=${pdfjs.version}`
 
   const arrayBuffer = await fileToArrayBuffer(file)
   const pdfDocument = await pdfjs.getDocument({ data: arrayBuffer }).promise

+ 74 - 45
src/views/elderly/apply/nine-precautions/MMSE/index.vue

@@ -82,9 +82,9 @@
   <ContentWrap>
     <div class="mb-10px">
       <ButtonAdd @click="openForm(undefined)" />
+      <ButtonImport @click="handleImportCard" />
       <!--      <el-button @click="inputH" type="success"><Icon icon="fa:cloud-upload" :size="16" class="mr-1"/>导入</el-button>-->
-      <!--      <ButtonImport @click="handleImportCard"  />-->
-    </div>
+</div>
     <el-table v-loading="loading" :data="list" :header-cell-style="tableHeaderColor">
       <el-table-column header-align="center" align="center" label="序号" width="60">
         <template #default="scope">
@@ -193,10 +193,12 @@
 <script setup lang="ts">
 import AddForm from './AddForm.vue'
 import ButtonAdd from '@/components/ButtonAdd/src/ButtonAdd.vue'
+import ButtonImport from '@/components/ButtonImport/src/ButtonImport.vue'
 import { getRiskLevelInfo } from '@/utils/risk-assessment'
 import { useUserStore } from '@/store/modules/user'
 import Import from '@/components/ImportFile/index.vue'
 import { mmseDelete, mmseGetPage } from '@/api/social-work'
+import { exportWithExpandedObjectArrays } from '@/utils/excel-export'
 import { findLabelById } from '@/utils/dict'
 import { ref } from 'vue'
 import { getBuildList } from '@/api/system/badManage'
@@ -209,20 +211,7 @@ const importRef = ref()
 const total = ref(0) // 列表的总页数
 const list = ref([]) // 列表的数据
 
-// 状态管理
-const showBatchExport = ref(false)
-const exportConfig = ref({
-  title: '',
-  batchMin: 1,
-  batchMax: 999,
-  countMin: 1,
-  countMax: 200,
-  defaultBatch: 1,
-  defaultCount: 200,
-  description: [] as string[]
-})
 const exportLoading = ref(false)
-
 let queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
@@ -235,41 +224,81 @@ let queryParams = reactive({
 })
 const queryFormRef = ref() // 搜索的表单
 
-const inputH = () => {
-  importRef.value.open(queryParams.tenantIds[0])
-}
 // 打开导出弹窗
 const handleImportCard = async () => {
-  // showBatchExport.value = true
-}
-
-// 处理批量导出
-const handleBatchExport = async (batch: number, count: number) => {
   exportLoading.value = true
-  console.log(batch, count)
-  // try {
-  //   let queryParams = {
-  //     pageNo: batch,
-  //     pageSize: count,
-  //     tenantId: userStore.orgTenantId[0]
-  //   }
-  //   const list = await careRecordsPage(queryParams)
-  //   if (list.length <= 0) {
-  //     message.error('暂无数据可以导出!')
-  //     return
-  //   }
-  //   const headers = [
-  //     { key: 'organizationName', title: '机构名称' },
-  //     { key: 'visitName', title: '姓名' },
-  //     { key: 'visitPhone', title: '手机号' },
-  //     { key: 'visitDate', title: '预约时间' },
-  //     { key: 'accompanyCount', title: '陪同人数' },
-  //     { key: 'reason', title: '理由' }
-  //   ]
-  //   exportWithExpandedObjectArrays(list, headers, `医疗护理记录${formatToDateTime()}.xlsx`, '医疗护理记录')
-  // } catch (_) {}
+  try {
+    const queryP = {
+      pageNo: 1,
+      pageSize: 9999,
+      elderName: queryParams.elderName,
+      assessor: queryParams.assessor,
+      assessDate: queryParams.assessDate,
+      tenantIds: queryParams.tenantIds
+    }
+    const data = await mmseGetPage(queryP)
+    const exportData = data.list || []
+
+    if (exportData.length === 0) {
+      message.warning('暂无数据可导出')
+      return
+    }
+
+    const processedData = exportData.map((item) => {
+      const row: any = {
+        orgName: findLabelById(userStore.getOrgTenant.options, item.tenantId) || '',
+        elderName: item.elderName || '',
+        assessor: item.assessor || '',
+        assessDate: item.assessDate || '',
+        assessScore: item.assessScore ?? '',
+        creator: item.creator || ''
+      }
+      const riskInfo = getRiskLevelInfo(item.assessData)
+      row.riskLevelText = riskInfo.text || '-'
+      return row
+    })
+
+    const headers = [
+      {
+            'key': 'orgName',
+            'title': '机构名称'
+      },
+      {
+            'key': 'elderName',
+            'title': '长者姓名'
+      },
+      {
+            'key': 'assessor',
+            'title': '评估人'
+      },
+      {
+            'key': 'assessDate',
+            'title': '记录日期'
+      },
+      {
+            'key': 'riskLevelText',
+            'title': '风险等级'
+      },
+      {
+            'key': 'creator',
+            'title': '记录人'
+      }
+]
+
+    exportWithExpandedObjectArrays(processedData, headers, `MMSE认知评估_${new Date().getTime()}.xlsx`, 'MMSE认知评估')
+    message.success('导出成功')
+  } catch (error) {
+    console.error('导出失败:', error)
+    message.error('导出失败,请重试')
+  } finally {
+    exportLoading.value = false
+  }
 }
 
+
+const inputH = () => {
+  importRef.value.open(queryParams.tenantIds[0])
+}
 /** 查询列表 */
 const getList = async () => {
   loading.value = true

+ 74 - 16
src/views/elderly/apply/nine-precautions/anti-entertainment/index.vue

@@ -77,6 +77,7 @@
   <ContentWrap>
     <div class="mb-10px">
       <ButtonAdd @click="openForm(undefined)" />
+      <ButtonImport @click="handleImportCard" />
     </div>
     <el-table v-loading="loading" :data="list" :header-cell-style="tableHeaderColor">
       <el-table-column header-align="center" align="center" label="序号" width="60">
@@ -179,6 +180,7 @@
 <script setup lang="ts">
 import AddForm from './AddForm.vue'
 import ButtonAdd from '@/components/ButtonAdd/src/ButtonAdd.vue'
+import ButtonImport from '@/components/ButtonImport/src/ButtonImport.vue'
 import { useUserStore } from '@/store/modules/user'
 import { getCurrentMonthRange } from '@/utils/dateUtil'
 import {
@@ -187,6 +189,7 @@ import {
   fallDownDelete,
   fallDownPage
 } from '@/api/social-work'
+import { exportWithExpandedObjectArrays } from '@/utils/excel-export'
 import { findLabelById } from '@/utils/dict'
 import { getBuildList } from '@/api/system/badManage'
 import { ref } from 'vue'
@@ -198,20 +201,7 @@ const loading = ref(true)
 const total = ref(0)
 const list = ref([])
 
-// 状态管理
-const showBatchExport = ref(false)
-const exportConfig = ref({
-  title: '',
-  batchMin: 1,
-  batchMax: 999,
-  countMin: 1,
-  countMax: 200,
-  defaultBatch: 1,
-  defaultCount: 200,
-  description: [] as string[]
-})
 const exportLoading = ref(false)
-
 let queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
@@ -225,10 +215,78 @@ let queryParams = reactive({
 })
 const queryFormRef = ref()
 
-// 处理批量导出
-const handleBatchExport = async (batch: number, count: number) => {
+// 打开导出弹窗
+const handleImportCard = async () => {
   exportLoading.value = true
-  console.log(batch, count)
+  try {
+    const queryP = {
+      pageNo: 1,
+      pageSize: 9999,
+      elderName: queryParams.elderName,
+      assessor: queryParams.assessor,
+      assessDate: queryParams.assessDate,
+      tenantIds: queryParams.tenantIds
+    }
+    const data = await entertainmentPage(queryP)
+    const exportData = data.list || []
+
+    if (exportData.length === 0) {
+      message.warning('暂无数据可导出')
+      return
+    }
+
+    const processedData = exportData.map((item) => {
+      const row: any = {
+        orgName: findLabelById(userStore.getOrgTenant.options, item.tenantId) || '',
+        elderName: item.elderName || '',
+        assessor: item.assessor || '',
+        assessDate: item.assessDate || '',
+        assessScore: item.assessScore ?? '',
+        creator: item.creator || ''
+      }
+      row.riskLevelText = getRiskLevelText(item.riskLevel) || '-'
+      return row
+    })
+
+    const headers = [
+      {
+            'key': 'orgName',
+            'title': '机构名称'
+      },
+      {
+            'key': 'elderName',
+            'title': '长者姓名'
+      },
+      {
+            'key': 'assessor',
+            'title': '评估人'
+      },
+      {
+            'key': 'assessDate',
+            'title': '记录日期'
+      },
+      {
+            'key': 'assessScore',
+            'title': '评估总得分'
+      },
+      {
+            'key': 'riskLevelText',
+            'title': '风险等级'
+      },
+      {
+            'key': 'creator',
+            'title': '记录人'
+      }
+]
+
+    exportWithExpandedObjectArrays(processedData, headers, `防文娱活动意外评估_${new Date().getTime()}.xlsx`, '防文娱活动意外评估')
+    message.success('导出成功')
+  } catch (error) {
+    console.error('导出失败:', error)
+    message.error('导出失败,请重试')
+  } finally {
+    exportLoading.value = false
+  }
 }
 
 /** 查询列表 */

+ 70 - 33
src/views/elderly/apply/nine-precautions/asphyxiation-by-choking/index.vue

@@ -51,6 +51,7 @@
   <ContentWrap>
     <div class="mb-10px">
       <ButtonAdd @click="openForm(undefined)" />
+      <ButtonImport @click="handleImportCard" />
     </div>
     <el-table v-loading="loading" :data="list" :header-cell-style="tableHeaderColor">
       <el-table-column header-align="center" align="center" label="序号" width="60">
@@ -140,31 +141,16 @@
   </ContentWrap>
 
   <AddForm ref="formRef" @success="getList" />
-
-  <!-- 通用批量导出弹窗 -->
-  <BatchExportDialog
-    :show="showBatchExport"
-    :title="exportConfig.title"
-    :loading="exportLoading"
-    :batch-min="exportConfig.batchMin"
-    :batch-max="exportConfig.batchMax"
-    :count-min="exportConfig.countMin"
-    :count-max="exportConfig.countMax"
-    :default-batch="exportConfig.defaultBatch"
-    :default-count="exportConfig.defaultCount"
-    :description="exportConfig.description"
-    @update:show="showBatchExport = $event"
-    @confirm="handleBatchExport"
-    @cancel="showBatchExport = false"
-  />
 </template>
 
 <script setup lang="ts">
 import AddForm from './AddForm.vue'
 import ButtonAdd from '@/components/ButtonAdd/src/ButtonAdd.vue'
+import ButtonImport from '@/components/ButtonImport/src/ButtonImport.vue'
 import { useUserStore } from '@/store/modules/user'
 import { getCurrentMonthRange } from '@/utils/dateUtil'
 import { asphyxiationDelete, asphyxiationPage } from '@/api/social-work'
+import { exportWithExpandedObjectArrays } from '@/utils/excel-export'
 import { findLabelById } from '@/utils/dict'
 
 const message = useMessage()
@@ -174,20 +160,7 @@ const loading = ref(true)
 const total = ref(0)
 const list = ref([])
 
-// 状态管理
-const showBatchExport = ref(false)
-const exportConfig = ref({
-  title: '',
-  batchMin: 1,
-  batchMax: 999,
-  countMin: 1,
-  countMax: 200,
-  defaultBatch: 1,
-  defaultCount: 200,
-  description: [] as string[]
-})
 const exportLoading = ref(false)
-
 let queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
@@ -199,10 +172,74 @@ let queryParams = reactive({
 })
 const queryFormRef = ref()
 
-// 处理批量导出
-const handleBatchExport = async (batch: number, count: number) => {
+// 打开导出弹窗
+const handleImportCard = async () => {
   exportLoading.value = true
-  console.log(batch, count)
+  try {
+    const queryP = {
+      pageNo: 1,
+      pageSize: 9999,
+      elderName: queryParams.elderName,
+      assessor: queryParams.assessor,
+      assessDate: queryParams.assessDate,
+      tenantIds: queryParams.tenantIds
+    }
+    const data = await asphyxiationPage(queryP)
+    const exportData = data.list || []
+
+    if (exportData.length === 0) {
+      message.warning('暂无数据可导出')
+      return
+    }
+
+    const processedData = exportData.map((item) => {
+      const row: any = {
+        orgName: findLabelById(userStore.getOrgTenant.options, item.tenantId) || '',
+        elderName: item.elderName || '',
+        assessor: item.assessor || '',
+        assessDate: item.assessDate || '',
+        assessScore: item.assessScore ?? '',
+        creator: item.creator || ''
+      }
+      row.riskLevelText = getRiskLevelText(item.riskLevel) || '-'
+      return row
+    })
+
+    const headers = [
+      {
+            'key': 'orgName',
+            'title': '机构名称'
+      },
+      {
+            'key': 'elderName',
+            'title': '长者姓名'
+      },
+      {
+            'key': 'assessor',
+            'title': '评估人'
+      },
+      {
+            'key': 'assessDate',
+            'title': '记录日期'
+      },
+      {
+            'key': 'riskLevelText',
+            'title': '风险等级'
+      },
+      {
+            'key': 'creator',
+            'title': '记录人'
+      }
+]
+
+    exportWithExpandedObjectArrays(processedData, headers, `防噎食评估_${new Date().getTime()}.xlsx`, '防噎食评估')
+    message.success('导出成功')
+  } catch (error) {
+    console.error('导出失败:', error)
+    message.error('导出失败,请重试')
+  } finally {
+    exportLoading.value = false
+  }
 }
 
 /** 查询列表 */

+ 70 - 59
src/views/elderly/apply/nine-precautions/attack/index.vue

@@ -82,9 +82,9 @@
   <ContentWrap>
     <div class="mb-10px">
       <ButtonAdd @click="openForm(undefined)" />
+      <ButtonImport @click="handleImportCard" />
       <!--      <el-button @click="inputH" type="success"><Icon icon="fa:cloud-upload" :size="16" class="mr-1"/>导入</el-button>-->
-      <!--      <ButtonImport @click="handleImportCard"  />-->
-    </div>
+</div>
     <el-table v-loading="loading" :data="list" :header-cell-style="tableHeaderColor">
       <el-table-column header-align="center" align="center" label="序号" width="60">
         <template #default="scope">
@@ -177,23 +177,6 @@
 
   <AddForm ref="formRef" @success="getList" />
 
-  <!-- 通用批量导出弹窗 -->
-  <BatchExportDialog
-    :show="showBatchExport"
-    :title="exportConfig.title"
-    :loading="exportLoading"
-    :batch-min="exportConfig.batchMin"
-    :batch-max="exportConfig.batchMax"
-    :count-min="exportConfig.countMin"
-    :count-max="exportConfig.countMax"
-    :default-batch="exportConfig.defaultBatch"
-    :default-count="exportConfig.defaultCount"
-    :description="exportConfig.description"
-    @update:show="showBatchExport = $event"
-    @confirm="handleBatchExport"
-    @cancel="showBatchExport = false"
-  />
-
   <Import
     ref="importRef"
     @success="getList"
@@ -216,6 +199,7 @@ import { formatTimestamp, getCurrentMonthRange } from '@/utils/dateUtil'
 import Import from '@/components/ImportFile/index.vue'
 import { restraintCreatePage, restraintDelete } from '@/api/elderly/nursing/keep-fit'
 import { attackRiskDelete, attackRiskPage } from '@/api/social-work'
+import { exportWithExpandedObjectArrays } from '@/utils/excel-export'
 import { getRiskLevelInfo } from '@/utils/risk-assessment'
 import { findLabelById } from '@/utils/dict'
 import { ref } from 'vue'
@@ -229,20 +213,7 @@ const importRef = ref()
 const total = ref(0) // 列表的总页数
 const list = ref([]) // 列表的数据
 
-// 状态管理
-const showBatchExport = ref(false)
-const exportConfig = ref({
-  title: '',
-  batchMin: 1,
-  batchMax: 999,
-  countMin: 1,
-  countMax: 200,
-  defaultBatch: 1,
-  defaultCount: 200,
-  description: [] as string[]
-})
 const exportLoading = ref(false)
-
 let queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
@@ -258,36 +229,76 @@ const queryFormRef = ref() // 搜索的表单
 
 // 打开导出弹窗
 const handleImportCard = async () => {
-  // showBatchExport.value = true
-}
-
-// 处理批量导出
-const handleBatchExport = async (batch: number, count: number) => {
   exportLoading.value = true
-  console.log(batch, count)
-  // try {
-  //   let queryParams = {
-  //     pageNo: batch,
-  //     pageSize: count,
-  //     tenantId: userStore.orgTenantId[0]
-  //   }
-  //   const list = await careRecordsPage(queryParams)
-  //   if (list.length <= 0) {
-  //     message.error('暂无数据可以导出!')
-  //     return
-  //   }
-  //   const headers = [
-  //     { key: 'organizationName', title: '机构名称' },
-  //     { key: 'visitName', title: '姓名' },
-  //     { key: 'visitPhone', title: '手机号' },
-  //     { key: 'visitDate', title: '预约时间' },
-  //     { key: 'accompanyCount', title: '陪同人数' },
-  //     { key: 'reason', title: '理由' }
-  //   ]
-  //   exportWithExpandedObjectArrays(list, headers, `医疗护理记录${formatToDateTime()}.xlsx`, '医疗护理记录')
-  // } catch (_) {}
+  try {
+    const queryP = {
+      pageNo: 1,
+      pageSize: 9999,
+      elderName: queryParams.elderName,
+      assessor: queryParams.assessor,
+      assessDate: queryParams.assessDate,
+      tenantIds: queryParams.tenantIds
+    }
+    const data = await attackRiskPage(queryP)
+    const exportData = data.list || []
+
+    if (exportData.length === 0) {
+      message.warning('暂无数据可导出')
+      return
+    }
+
+    const processedData = exportData.map((item) => {
+      const row: any = {
+        orgName: findLabelById(userStore.getOrgTenant.options, item.tenantId) || '',
+        elderName: item.elderName || '',
+        assessor: item.assessor || '',
+        assessDate: item.assessDate || '',
+        assessScore: item.assessScore ?? '',
+        creator: item.creator || ''
+      }
+      const riskInfo = getRiskLevelInfo(item.assessData)
+      row.riskLevelText = riskInfo.text || '-'
+      return row
+    })
+
+    const headers = [
+      {
+            'key': 'orgName',
+            'title': '机构名称'
+      },
+      {
+            'key': 'elderName',
+            'title': '长者姓名'
+      },
+      {
+            'key': 'assessor',
+            'title': '评估人'
+      },
+      {
+            'key': 'riskLevelText',
+            'title': '风险等级'
+      },
+      {
+            'key': 'assessDate',
+            'title': '记录日期'
+      },
+      {
+            'key': 'creator',
+            'title': '记录人'
+      }
+]
+
+    exportWithExpandedObjectArrays(processedData, headers, `攻击风险评估_${new Date().getTime()}.xlsx`, '攻击风险评估')
+    message.success('导出成功')
+  } catch (error) {
+    console.error('导出失败:', error)
+    message.error('导出失败,请重试')
+  } finally {
+    exportLoading.value = false
+  }
 }
 
+
 /** 查询列表 */
 const getList = async () => {
   loading.value = true

+ 71 - 59
src/views/elderly/apply/nine-precautions/commit-suicide/index.vue

@@ -56,9 +56,9 @@
   <ContentWrap>
     <div class="mb-10px">
       <ButtonAdd @click="openForm(undefined)" />
+      <ButtonImport @click="handleImportCard" />
       <!--      <el-button @click="inputH" type="success"><Icon icon="fa:cloud-upload" :size="16" class="mr-1"/>导入</el-button>-->
-      <!--      <ButtonImport @click="handleImportCard"  />-->
-    </div>
+</div>
     <el-table v-loading="loading" :data="list" :header-cell-style="tableHeaderColor">
       <el-table-column header-align="center" align="center" label="序号" width="60">
         <template #default="scope">
@@ -151,23 +151,6 @@
 
   <AddForm ref="formRef" @success="getList" />
 
-  <!-- 通用批量导出弹窗 -->
-  <BatchExportDialog
-    :show="showBatchExport"
-    :title="exportConfig.title"
-    :loading="exportLoading"
-    :batch-min="exportConfig.batchMin"
-    :batch-max="exportConfig.batchMax"
-    :count-min="exportConfig.countMin"
-    :count-max="exportConfig.countMax"
-    :default-batch="exportConfig.defaultBatch"
-    :default-count="exportConfig.defaultCount"
-    :description="exportConfig.description"
-    @update:show="showBatchExport = $event"
-    @confirm="handleBatchExport"
-    @cancel="showBatchExport = false"
-  />
-
   <Import
     ref="importRef"
     @success="getList"
@@ -184,9 +167,11 @@
 <script setup lang="ts">
 import AddForm from './AddForm.vue'
 import ButtonAdd from '@/components/ButtonAdd/src/ButtonAdd.vue'
+import ButtonImport from '@/components/ButtonImport/src/ButtonImport.vue'
 import { useUserStore } from '@/store/modules/user'
 import Import from '@/components/ImportFile/index.vue'
 import { ngasrDelete, ngasrPage } from '@/api/social-work'
+import { exportWithExpandedObjectArrays } from '@/utils/excel-export'
 import { getRiskLevelInfo } from '@/utils/risk-assessment'
 import { findLabelById } from '@/utils/dict'
 const message = useMessage() // 消息弹窗
@@ -198,20 +183,7 @@ const importRef = ref()
 const total = ref(0) // 列表的总页数
 const list = ref([]) // 列表的数据
 
-// 状态管理
-const showBatchExport = ref(false)
-const exportConfig = ref({
-  title: '',
-  batchMin: 1,
-  batchMax: 999,
-  countMin: 1,
-  countMax: 200,
-  defaultBatch: 1,
-  defaultCount: 200,
-  description: [] as string[]
-})
 const exportLoading = ref(false)
-
 let queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
@@ -225,36 +197,76 @@ const queryFormRef = ref() // 搜索的表单
 
 // 打开导出弹窗
 const handleImportCard = async () => {
-  // showBatchExport.value = true
-}
-
-// 处理批量导出
-const handleBatchExport = async (batch: number, count: number) => {
   exportLoading.value = true
-  console.log(batch, count)
-  // try {
-  //   let queryParams = {
-  //     pageNo: batch,
-  //     pageSize: count,
-  //     tenantId: userStore.orgTenantId[0]
-  //   }
-  //   const list = await careRecordsPage(queryParams)
-  //   if (list.length <= 0) {
-  //     message.error('暂无数据可以导出!')
-  //     return
-  //   }
-  //   const headers = [
-  //     { key: 'organizationName', title: '机构名称' },
-  //     { key: 'visitName', title: '姓名' },
-  //     { key: 'visitPhone', title: '手机号' },
-  //     { key: 'visitDate', title: '预约时间' },
-  //     { key: 'accompanyCount', title: '陪同人数' },
-  //     { key: 'reason', title: '理由' }
-  //   ]
-  //   exportWithExpandedObjectArrays(list, headers, `医疗护理记录${formatToDateTime()}.xlsx`, '医疗护理记录')
-  // } catch (_) {}
+  try {
+    const queryP = {
+      pageNo: 1,
+      pageSize: 9999,
+      elderName: queryParams.elderName,
+      assessor: queryParams.assessor,
+      assessDate: queryParams.assessDate,
+      tenantIds: queryParams.tenantIds
+    }
+    const data = await ngasrPage(queryP)
+    const exportData = data.list || []
+
+    if (exportData.length === 0) {
+      message.warning('暂无数据可导出')
+      return
+    }
+
+    const processedData = exportData.map((item) => {
+      const row: any = {
+        orgName: findLabelById(userStore.getOrgTenant.options, item.tenantId) || '',
+        elderName: item.elderName || '',
+        assessor: item.assessor || '',
+        assessDate: item.assessDate || '',
+        assessScore: item.assessScore ?? '',
+        creator: item.creator || ''
+      }
+      const riskInfo = getRiskLevelInfo(item.assessData)
+      row.riskLevelText = riskInfo.text || '-'
+      return row
+    })
+
+    const headers = [
+      {
+            'key': 'orgName',
+            'title': '机构名称'
+      },
+      {
+            'key': 'elderName',
+            'title': '长者姓名'
+      },
+      {
+            'key': 'assessor',
+            'title': '评估人'
+      },
+      {
+            'key': 'assessDate',
+            'title': '记录日期'
+      },
+      {
+            'key': 'riskLevelText',
+            'title': '风险等级'
+      },
+      {
+            'key': 'creator',
+            'title': '记录人'
+      }
+]
+
+    exportWithExpandedObjectArrays(processedData, headers, `自伤自杀风险评估_${new Date().getTime()}.xlsx`, '自伤自杀风险评估')
+    message.success('导出成功')
+  } catch (error) {
+    console.error('导出失败:', error)
+    message.error('导出失败,请重试')
+  } finally {
+    exportLoading.value = false
+  }
 }
 
+
 /** 查询列表 */
 const getList = async () => {
   loading.value = true

+ 74 - 62
src/views/elderly/apply/nine-precautions/communication/index.vue

@@ -82,9 +82,9 @@
   <ContentWrap>
     <div class="mb-10px">
       <ButtonAdd @click="openForm(undefined)" />
+      <ButtonImport @click="handleImportCard" />
       <!--      <el-button @click="inputH" type="success"><Icon icon="fa:cloud-upload" :size="16" class="mr-1"/>导入</el-button>-->
-      <!--      <ButtonImport @click="handleImportCard"  />-->
-    </div>
+</div>
     <el-table v-loading="loading" :data="list" :header-cell-style="tableHeaderColor">
       <el-table-column header-align="center" align="center" label="序号" width="60">
         <template #default="scope">
@@ -177,23 +177,6 @@
 
   <AddForm ref="formRef" @success="getList" />
 
-  <!-- 通用批量导出弹窗 -->
-  <BatchExportDialog
-    :show="showBatchExport"
-    :title="exportConfig.title"
-    :loading="exportLoading"
-    :batch-min="exportConfig.batchMin"
-    :batch-max="exportConfig.batchMax"
-    :count-min="exportConfig.countMin"
-    :count-max="exportConfig.countMax"
-    :default-batch="exportConfig.defaultBatch"
-    :default-count="exportConfig.defaultCount"
-    :description="exportConfig.description"
-    @update:show="showBatchExport = $event"
-    @confirm="handleBatchExport"
-    @cancel="showBatchExport = false"
-  />
-
   <Import
     ref="importRef"
     @success="getList"
@@ -210,10 +193,12 @@
 <script setup lang="ts">
 import AddForm from './AddForm.vue'
 import ButtonAdd from '@/components/ButtonAdd/src/ButtonAdd.vue'
+import ButtonImport from '@/components/ButtonImport/src/ButtonImport.vue'
 import { getRiskLevelInfo } from '@/utils/risk-assessment'
 import { useUserStore } from '@/store/modules/user'
 import Import from '@/components/ImportFile/index.vue'
 import { perceptionDelete, perceptionPage } from '@/api/social-work'
+import { exportWithExpandedObjectArrays } from '@/utils/excel-export'
 import { findLabelById } from '@/utils/dict'
 import { getBuildList } from '@/api/system/badManage'
 import { ref } from 'vue'
@@ -226,20 +211,7 @@ const importRef = ref()
 const total = ref(0) // 列表的总页数
 const list = ref([]) // 列表的数据
 
-// 状态管理
-const showBatchExport = ref(false)
-const exportConfig = ref({
-  title: '',
-  batchMin: 1,
-  batchMax: 999,
-  countMin: 1,
-  countMax: 200,
-  defaultBatch: 1,
-  defaultCount: 200,
-  description: [] as string[]
-})
 const exportLoading = ref(false)
-
 let queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
@@ -252,41 +224,81 @@ let queryParams = reactive({
 })
 const queryFormRef = ref() // 搜索的表单
 
-const inputH = () => {
-  importRef.value.open(queryParams.tenantIds[0])
-}
 // 打开导出弹窗
 const handleImportCard = async () => {
-  // showBatchExport.value = true
-}
-
-// 处理批量导出
-const handleBatchExport = async (batch: number, count: number) => {
   exportLoading.value = true
-  console.log(batch, count)
-  // try {
-  //   let queryParams = {
-  //     pageNo: batch,
-  //     pageSize: count,
-  //     tenantId: userStore.orgTenantId[0]
-  //   }
-  //   const list = await careRecordsPage(queryParams)
-  //   if (list.length <= 0) {
-  //     message.error('暂无数据可以导出!')
-  //     return
-  //   }
-  //   const headers = [
-  //     { key: 'organizationName', title: '机构名称' },
-  //     { key: 'visitName', title: '姓名' },
-  //     { key: 'visitPhone', title: '手机号' },
-  //     { key: 'visitDate', title: '预约时间' },
-  //     { key: 'accompanyCount', title: '陪同人数' },
-  //     { key: 'reason', title: '理由' }
-  //   ]
-  //   exportWithExpandedObjectArrays(list, headers, `医疗护理记录${formatToDateTime()}.xlsx`, '医疗护理记录')
-  // } catch (_) {}
+  try {
+    const queryP = {
+      pageNo: 1,
+      pageSize: 9999,
+      elderName: queryParams.elderName,
+      assessor: queryParams.assessor,
+      assessDate: queryParams.assessDate,
+      tenantIds: queryParams.tenantIds
+    }
+    const data = await perceptionPage(queryP)
+    const exportData = data.list || []
+
+    if (exportData.length === 0) {
+      message.warning('暂无数据可导出')
+      return
+    }
+
+    const processedData = exportData.map((item) => {
+      const row: any = {
+        orgName: findLabelById(userStore.getOrgTenant.options, item.tenantId) || '',
+        elderName: item.elderName || '',
+        assessor: item.assessor || '',
+        assessDate: item.assessDate || '',
+        assessScore: item.assessScore ?? '',
+        creator: item.creator || ''
+      }
+      const riskInfo = getRiskLevelInfo(item.assessData)
+      row.riskLevelText = riskInfo.text || '-'
+      return row
+    })
+
+    const headers = [
+      {
+            'key': 'orgName',
+            'title': '机构名称'
+      },
+      {
+            'key': 'elderName',
+            'title': '长者姓名'
+      },
+      {
+            'key': 'assessor',
+            'title': '评估人'
+      },
+      {
+            'key': 'assessDate',
+            'title': '记录日期'
+      },
+      {
+            'key': 'riskLevelText',
+            'title': '风险等级'
+      },
+      {
+            'key': 'creator',
+            'title': '记录人'
+      }
+]
+
+    exportWithExpandedObjectArrays(processedData, headers, `感知沟通评估_${new Date().getTime()}.xlsx`, '感知沟通评估')
+    message.success('导出成功')
+  } catch (error) {
+    console.error('导出失败:', error)
+    message.error('导出失败,请重试')
+  } finally {
+    exportLoading.value = false
+  }
 }
 
+
+const inputH = () => {
+  importRef.value.open(queryParams.tenantIds[0])
+}
 /** 查询列表 */
 const getList = async () => {
   loading.value = true

+ 74 - 33
src/views/elderly/apply/nine-precautions/daily-life/index.vue

@@ -51,6 +51,7 @@
   <ContentWrap>
     <div class="mb-10px">
       <ButtonAdd @click="openForm(undefined)" />
+      <ButtonImport @click="handleImportCard" />
     </div>
     <el-table v-loading="loading" :data="list" :header-cell-style="tableHeaderColor">
       <el-table-column header-align="center" align="center" label="序号" width="60">
@@ -148,31 +149,16 @@
   </ContentWrap>
 
   <AddForm ref="formRef" @success="getList" />
-
-  <!-- 通用批量导出弹窗 -->
-  <BatchExportDialog
-    :show="showBatchExport"
-    :title="exportConfig.title"
-    :loading="exportLoading"
-    :batch-min="exportConfig.batchMin"
-    :batch-max="exportConfig.batchMax"
-    :count-min="exportConfig.countMin"
-    :count-max="exportConfig.countMax"
-    :default-batch="exportConfig.defaultBatch"
-    :default-count="exportConfig.defaultCount"
-    :description="exportConfig.description"
-    @update:show="showBatchExport = $event"
-    @confirm="handleBatchExport"
-    @cancel="showBatchExport = false"
-  />
 </template>
 
 <script setup lang="ts">
 import AddForm from './AddForm.vue'
 import ButtonAdd from '@/components/ButtonAdd/src/ButtonAdd.vue'
+import ButtonImport from '@/components/ButtonImport/src/ButtonImport.vue'
 import { useUserStore } from '@/store/modules/user'
 import { getCurrentMonthRange } from '@/utils/dateUtil'
 import { dailyLifeDelete, dailyLifePage } from '@/api/social-work'
+import { exportWithExpandedObjectArrays } from '@/utils/excel-export'
 import { findLabelById } from '@/utils/dict'
 
 const message = useMessage()
@@ -182,20 +168,7 @@ const loading = ref(true)
 const total = ref(0)
 const list = ref([])
 
-// 状态管理
-const showBatchExport = ref(false)
-const exportConfig = ref({
-  title: '',
-  batchMin: 1,
-  batchMax: 999,
-  countMin: 1,
-  countMax: 200,
-  defaultBatch: 1,
-  defaultCount: 200,
-  description: [] as string[]
-})
 const exportLoading = ref(false)
-
 let queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
@@ -207,10 +180,78 @@ let queryParams = reactive({
 })
 const queryFormRef = ref()
 
-// 处理批量导出
-const handleBatchExport = async (batch: number, count: number) => {
+// 打开导出弹窗
+const handleImportCard = async () => {
   exportLoading.value = true
-  console.log(batch, count)
+  try {
+    const queryP = {
+      pageNo: 1,
+      pageSize: 9999,
+      elderName: queryParams.elderName,
+      assessor: queryParams.assessor,
+      assessDate: queryParams.assessDate,
+      tenantIds: queryParams.tenantIds
+    }
+    const data = await dailyLifePage(queryP)
+    const exportData = data.list || []
+
+    if (exportData.length === 0) {
+      message.warning('暂无数据可导出')
+      return
+    }
+
+    const processedData = exportData.map((item) => {
+      const row: any = {
+        orgName: findLabelById(userStore.getOrgTenant.options, item.tenantId) || '',
+        elderName: item.elderName || '',
+        assessor: item.assessor || '',
+        assessDate: item.assessDate || '',
+        assessScore: item.assessScore ?? '',
+        creator: item.creator || ''
+      }
+      row.riskLevelText = getResultLevelText(item.riskLevel) || '-'
+      return row
+    })
+
+    const headers = [
+      {
+            'key': 'orgName',
+            'title': '机构名称'
+      },
+      {
+            'key': 'elderName',
+            'title': '长者姓名'
+      },
+      {
+            'key': 'assessor',
+            'title': '评估人'
+      },
+      {
+            'key': 'assessDate',
+            'title': '记录日期'
+      },
+      {
+            'key': 'assessScore',
+            'title': '评估总得分'
+      },
+      {
+            'key': 'riskLevelText',
+            'title': '结果等级'
+      },
+      {
+            'key': 'creator',
+            'title': '记录人'
+      }
+]
+
+    exportWithExpandedObjectArrays(processedData, headers, `日常生活活动能力评估_${new Date().getTime()}.xlsx`, '日常生活活动能力评估')
+    message.success('导出成功')
+  } catch (error) {
+    console.error('导出失败:', error)
+    message.error('导出失败,请重试')
+  } finally {
+    exportLoading.value = false
+  }
 }
 
 /** 查询列表 */

+ 74 - 33
src/views/elderly/apply/nine-precautions/empyrosis/index.vue

@@ -51,6 +51,7 @@
   <ContentWrap>
     <div class="mb-10px">
       <ButtonAdd @click="openForm(undefined)" />
+      <ButtonImport @click="handleImportCard" />
     </div>
     <el-table v-loading="loading" :data="list" :header-cell-style="tableHeaderColor">
       <el-table-column header-align="center" align="center" label="序号" width="60">
@@ -148,31 +149,16 @@
   </ContentWrap>
 
   <AddForm ref="formRef" @success="getList" />
-
-  <!-- 通用批量导出弹窗 -->
-  <BatchExportDialog
-    :show="showBatchExport"
-    :title="exportConfig.title"
-    :loading="exportLoading"
-    :batch-min="exportConfig.batchMin"
-    :batch-max="exportConfig.batchMax"
-    :count-min="exportConfig.countMin"
-    :count-max="exportConfig.countMax"
-    :default-batch="exportConfig.defaultBatch"
-    :default-count="exportConfig.defaultCount"
-    :description="exportConfig.description"
-    @update:show="showBatchExport = $event"
-    @confirm="handleBatchExport"
-    @cancel="showBatchExport = false"
-  />
 </template>
 
 <script setup lang="ts">
 import AddForm from './AddForm.vue'
 import ButtonAdd from '@/components/ButtonAdd/src/ButtonAdd.vue'
+import ButtonImport from '@/components/ButtonImport/src/ButtonImport.vue'
 import { useUserStore } from '@/store/modules/user'
 import { getCurrentMonthRange } from '@/utils/dateUtil'
 import { burnPreventionDelete, burnPreventionPage } from '@/api/social-work'
+import { exportWithExpandedObjectArrays } from '@/utils/excel-export'
 import { findLabelById } from '@/utils/dict'
 
 const message = useMessage()
@@ -182,20 +168,7 @@ const loading = ref(true)
 const total = ref(0)
 const list = ref([])
 
-// 状态管理
-const showBatchExport = ref(false)
-const exportConfig = ref({
-  title: '',
-  batchMin: 1,
-  batchMax: 999,
-  countMin: 1,
-  countMax: 200,
-  defaultBatch: 1,
-  defaultCount: 200,
-  description: [] as string[]
-})
 const exportLoading = ref(false)
-
 let queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
@@ -207,10 +180,78 @@ let queryParams = reactive({
 })
 const queryFormRef = ref()
 
-// 处理批量导出
-const handleBatchExport = async (batch: number, count: number) => {
+// 打开导出弹窗
+const handleImportCard = async () => {
   exportLoading.value = true
-  console.log(batch, count)
+  try {
+    const queryP = {
+      pageNo: 1,
+      pageSize: 9999,
+      elderName: queryParams.elderName,
+      assessor: queryParams.assessor,
+      assessDate: queryParams.assessDate,
+      tenantIds: queryParams.tenantIds
+    }
+    const data = await burnPreventionPage(queryP)
+    const exportData = data.list || []
+
+    if (exportData.length === 0) {
+      message.warning('暂无数据可导出')
+      return
+    }
+
+    const processedData = exportData.map((item) => {
+      const row: any = {
+        orgName: findLabelById(userStore.getOrgTenant.options, item.tenantId) || '',
+        elderName: item.elderName || '',
+        assessor: item.assessor || '',
+        assessDate: item.assessDate || '',
+        assessScore: item.assessScore ?? '',
+        creator: item.creator || ''
+      }
+      row.riskLevelText = getRiskLevelText(item.riskLevel) || '-'
+      return row
+    })
+
+    const headers = [
+      {
+            'key': 'orgName',
+            'title': '机构名称'
+      },
+      {
+            'key': 'elderName',
+            'title': '长者姓名'
+      },
+      {
+            'key': 'assessor',
+            'title': '评估人'
+      },
+      {
+            'key': 'assessDate',
+            'title': '记录日期'
+      },
+      {
+            'key': 'riskLevelText',
+            'title': '风险等级'
+      },
+      {
+            'key': 'assessScore',
+            'title': '评估总得分'
+      },
+      {
+            'key': 'creator',
+            'title': '记录人'
+      }
+]
+
+    exportWithExpandedObjectArrays(processedData, headers, `防烫伤评估_${new Date().getTime()}.xlsx`, '防烫伤评估')
+    message.success('导出成功')
+  } catch (error) {
+    console.error('导出失败:', error)
+    message.error('导出失败,请重试')
+  } finally {
+    exportLoading.value = false
+  }
 }
 
 /** 查询列表 */

+ 74 - 33
src/views/elderly/apply/nine-precautions/equilibrium/index.vue

@@ -51,6 +51,7 @@
   <ContentWrap>
     <div class="mb-10px">
       <ButtonAdd @click="openForm(undefined)" />
+      <ButtonImport @click="handleImportCard" />
     </div>
     <el-table v-loading="loading" :data="list" :header-cell-style="tableHeaderColor">
       <el-table-column header-align="center" align="center" label="序号" width="60">
@@ -148,31 +149,16 @@
   </ContentWrap>
 
   <AddForm ref="formRef" @success="getList" />
-
-  <!-- 通用批量导出弹窗 -->
-  <BatchExportDialog
-    :show="showBatchExport"
-    :title="exportConfig.title"
-    :loading="exportLoading"
-    :batch-min="exportConfig.batchMin"
-    :batch-max="exportConfig.batchMax"
-    :count-min="exportConfig.countMin"
-    :count-max="exportConfig.countMax"
-    :default-batch="exportConfig.defaultBatch"
-    :default-count="exportConfig.defaultCount"
-    :description="exportConfig.description"
-    @update:show="showBatchExport = $event"
-    @confirm="handleBatchExport"
-    @cancel="showBatchExport = false"
-  />
 </template>
 
 <script setup lang="ts">
 import AddForm from './AddForm.vue'
 import ButtonAdd from '@/components/ButtonAdd/src/ButtonAdd.vue'
+import ButtonImport from '@/components/ButtonImport/src/ButtonImport.vue'
 import { useUserStore } from '@/store/modules/user'
 import { getCurrentMonthRange } from '@/utils/dateUtil'
 import { equilibriumDelete, equilibriumPage } from '@/api/social-work'
+import { exportWithExpandedObjectArrays } from '@/utils/excel-export'
 import { findLabelById } from '@/utils/dict'
 
 const message = useMessage()
@@ -182,20 +168,7 @@ const loading = ref(true)
 const total = ref(0)
 const list = ref([])
 
-// 状态管理
-const showBatchExport = ref(false)
-const exportConfig = ref({
-  title: '',
-  batchMin: 1,
-  batchMax: 999,
-  countMin: 1,
-  countMax: 200,
-  defaultBatch: 1,
-  defaultCount: 200,
-  description: [] as string[]
-})
 const exportLoading = ref(false)
-
 let queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
@@ -207,10 +180,78 @@ let queryParams = reactive({
 })
 const queryFormRef = ref()
 
-// 处理批量导出
-const handleBatchExport = async (batch: number, count: number) => {
+// 打开导出弹窗
+const handleImportCard = async () => {
   exportLoading.value = true
-  console.log(batch, count)
+  try {
+    const queryP = {
+      pageNo: 1,
+      pageSize: 9999,
+      elderName: queryParams.elderName,
+      assessor: queryParams.assessor,
+      assessDate: queryParams.assessDate,
+      tenantIds: queryParams.tenantIds
+    }
+    const data = await equilibriumPage(queryP)
+    const exportData = data.list || []
+
+    if (exportData.length === 0) {
+      message.warning('暂无数据可导出')
+      return
+    }
+
+    const processedData = exportData.map((item) => {
+      const row: any = {
+        orgName: findLabelById(userStore.getOrgTenant.options, item.tenantId) || '',
+        elderName: item.elderName || '',
+        assessor: item.assessor || '',
+        assessDate: item.assessDate || '',
+        assessScore: item.assessScore ?? '',
+        creator: item.creator || ''
+      }
+      row.riskLevelText = getRiskLevelText(item.riskLevel) || '-'
+      return row
+    })
+
+    const headers = [
+      {
+            'key': 'orgName',
+            'title': '机构名称'
+      },
+      {
+            'key': 'elderName',
+            'title': '长者姓名'
+      },
+      {
+            'key': 'assessor',
+            'title': '评估人'
+      },
+      {
+            'key': 'assessDate',
+            'title': '记录日期'
+      },
+      {
+            'key': 'assessScore',
+            'title': '评估总得分'
+      },
+      {
+            'key': 'riskLevelText',
+            'title': '风险等级'
+      },
+      {
+            'key': 'creator',
+            'title': '记录人'
+      }
+]
+
+    exportWithExpandedObjectArrays(processedData, headers, `平衡能力评估_${new Date().getTime()}.xlsx`, '平衡能力评估')
+    message.success('导出成功')
+  } catch (error) {
+    console.error('导出失败:', error)
+    message.error('导出失败,请重试')
+  } finally {
+    exportLoading.value = false
+  }
 }
 
 /** 查询列表 */

+ 74 - 33
src/views/elderly/apply/nine-precautions/fall-down/index.vue

@@ -51,6 +51,7 @@
   <ContentWrap>
     <div class="mb-10px">
       <ButtonAdd @click="openForm(undefined)" />
+      <ButtonImport @click="handleImportCard" />
     </div>
     <el-table v-loading="loading" :data="list" :header-cell-style="tableHeaderColor">
       <el-table-column header-align="center" align="center" label="序号" width="60">
@@ -148,31 +149,16 @@
   </ContentWrap>
 
   <AddForm ref="formRef" @success="getList" />
-
-  <!-- 通用批量导出弹窗 -->
-  <BatchExportDialog
-    :show="showBatchExport"
-    :title="exportConfig.title"
-    :loading="exportLoading"
-    :batch-min="exportConfig.batchMin"
-    :batch-max="exportConfig.batchMax"
-    :count-min="exportConfig.countMin"
-    :count-max="exportConfig.countMax"
-    :default-batch="exportConfig.defaultBatch"
-    :default-count="exportConfig.defaultCount"
-    :description="exportConfig.description"
-    @update:show="showBatchExport = $event"
-    @confirm="handleBatchExport"
-    @cancel="showBatchExport = false"
-  />
 </template>
 
 <script setup lang="ts">
 import AddForm from './AddForm.vue'
 import ButtonAdd from '@/components/ButtonAdd/src/ButtonAdd.vue'
+import ButtonImport from '@/components/ButtonImport/src/ButtonImport.vue'
 import { useUserStore } from '@/store/modules/user'
 import { getCurrentMonthRange } from '@/utils/dateUtil'
 import { fallDownDelete, fallDownPage } from '@/api/social-work'
+import { exportWithExpandedObjectArrays } from '@/utils/excel-export'
 import { findLabelById } from '@/utils/dict'
 
 const message = useMessage()
@@ -182,20 +168,7 @@ const loading = ref(true)
 const total = ref(0)
 const list = ref([])
 
-// 状态管理
-const showBatchExport = ref(false)
-const exportConfig = ref({
-  title: '',
-  batchMin: 1,
-  batchMax: 999,
-  countMin: 1,
-  countMax: 200,
-  defaultBatch: 1,
-  defaultCount: 200,
-  description: [] as string[]
-})
 const exportLoading = ref(false)
-
 let queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
@@ -207,10 +180,78 @@ let queryParams = reactive({
 })
 const queryFormRef = ref()
 
-// 处理批量导出
-const handleBatchExport = async (batch: number, count: number) => {
+// 打开导出弹窗
+const handleImportCard = async () => {
   exportLoading.value = true
-  console.log(batch, count)
+  try {
+    const queryP = {
+      pageNo: 1,
+      pageSize: 9999,
+      elderName: queryParams.elderName,
+      assessor: queryParams.assessor,
+      assessDate: queryParams.assessDate,
+      tenantIds: queryParams.tenantIds
+    }
+    const data = await fallDownPage(queryP)
+    const exportData = data.list || []
+
+    if (exportData.length === 0) {
+      message.warning('暂无数据可导出')
+      return
+    }
+
+    const processedData = exportData.map((item) => {
+      const row: any = {
+        orgName: findLabelById(userStore.getOrgTenant.options, item.tenantId) || '',
+        elderName: item.elderName || '',
+        assessor: item.assessor || '',
+        assessDate: item.assessDate || '',
+        assessScore: item.assessScore ?? '',
+        creator: item.creator || ''
+      }
+      row.riskLevelText = getRiskLevelText(item.riskLevel) || '-'
+      return row
+    })
+
+    const headers = [
+      {
+            'key': 'orgName',
+            'title': '机构名称'
+      },
+      {
+            'key': 'elderName',
+            'title': '长者姓名'
+      },
+      {
+            'key': 'assessor',
+            'title': '评估人'
+      },
+      {
+            'key': 'assessDate',
+            'title': '记录日期'
+      },
+      {
+            'key': 'assessScore',
+            'title': '评估总得分'
+      },
+      {
+            'key': 'riskLevelText',
+            'title': '风险等级'
+      },
+      {
+            'key': 'creator',
+            'title': '记录人'
+      }
+]
+
+    exportWithExpandedObjectArrays(processedData, headers, `跌倒风险评估_${new Date().getTime()}.xlsx`, '跌倒风险评估')
+    message.success('导出成功')
+  } catch (error) {
+    console.error('导出失败:', error)
+    message.error('导出失败,请重试')
+  } finally {
+    exportLoading.value = false
+  }
 }
 
 /** 查询列表 */

+ 74 - 33
src/views/elderly/apply/nine-precautions/fall-prevention-measures/index.vue

@@ -51,6 +51,7 @@
   <ContentWrap>
     <div class="mb-10px">
       <ButtonAdd @click="openForm(undefined)" />
+      <ButtonImport @click="handleImportCard" />
     </div>
     <el-table v-loading="loading" :data="list" :header-cell-style="tableHeaderColor">
       <el-table-column header-align="center" align="center" label="序号" width="60">
@@ -148,31 +149,16 @@
   </ContentWrap>
 
   <AddForm ref="formRef" @success="getList" />
-
-  <!-- 通用批量导出弹窗 -->
-  <BatchExportDialog
-    :show="showBatchExport"
-    :title="exportConfig.title"
-    :loading="exportLoading"
-    :batch-min="exportConfig.batchMin"
-    :batch-max="exportConfig.batchMax"
-    :count-min="exportConfig.countMin"
-    :count-max="exportConfig.countMax"
-    :default-batch="exportConfig.defaultBatch"
-    :default-count="exportConfig.defaultCount"
-    :description="exportConfig.description"
-    @update:show="showBatchExport = $event"
-    @confirm="handleBatchExport"
-    @cancel="showBatchExport = false"
-  />
 </template>
 
 <script setup lang="ts">
 import AddForm from './AddForm.vue'
 import ButtonAdd from '@/components/ButtonAdd/src/ButtonAdd.vue'
+import ButtonImport from '@/components/ButtonImport/src/ButtonImport.vue'
 import { useUserStore } from '@/store/modules/user'
 import { getCurrentMonthRange } from '@/utils/dateUtil'
 import { fallPreventionDelete, fallPreventionPage } from '@/api/social-work'
+import { exportWithExpandedObjectArrays } from '@/utils/excel-export'
 import { findLabelById } from '@/utils/dict'
 
 const message = useMessage()
@@ -182,20 +168,7 @@ const loading = ref(true)
 const total = ref(0)
 const list = ref([])
 
-// 状态管理
-const showBatchExport = ref(false)
-const exportConfig = ref({
-  title: '',
-  batchMin: 1,
-  batchMax: 999,
-  countMin: 1,
-  countMax: 200,
-  defaultBatch: 1,
-  defaultCount: 200,
-  description: [] as string[]
-})
 const exportLoading = ref(false)
-
 let queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
@@ -207,10 +180,78 @@ let queryParams = reactive({
 })
 const queryFormRef = ref()
 
-// 处理批量导出
-const handleBatchExport = async (batch: number, count: number) => {
+// 打开导出弹窗
+const handleImportCard = async () => {
   exportLoading.value = true
-  console.log(batch, count)
+  try {
+    const queryP = {
+      pageNo: 1,
+      pageSize: 9999,
+      elderName: queryParams.elderName,
+      assessor: queryParams.assessor,
+      assessDate: queryParams.assessDate,
+      tenantIds: queryParams.tenantIds
+    }
+    const data = await fallPreventionPage(queryP)
+    const exportData = data.list || []
+
+    if (exportData.length === 0) {
+      message.warning('暂无数据可导出')
+      return
+    }
+
+    const processedData = exportData.map((item) => {
+      const row: any = {
+        orgName: findLabelById(userStore.getOrgTenant.options, item.tenantId) || '',
+        elderName: item.elderName || '',
+        assessor: item.assessor || '',
+        assessDate: item.assessDate || '',
+        assessScore: item.assessScore ?? '',
+        creator: item.creator || ''
+      }
+      row.riskLevelText = getRiskLevelText(item.riskLevel) || '-'
+      return row
+    })
+
+    const headers = [
+      {
+            'key': 'orgName',
+            'title': '机构名称'
+      },
+      {
+            'key': 'elderName',
+            'title': '长者姓名'
+      },
+      {
+            'key': 'assessor',
+            'title': '评估人'
+      },
+      {
+            'key': 'assessDate',
+            'title': '记录日期'
+      },
+      {
+            'key': 'assessScore',
+            'title': '评估总得分'
+      },
+      {
+            'key': 'riskLevelText',
+            'title': '风险等级'
+      },
+      {
+            'key': 'creator',
+            'title': '记录人'
+      }
+]
+
+    exportWithExpandedObjectArrays(processedData, headers, `防坠床评估_${new Date().getTime()}.xlsx`, '防坠床评估')
+    message.success('导出成功')
+  } catch (error) {
+    console.error('导出失败:', error)
+    message.error('导出失败,请重试')
+  } finally {
+    exportLoading.value = false
+  }
 }
 
 /** 查询列表 */

+ 79 - 4
src/views/elderly/apply/nine-precautions/nutritional-risk/index.vue

@@ -1,7 +1,9 @@
 <script setup lang="ts">
+import ButtonImport from '@/components/ButtonImport/src/ButtonImport.vue'
 import { onMounted, ref, reactive } from 'vue'
 import { ContentWrap } from '@/components/ContentWrap'
 import { nutritionalRiskPage, nutritionalRiskDelete } from '@/api/social-work'
+import { exportWithExpandedObjectArrays } from '@/utils/excel-export'
 import AddForm from './AddForm.vue'
 import { useUserStore } from '@/store/modules/user'
 import { tableHeaderColor } from '@/utils/table'
@@ -28,6 +30,82 @@ let queryParams = reactive({
 })
 const queryFormRef = ref()
 
+const exportLoading = ref(false)
+
+// 打开导出弹窗
+const handleImportCard = async () => {
+  exportLoading.value = true
+  try {
+    const queryP = {
+      pageNo: 1,
+      pageSize: 9999,
+      elderName: queryParams.elderName,
+      assessor: queryParams.assessor,
+      assessDate: queryParams.assessDate,
+      tenantIds: queryParams.tenantIds
+    }
+    const data = await nutritionalRiskPage(queryP)
+    const exportData = data.list || []
+
+    if (exportData.length === 0) {
+      message.warning('暂无数据可导出')
+      return
+    }
+
+    const processedData = exportData.map((item) => {
+      const row: any = {
+        orgName: findLabelById(userStore.getOrgTenant.options, item.tenantId) || '',
+        elderName: item.elderName || '',
+        assessor: item.assessor || '',
+        assessDate: item.assessDate || '',
+        assessScore: item.assessScore ?? '',
+        creator: item.creator || ''
+      }
+      row.riskLevelText = getResultLevelText(item.riskLevel) || '-'
+      return row
+    })
+
+    const headers = [
+      {
+            'key': 'orgName',
+            'title': '机构名称'
+      },
+      {
+            'key': 'elderName',
+            'title': '长者姓名'
+      },
+      {
+            'key': 'assessor',
+            'title': '评估人'
+      },
+      {
+            'key': 'assessDate',
+            'title': '记录日期'
+      },
+      {
+            'key': 'assessScore',
+            'title': '量表总分'
+      },
+      {
+            'key': 'riskLevelText',
+            'title': '评估结果'
+      },
+      {
+            'key': 'creator',
+            'title': '记录人'
+      }
+]
+
+    exportWithExpandedObjectArrays(processedData, headers, `营养风险评估_${new Date().getTime()}.xlsx`, '营养风险评估')
+    message.success('导出成功')
+  } catch (error) {
+    console.error('导出失败:', error)
+    message.error('导出失败,请重试')
+  } finally {
+    exportLoading.value = false
+  }
+}
+
 /** 查询列表 */
 const getList = async () => {
   loading.value = true
@@ -84,10 +162,6 @@ const openClose = async (row: any) => {
   }
 }
 
-const handleExport = () => {
-  message.info('导出功能开发中')
-}
-
 const getResultLevelType = (level: string) => {
   const typeMap: Record<string, string> = {
     good: 'success',
@@ -201,6 +275,7 @@ onMounted(async () => {
   <ContentWrap>
     <div class="mb-10px">
       <ButtonAdd @click="openForm(undefined)" />
+      <ButtonImport @click="handleImportCard" />
     </div>
     <el-table v-loading="loading" :data="list" :header-cell-style="tableHeaderColor">
       <el-table-column header-align="center" align="center" label="序号" width="60">

+ 74 - 33
src/views/elderly/apply/nine-precautions/pressure-sores/index.vue

@@ -51,6 +51,7 @@
   <ContentWrap>
     <div class="mb-10px">
       <ButtonAdd @click="openForm(undefined)" />
+      <ButtonImport @click="handleImportCard" />
     </div>
     <el-table v-loading="loading" :data="list" :header-cell-style="tableHeaderColor">
       <el-table-column header-align="center" align="center" label="序号" width="60">
@@ -148,31 +149,16 @@
   </ContentWrap>
 
   <AddForm ref="formRef" @success="getList" />
-
-  <!-- 通用批量导出弹窗 -->
-  <BatchExportDialog
-    :show="showBatchExport"
-    :title="exportConfig.title"
-    :loading="exportLoading"
-    :batch-min="exportConfig.batchMin"
-    :batch-max="exportConfig.batchMax"
-    :count-min="exportConfig.countMin"
-    :count-max="exportConfig.countMax"
-    :default-batch="exportConfig.defaultBatch"
-    :default-count="exportConfig.defaultCount"
-    :description="exportConfig.description"
-    @update:show="showBatchExport = $event"
-    @confirm="handleBatchExport"
-    @cancel="showBatchExport = false"
-  />
 </template>
 
 <script setup lang="ts">
 import AddForm from './AddForm.vue'
 import ButtonAdd from '@/components/ButtonAdd/src/ButtonAdd.vue'
+import ButtonImport from '@/components/ButtonImport/src/ButtonImport.vue'
 import { useUserStore } from '@/store/modules/user'
 import { getCurrentMonthRange } from '@/utils/dateUtil'
 import { pressureSoresDelete, pressureSoresPage } from '@/api/social-work'
+import { exportWithExpandedObjectArrays } from '@/utils/excel-export'
 import { findLabelById } from '@/utils/dict'
 
 const message = useMessage()
@@ -182,20 +168,7 @@ const loading = ref(true)
 const total = ref(0)
 const list = ref([])
 
-// 状态管理
-const showBatchExport = ref(false)
-const exportConfig = ref({
-  title: '',
-  batchMin: 1,
-  batchMax: 999,
-  countMin: 1,
-  countMax: 200,
-  defaultBatch: 1,
-  defaultCount: 200,
-  description: [] as string[]
-})
 const exportLoading = ref(false)
-
 let queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
@@ -207,10 +180,78 @@ let queryParams = reactive({
 })
 const queryFormRef = ref()
 
-// 处理批量导出
-const handleBatchExport = async (batch: number, count: number) => {
+// 打开导出弹窗
+const handleImportCard = async () => {
   exportLoading.value = true
-  console.log(batch, count)
+  try {
+    const queryP = {
+      pageNo: 1,
+      pageSize: 9999,
+      elderName: queryParams.elderName,
+      assessor: queryParams.assessor,
+      assessDate: queryParams.assessDate,
+      tenantIds: queryParams.tenantIds
+    }
+    const data = await pressureSoresPage(queryP)
+    const exportData = data.list || []
+
+    if (exportData.length === 0) {
+      message.warning('暂无数据可导出')
+      return
+    }
+
+    const processedData = exportData.map((item) => {
+      const row: any = {
+        orgName: findLabelById(userStore.getOrgTenant.options, item.tenantId) || '',
+        elderName: item.elderName || '',
+        assessor: item.assessor || '',
+        assessDate: item.assessDate || '',
+        assessScore: item.assessScore ?? '',
+        creator: item.creator || ''
+      }
+      row.riskLevelText = getRiskLevelText(item.riskLevel) || '-'
+      return row
+    })
+
+    const headers = [
+      {
+            'key': 'orgName',
+            'title': '机构名称'
+      },
+      {
+            'key': 'elderName',
+            'title': '长者姓名'
+      },
+      {
+            'key': 'assessor',
+            'title': '评估人'
+      },
+      {
+            'key': 'assessDate',
+            'title': '记录日期'
+      },
+      {
+            'key': 'assessScore',
+            'title': '评估总得分'
+      },
+      {
+            'key': 'riskLevelText',
+            'title': '风险等级'
+      },
+      {
+            'key': 'creator',
+            'title': '记录人'
+      }
+]
+
+    exportWithExpandedObjectArrays(processedData, headers, `防压疮评估_${new Date().getTime()}.xlsx`, '防压疮评估')
+    message.success('导出成功')
+  } catch (error) {
+    console.error('导出失败:', error)
+    message.error('导出失败,请重试')
+  } finally {
+    exportLoading.value = false
+  }
 }
 
 /** 查询列表 */

+ 29 - 12
src/views/elderly/apply/nine-precautions/risk-disclosure-statement/index.vue

@@ -48,9 +48,7 @@
         <el-button type="primary" @click="handleAdd">
           <Icon icon="ep:plus" class="mr-5px" /> 新增
         </el-button>
-        <el-button type="success" @click="handleExport">
-          <Icon icon="ep:upload" class="mr-5px" /> 导出
-        </el-button>
+        <ButtonImport @click="handleImportCard" />
       </template>
     </TabBarBtn>
 
@@ -242,6 +240,7 @@ import AttackForm from '@/views/elderly/apply/nine-precautions/attack/AddForm.vu
 import AntiEntertainmentForm from '@/views/elderly/apply/nine-precautions/anti-entertainment/AddForm.vue'
 import DailyLifeForm from '@/views/elderly/apply/nine-precautions/daily-life/AddForm.vue'
 import NutritionalRiskForm from '@/views/elderly/apply/nine-precautions/nutritional-risk/AddForm.vue'
+import ButtonImport from '@/components/ButtonImport/src/ButtonImport.vue'
 import { useUserStore } from '@/store/modules/user'
 import { formatToDateTime } from '@/utils/dateUtil'
 import { exportWithExpandedObjectArrays } from '@/utils/excel-export'
@@ -381,16 +380,31 @@ const getRiskLevelText = (riskLevel: string) => {
   }
 }
 
-// 导出
-const handleExport = async () => {
+const exportLoading = ref(false)
+
+// 打开导出弹窗
+const handleImportCard = async () => {
+  exportLoading.value = true
   try {
-    if (!list.value || (list.value as any[]).length <= 0) {
-      message.error('暂无数据可以导出!')
+    const queryP = {
+      pageNo: 1,
+      pageSize: 9999,
+      elderName: queryParams.elderName,
+      floorName: queryParams.floorName,
+      tenantIds: queryParams.tenantIds
+    }
+    const data = await getSafetyRiskNoticePage(queryP)
+    const exportList = (data.list || []).map((item: any) => ({
+      ...item,
+      riskData: parseRiskData(item)
+    }))
+
+    if (exportList.length === 0) {
+      message.warning('暂无数据可导出')
       return
     }
 
-    // 预处理数据:解析 riskData 中各风险字段并映射为中文
-    const exportList = (list.value as any[]).map((row, index) => {
+    const processedData = exportList.map((row: any, index: number) => {
       const rd = row.riskData || {}
       return {
         index: index + 1,
@@ -436,14 +450,17 @@ const handleExport = async () => {
     ]
 
     exportWithExpandedObjectArrays(
-      exportList,
+      processedData,
       headers,
-      `安全风险告知书${formatToDateTime()}.xlsx`,
+      `安全风险告知书_${new Date().getTime()}.xlsx`,
       '安全风险告知书'
     )
+    message.success('导出成功')
   } catch (error) {
     console.error('导出失败:', error)
-    message.error('导出失败!')
+    message.error('导出失败,请重试')
+  } finally {
+    exportLoading.value = false
   }
 }
 

+ 74 - 33
src/views/elderly/apply/nine-precautions/wander-away/index.vue

@@ -51,6 +51,7 @@
   <ContentWrap>
     <div class="mb-10px">
       <ButtonAdd @click="openForm(undefined)" />
+      <ButtonImport @click="handleImportCard" />
     </div>
     <el-table v-loading="loading" :data="list" :header-cell-style="tableHeaderColor">
       <el-table-column header-align="center" align="center" label="序号" width="60">
@@ -148,31 +149,16 @@
   </ContentWrap>
 
   <AddForm ref="formRef" @success="getList" />
-
-  <!-- 通用批量导出弹窗 -->
-  <BatchExportDialog
-    :show="showBatchExport"
-    :title="exportConfig.title"
-    :loading="exportLoading"
-    :batch-min="exportConfig.batchMin"
-    :batch-max="exportConfig.batchMax"
-    :count-min="exportConfig.countMin"
-    :count-max="exportConfig.countMax"
-    :default-batch="exportConfig.defaultBatch"
-    :default-count="exportConfig.defaultCount"
-    :description="exportConfig.description"
-    @update:show="showBatchExport = $event"
-    @confirm="handleBatchExport"
-    @cancel="showBatchExport = false"
-  />
 </template>
 
 <script setup lang="ts">
 import AddForm from './AddForm.vue'
 import ButtonAdd from '@/components/ButtonAdd/src/ButtonAdd.vue'
+import ButtonImport from '@/components/ButtonImport/src/ButtonImport.vue'
 import { useUserStore } from '@/store/modules/user'
 import { getCurrentMonthRange } from '@/utils/dateUtil'
 import { wanderAwayDelete, wanderAwayPage } from '@/api/social-work'
+import { exportWithExpandedObjectArrays } from '@/utils/excel-export'
 import { findLabelById } from '@/utils/dict'
 
 const message = useMessage()
@@ -182,20 +168,7 @@ const loading = ref(true)
 const total = ref(0)
 const list = ref([])
 
-// 状态管理
-const showBatchExport = ref(false)
-const exportConfig = ref({
-  title: '',
-  batchMin: 1,
-  batchMax: 999,
-  countMin: 1,
-  countMax: 200,
-  defaultBatch: 1,
-  defaultCount: 200,
-  description: [] as string[]
-})
 const exportLoading = ref(false)
-
 let queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
@@ -207,10 +180,78 @@ let queryParams = reactive({
 })
 const queryFormRef = ref()
 
-// 处理批量导出
-const handleBatchExport = async (batch: number, count: number) => {
+// 打开导出弹窗
+const handleImportCard = async () => {
   exportLoading.value = true
-  console.log(batch, count)
+  try {
+    const queryP = {
+      pageNo: 1,
+      pageSize: 9999,
+      elderName: queryParams.elderName,
+      assessor: queryParams.assessor,
+      assessDate: queryParams.assessDate,
+      tenantIds: queryParams.tenantIds
+    }
+    const data = await wanderAwayPage(queryP)
+    const exportData = data.list || []
+
+    if (exportData.length === 0) {
+      message.warning('暂无数据可导出')
+      return
+    }
+
+    const processedData = exportData.map((item) => {
+      const row: any = {
+        orgName: findLabelById(userStore.getOrgTenant.options, item.tenantId) || '',
+        elderName: item.elderName || '',
+        assessor: item.assessor || '',
+        assessDate: item.assessDate || '',
+        assessScore: item.assessScore ?? '',
+        creator: item.creator || ''
+      }
+      row.riskLevelText = getRiskLevelText(item.riskLevel) || '-'
+      return row
+    })
+
+    const headers = [
+      {
+            'key': 'orgName',
+            'title': '机构名称'
+      },
+      {
+            'key': 'elderName',
+            'title': '长者姓名'
+      },
+      {
+            'key': 'assessor',
+            'title': '评估人'
+      },
+      {
+            'key': 'assessDate',
+            'title': '记录日期'
+      },
+      {
+            'key': 'assessScore',
+            'title': '评估总得分'
+      },
+      {
+            'key': 'riskLevelText',
+            'title': '风险等级'
+      },
+      {
+            'key': 'creator',
+            'title': '记录人'
+      }
+]
+
+    exportWithExpandedObjectArrays(processedData, headers, `防走失风险评估_${new Date().getTime()}.xlsx`, '防走失风险评估')
+    message.success('导出成功')
+  } catch (error) {
+    console.error('导出失败:', error)
+    message.error('导出失败,请重试')
+  } finally {
+    exportLoading.value = false
+  }
 }
 
 /** 查询列表 */

+ 1 - 1
src/views/elderly/contracts/components/DocumentAttachmentBody.vue

@@ -118,7 +118,7 @@ const handleFileChange = async (e: Event) => {
         }
       } catch (error) {
         console.error('PDF 解析失败', error)
-        message.error(`PDF 解析失败:${file.name}`)
+        message.error(`PDF 解析失败:${file.name}-${error}`)
       }
     } else {
       await uploadSingleFile(file)

+ 3 - 2
vite.config.ts

@@ -89,7 +89,8 @@ export default ({command, mode}: ConfigEnv): UserConfig => {
             rollupOptions: {
                 output: {
                   chunkFileNames: (chunkInfo) => {
-                      // 只要 chunk 名字包含 pdf.worker,就直接抛到根目录并命名为 pdf.worker.js
+                      // pdf.worker 保持固定文件名,云端 nginx 通常针对该路径配置了 .mjs 的 MIME;
+                      // 改名会导致 module worker MIME 校验失败。缓存问题通过 URL query 参数解决(见 useUpload.ts)
                       if (chunkInfo.name && chunkInfo.name.includes('pdf.worker')) {
                         return 'pdf.worker.js';
                       }
@@ -97,7 +98,7 @@ export default ({command, mode}: ConfigEnv): UserConfig => {
                     },
                     entryFileNames: 'assets/js/[name]-[hash].js',
                     assetFileNames: (chunkInfo) => {
-                      // public 目录下的 pdf worker 保持原文件名,否则 pdfjs 找不到 worker
+                      // pdf.worker 保持固定文件名,避免云端 nginx 对新文件名不匹配 MIME 规则
                       if (chunkInfo.name && chunkInfo.name.includes('pdf.worker')) {
                         return 'pdf.worker.mjs'
                       }

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor