Procházet zdrojové kódy

生命体征监测单人导出表格

xiongxing před 1 měsícem
rodič
revize
e4c06a59ee
1 změnil soubory, kde provedl 76 přidání a 75 odebrání
  1. 76 75
      src/views/elderly/assess/vital-sign/index.vue

+ 76 - 75
src/views/elderly/assess/vital-sign/index.vue

@@ -36,7 +36,13 @@
 
   <!-- 列表 -->
   <ContentWrap v-if="!visible">
-    <TabBarBtn @add="openForm()" @export="handleExport" @del="handleDelete" />
+    <TabBarBtn @add="openForm()" @export="handleExport" @del="handleDelete">
+      <template #next>
+        <el-button type="warning" plain @click="handleSingleExport">
+          <Icon icon="ep:download" class="mr-5px" /> 单人导出
+        </el-button>
+      </template>
+    </TabBarBtn>
     <Table2
       selection
       @selectionChange="handleSelectionChange"
@@ -45,14 +51,7 @@
       :columns="VitalSignColumns"
       :queryParams="queryParams"
       @detail="openDetail"
-      :opWidth="220"
-    >
-      <template #next="{ scope }">
-        <el-button link type="primary" @click="handleRowExport(scope)">
-          <Icon icon="ep:download" class="mr-5px" /> 导出
-        </el-button>
-      </template>
-    </Table2>
+    />
 
     <!-- 分页 -->
     <Pagination
@@ -75,8 +74,6 @@ import Export from './Export.vue'
 import Detail from './Detail.vue'
 import { useUserStore } from '@/store/modules/user'
 import * as XLSX from 'xlsx-js-style'
-import { getDictLabel } from '@/utils/dict'
-import { DICT_TYPE } from '@/utils/dict'
 import { formatTime } from '@/utils'
 defineOptions({ name: 'VitalSign' })
 const userStore = useUserStore()
@@ -163,93 +160,90 @@ const handleDelete = async () => {
   } catch {}
 }
 
-/** 单行导出 */
-const handleRowExport = (row: any) => {
+/** 去除指标值中的偏高/偏低标记,只保留原始数值(如 36.5(偏高) => 36.5) */
+const stripMetric = (val: any) => {
+  if (val === null || val === undefined || val === '') return ''
+  const str = String(val)
+  const indexEn = str.indexOf('(')
+  const indexCn = str.indexOf('(')
+  let index = -1
+  if (indexEn !== -1 && indexCn !== -1) {
+    index = Math.min(indexEn, indexCn)
+  } else {
+    index = indexEn !== -1 ? indexEn : indexCn
+  }
+  return index === -1 ? str : str.substring(0, index).trim()
+}
+
+/** 单人导出 */
+const handleSingleExport = async () => {
+  if (!queryParams.elderName) {
+    message.warning('请先输入长者姓名')
+    return
+  }
   const wb = XLSX.utils.book_new()
-  const headers = [
-    '体温℃',
-    '脉搏/分',
-    '呼吸/分',
-    '收缩压mmHg',
-    '舒张压mmHg',
-    '血压饱和度%',
-    '血糖mmol/L',
-    '体重kg',
-    '大便',
-    '小便',
-    '备注',
-    '测量人',
-    '测量时间',
-    '测量日期'
-  ]
+  const headers = ['日期', '时间', '体温', '脉搏', '呼吸', '血压', '血氧']
   const colCount = headers.length
-  const sexText = getDictLabel(DICT_TYPE.SYSTEM_USER_SEX, row.elderSex) || row.elderSex
-  const measuringDateText = row.measuringDate ? formatTime(row.measuringDate, 'yyyy-MM-dd') : ''
+
+  // 查询该长者所有数据
+  const data = await getVitalSignsPage({ ...queryParams, pageNo: 1, pageSize: 99999 })
+  const records: Recordable[] = data.list || []
+  if (records.length === 0) {
+    message.warning('未查询到该长者的生命体征数据')
+    return
+  }
 
   // 标题行
   const titleRow: string[] = new Array(colCount).fill('')
   titleRow[0] = '生命体征'
 
-  // 基本信息行:姓名 / 性别 / 床号 均匀分布,中间留空列
+  // 基本信息行:姓名 / 床号
+  const first = records[0]
   const infoItems = [
-    { label: '姓名:', value: row.elderName || '', start: 0, span: 4 },
-    { label: '性别:', value: sexText, start: 5, span: 4 },
-    { label: '床号:', value: row.bedName || '', start: 10, span: 4 }
+    { label: '姓名:', value: first.elderName || '', start: 0, span: 3 },
+    { label: '床号:', value: first.bedName || '', start: 4, span: 3 }
   ]
   const infoRow: string[] = new Array(colCount).fill('')
   infoItems.forEach((item) => {
     infoRow[item.start] = item.label + item.value
   })
 
-  // 表头行
-  const headerRow = headers
-
   // 数据行
-  const dataRow = [
-    row.temperature,
-    row.pulse,
-    row.respiratoryRate,
-    row.systolicPressure,
-    row.diastolicPressure,
-    row.bloodOxygenSaturation,
-    row.bloodSugar,
-    row.weight,
-    row.stool,
-    row.urinate,
-    row.remark,
-    row.measuringName,
-    row.measuringTime,
-    measuringDateText
-  ]
+  const dataRows = records.map((row: any) => [
+    row.measuringDate ? formatTime(row.measuringDate, 'yyyy-MM-dd') : '',
+    row.measuringTime || '',
+    stripMetric(row.temperature),
+    stripMetric(row.pulse),
+    stripMetric(row.respiratoryRate),
+    [stripMetric(row.systolicPressure), stripMetric(row.diastolicPressure)].filter(Boolean).join('/'),
+    stripMetric(row.bloodOxygenSaturation)
+  ])
+
+  // 护士签名行
+  const nurseSignRow: string[] = new Array(colCount).fill('')
+  nurseSignRow[0] = '护士签名:'
 
-  const ws = XLSX.utils.aoa_to_sheet([titleRow, infoRow, headerRow, dataRow])
+  const ws = XLSX.utils.aoa_to_sheet([titleRow, infoRow, headers, ...dataRows, nurseSignRow])
 
   // 合并单元格
+  const nurseSignRowIndex = 3 + dataRows.length
   ws['!merges'] = [
     { s: { r: 0, c: 0 }, e: { r: 0, c: colCount - 1 } },
-    ...infoItems.map((item) => ({ s: { r: 1, c: item.start }, e: { r: 1, c: item.start + item.span - 1 } }))
+    ...infoItems.map((item) => ({ s: { r: 1, c: item.start }, e: { r: 1, c: item.start + item.span - 1 } })),
+    { s: { r: nurseSignRowIndex, c: 0 }, e: { r: nurseSignRowIndex, c: colCount - 1 } }
   ]
 
   // 列宽
-  ws['!cols'] = [
-    { wch: 18 },
-    { wch: 10 },
-    { wch: 10 },
-    { wch: 10 },
-    { wch: 10 },
-    { wch: 10 },
-    { wch: 10 },
-    { wch: 10 },
-    { wch: 10 },
-    { wch: 10 },
-    { wch: 10 },
-    { wch: 10 },
-    { wch: 10 },
-    { wch: 15 }
-  ]
+  ws['!cols'] = [{ wch: 14 }, { wch: 12 }, { wch: 10 }, { wch: 10 }, { wch: 10 }, { wch: 12 }, { wch: 10 }]
 
   // 行高
-  ws['!rows'] = [{ hpt: 38 }, { hpt: 28 }, { hpt: 32 }, { hpt: 28 }]
+  ws['!rows'] = [
+    { hpt: 38 },
+    { hpt: 28 },
+    { hpt: 32 },
+    ...dataRows.map(() => ({ hpt: 28 })),
+    { hpt: 34 }
+  ]
 
   const range = XLSX.utils.decode_range(ws['!ref'] || '')
   const headerFill = {
@@ -271,25 +265,32 @@ const handleRowExport = (row: any) => {
       }
       const cell = ws[cellRef]
       cell.s = cell.s || {}
-      cell.s.border = border
       cell.s.alignment = { vertical: 'center', horizontal: 'center', wrapText: true }
 
       if (R === 0) {
+        cell.s.border = border
         cell.s.font = { bold: true, sz: 18, name: '宋体' }
       } else if (R === 1) {
+        cell.s.border = border
         cell.s.alignment = { vertical: 'center', horizontal: 'left', wrapText: true }
         cell.s.font = { bold: true, sz: 11, name: '宋体' }
       } else if (R === 2) {
+        cell.s.border = border
         cell.s.fill = headerFill
         cell.s.font = { bold: true, sz: 11, name: '宋体' }
+      } else if (R === nurseSignRowIndex) {
+        // 护士签名行:位于表格下方,无边框,左对齐,留空手签
+        cell.s.alignment = { vertical: 'center', horizontal: 'left' }
+        cell.s.font = { bold: true, sz: 11, name: '宋体' }
       } else {
+        cell.s.border = border
         cell.s.font = { sz: 11, name: '宋体' }
       }
     }
   }
 
   XLSX.utils.book_append_sheet(wb, ws, '生命体征')
-  XLSX.writeFile(wb, `${row.elderName || '生命体征'}_${measuringDateText || ''}.xlsx`)
+  XLSX.writeFile(wb, `生命体征_${queryParams.elderName}.xlsx`)
 }
 
 /** 初始化 **/