浏览代码

月报汇总

yanghao 1 天之前
父节点
当前提交
d98784cf1b
共有 2 个文件被更改,包括 214 次插入177 次删除
  1. 10 5
      src/views/pms/qhse/reportSummary/data.json
  2. 204 172
      src/views/pms/qhse/reportSummary/preview-drawer.vue

+ 10 - 5
src/views/pms/qhse/reportSummary/data.json

@@ -40,7 +40,8 @@
         "remark": "hhhhhhhhhhh",
         "dutyPerson": 1,
         "createTime": 1782377575000,
-        "personName": "超级管理员"
+        "personName": "超级管理员",
+        "deptName": "5#项目公司"
       },
       {
         "id": 4,
@@ -80,7 +81,8 @@
         "remark": "她她她她她她她她她她她她",
         "dutyPerson": 1,
         "createTime": 1782377575000,
-        "personName": "超级管理员"
+        "personName": "超级管理员",
+        "deptName": "四川瑞都"
       },
       {
         "id": 3,
@@ -120,7 +122,8 @@
         "remark": null,
         "dutyPerson": 1,
         "createTime": 1782377575000,
-        "personName": "超级管理员"
+        "personName": "超级管理员",
+        "deptName": "瑞恒兴域"
       },
       {
         "id": 2,
@@ -160,7 +163,8 @@
         "remark": null,
         "dutyPerson": 1,
         "createTime": 1782377575000,
-        "personName": "超级管理员"
+        "personName": "超级管理员",
+        "deptName": "瑞鹰国际"
       },
       {
         "id": 1,
@@ -200,7 +204,8 @@
         "remark": null,
         "dutyPerson": 1,
         "createTime": 1782199003000,
-        "personName": "超级管理员"
+        "personName": "超级管理员",
+        "deptName": "科瑞石油技术~~en**Kerui Petroleum Technology~~ru**"
       }
     ],
     "total": 5

+ 204 - 172
src/views/pms/qhse/reportSummary/preview-drawer.vue

@@ -3,8 +3,7 @@ import { QhseMonthReportSummaryApi } from '@/api/pms/qhse'
 import type {
   QhseMonthReportItem,
   ReportCompanyColumn,
-  ReportMetricRow,
-  ReportMetricValue
+  ReportMetricRow
 } from './types'
 import dayjs from 'dayjs'
 import { computed, ref, watch } from 'vue'
@@ -26,165 +25,181 @@ const props = defineProps<Props>()
 const emits = defineEmits(['update:visible'])
 
 const loading = ref(false)
-const report = ref<QhseMonthReportItem>()
-
-const companyColumns: ReportCompanyColumn[] = [
-  { key: 'rhxy', label: '瑞恒兴域' },
-  { key: 'scrd', label: '四川瑞都' },
-  { key: 'sxty', label: '陕西瑞鹰' },
-  { key: 'eys', label: '俄油服' },
-  { key: 'rqny', label: '瑞气能源' },
-  { key: 'rljs', label: '瑞霖技术' },
-  { key: 'bjhq', label: '北京总部' }
-]
+const reportList = ref<QhseMonthReportItem[]>([])
 
 const metricRows: ReportMetricRow[] = [
-  { category: '人工时与里程', label: '员工人数', field: 'employee', unit: '人' },
-  { category: '人工时与里程', label: '分包商人数', field: 'subcontractors', unit: '人' },
   {
-    category: '人工时与里程',
-    label: '安全行驶里程数(公里)',
+    category: '\u4eba\u5de5\u65f6\u548c\u5b89\u5168\u884c\u9a76\u516c\u91cc\u6570',
+    label: '\u5458\u5de5\u4eba\u6570',
+    field: 'employee',
+    unit: '\u4eba'
+  },
+  {
+    category: '\u4eba\u5de5\u65f6\u548c\u5b89\u5168\u884c\u9a76\u516c\u91cc\u6570',
+    label: '\u5206\u5305\u5546\u4eba\u6570',
+    field: 'subcontractors',
+    unit: '\u4eba'
+  },
+  {
+    category: '\u4eba\u5de5\u65f6\u548c\u5b89\u5168\u884c\u9a76\u516c\u91cc\u6570',
+    label: '\u5b89\u5168\u884c\u9a76\u91cc\u7a0b\u6570\uff08\u516c\u91cc\uff09',
     field: 'drivingMileage',
-    unit: '公里'
+    unit: '\u516c\u91cc'
+  },
+  {
+    category: '\u4eba\u5de5\u65f6\u548c\u5b89\u5168\u884c\u9a76\u516c\u91cc\u6570',
+    label: '\u603b\u4eba\u5de5\u65f6\u6570\uff08\u5c0f\u65f6\uff09',
+    field: 'totalManHours',
+    unit: '\u5c0f\u65f6'
+  },
+  {
+    category: 'QHSE\u88ab\u52a8\u6027\u6307\u6807\u7edf\u8ba1',
+    label: '\u65e0\u4e8b\u6545\u7d2f\u8ba1\u5929\u6570',
+    field: 'withoutAccident',
+    unit: '\u5929'
+  },
+  { category: 'QHSE\u88ab\u52a8\u6027\u6307\u6807\u7edf\u8ba1', label: '\u6b7b\u4ea1\u4e8b\u6545\uff08\u8d77\uff09', field: 'fatality', unit: '\u8d77' },
+  {
+    category: 'QHSE\u88ab\u52a8\u6027\u6307\u6807\u7edf\u8ba1',
+    label: '\u635f\u5931\u5de5\u65f6\u4e8b\u6545\uff08\u8d77\uff09',
+    field: 'injury',
+    unit: '\u8d77'
+  },
+  {
+    category: 'QHSE\u88ab\u52a8\u6027\u6307\u6807\u7edf\u8ba1',
+    label: '\u5de5\u4f5c\u53d7\u9650\u4e8b\u4ef6\uff08\u8d77\uff09',
+    field: 'restrictedCase',
+    unit: '\u8d77'
+  },
+  {
+    category: 'QHSE\u88ab\u52a8\u6027\u6307\u6807\u7edf\u8ba1',
+    label: '\u533b\u7597\u5904\u7406\u4e8b\u4ef6\uff08\u8d77\uff09',
+    field: 'medicalCase',
+    unit: '\u8d77'
+  },
+  {
+    category: 'QHSE\u88ab\u52a8\u6027\u6307\u6807\u7edf\u8ba1',
+    label: '\u6025\u6551\u7bb1\u4e8b\u4ef6\uff08\u8d77\uff09',
+    field: 'firstAidCase',
+    unit: '\u8d77'
+  },
+  {
+    category: 'QHSE\u88ab\u52a8\u6027\u6307\u6807\u7edf\u8ba1',
+    label: '\u4ea4\u901a\u4e8b\u6545\uff08\u8d77\uff09',
+    field: 'vehicleAccident',
+    unit: '\u8d77'
+  },
+  {
+    category: 'QHSE\u88ab\u52a8\u6027\u6307\u6807\u7edf\u8ba1',
+    label: '\u672a\u9042\u4e8b\u4ef6\uff08\u8d77\uff09',
+    field: 'nearMiss',
+    unit: '\u8d77'
+  },
+  {
+    category: 'QHSE\u88ab\u52a8\u6027\u6307\u6807\u7edf\u8ba1',
+    label: '\u6cc4\u6f0f\u4e8b\u4ef6\uff08\u8d77\uff09',
+    field: 'spill',
+    unit: '\u8d77'
+  },
+  {
+    category: 'QHSE\u88ab\u52a8\u6027\u6307\u6807\u7edf\u8ba1',
+    label: '\u8fdd\u53cd\u4fdd\u547d\u89c4\u5219\u7684\u6b21\u6570\uff08\u6b21\uff09',
+    field: 'lifeSavingRules',
+    unit: '\u6b21'
+  },
+  { category: 'QHSE\u4e3b\u52a8\u6027\u6307\u6807\u7edf\u8ba1', label: '\u73ed\u524d\u4f1a\uff08\u6b21\uff09', field: 'toolboxTalk', unit: '\u6b21' },
+  {
+    category: 'QHSE\u4e3b\u52a8\u6027\u6307\u6807\u7edf\u8ba1',
+    label: 'QHSE\u7ba1\u7406\u59d4\u5458\u4f1a\u4f1a\u8bae\uff08\u6b21\uff09',
+    field: 'committeeMeeting',
+    unit: '\u6b21'
+  },
+  {
+    category: 'QHSE\u4e3b\u52a8\u6027\u6307\u6807\u7edf\u8ba1',
+    label: 'QHSE\u6708\u5ea6\u4f8b\u4f1a\uff08\u6b21\uff09',
+    field: 'monthlyMeeting',
+    unit: '\u6b21'
+  },
+  {
+    category: 'QHSE\u4e3b\u52a8\u6027\u6307\u6807\u7edf\u8ba1',
+    label: '\u516c\u53f8\u7ea7\u9690\u60a3\u6392\u67e5\uff08\u6b21\uff09',
+    field: 'companyHazard',
+    unit: '\u6b21'
+  },
+  { category: 'QHSE\u4e3b\u52a8\u6027\u6307\u6807\u7edf\u8ba1', label: 'QHSE\u68c0\u67e5\uff08\u6b21\uff09', field: 'qhseInspection', unit: '\u6b21' },
+  {
+    category: 'QHSE\u4e3b\u52a8\u6027\u6307\u6807\u7edf\u8ba1',
+    label: '\u5b89\u5168\u89c2\u5bdf\u5361\uff08\u5f20\uff09',
+    field: 'socCards',
+    unit: '\u5f20'
+  },
+  {
+    category: 'QHSE\u4e3b\u52a8\u6027\u6307\u6807\u7edf\u8ba1',
+    label: '\u5de5\u4f5c\u8bb8\u53ef\u5ba1\u6838\uff08\u4efd\uff09',
+    field: 'ptwAudit',
+    unit: '\u4efd'
+  },
+  {
+    category: 'QHSE\u4e3b\u52a8\u6027\u6307\u6807\u7edf\u8ba1',
+    label: '\u5de5\u4f5c\u5b89\u5168\u5206\u6790\uff08\u6b21\uff09',
+    field: 'jsa',
+    unit: '\u6b21'
   },
-  { category: '人工时与里程', label: '总人工时数(小时)', field: 'totalManHours', unit: '小时' },
-  { category: '被动性指标', label: '无事故累计天数(天)', field: 'withoutAccident', unit: '天' },
-  { category: '被动性指标', label: '死亡事故(起)', field: 'fatality', unit: '起' },
-  { category: '被动性指标', label: '损失工时事故(起)', field: 'injury', unit: '起' },
-  { category: '被动性指标', label: '工作受限事件(起)', field: 'restrictedCase', unit: '起' },
-  { category: '被动性指标', label: '医疗处理事件(起)', field: 'medicalCase', unit: '起' },
-  { category: '被动性指标', label: '急救箱事件(起)', field: 'firstAidCase', unit: '起' },
-  { category: '被动性指标', label: '交通事故(起)', field: 'vehicleAccident', unit: '起' },
-  { category: '被动性指标', label: '未遂事件(起)', field: 'nearMiss', unit: '起' },
-  { category: '被动性指标', label: '泄漏事件(起)', field: 'spill', unit: '起' },
-  { category: '被动性指标', label: '违反保命规则的次数(次)', field: 'lifeSavingRules', unit: '次' },
-  { category: '主动性指标', label: '班前会(次)', field: 'toolboxTalk', unit: '次' },
-  { category: '主动性指标', label: 'QHSE管理委员会会议', field: 'committeeMeeting', unit: '次' },
-  { category: '主动性指标', label: 'QHSE月度例会', field: 'monthlyMeeting', unit: '次' },
-  { category: '主动性指标', label: '公司级隐患排查', field: 'companyHazard', unit: '次' },
-  { category: '主动性指标', label: 'QHSE检查', field: 'qhseInspection', unit: '次' },
-  { category: '主动性指标', label: '安全观察卡', field: 'socCards', unit: '张' },
-  { category: '主动性指标', label: '工作许可审核', field: 'ptwAudit', unit: '份' },
-  { category: '主动性指标', label: '工作安全分析', field: 'jsa', unit: '次' },
-  { category: '主动性指标', label: '演练次数', field: 'drills', unit: '次' },
-  { category: '主动性指标', label: 'QHSE培训次数', field: 'training', unit: '次' },
-  { category: '主动性指标', label: 'QHSE培训人次', field: 'participantsTraining', unit: '人次' },
-  { category: '主动性指标', label: 'QHSE培训学时数', field: 'trainingsHours', unit: '小时' },
-  { category: '环境数据', label: '水消耗', field: 'waterConsumption', unit: '吨' },
-  { category: '环境数据', label: '柴油消耗', field: 'dieselConsumption', unit: '升' },
-  { category: '环境数据', label: '用电量', field: 'electricityConsumption', unit: '千瓦·小时' },
-  { category: '环境数据', label: '天然气消耗量', field: 'naturalGasConsumption', unit: '立方米' },
-  { category: '其他信息', label: '备注', field: 'remark', unit: '/' }
+  { category: 'QHSE\u4e3b\u52a8\u6027\u6307\u6807\u7edf\u8ba1', label: '\u6f14\u7ec3\u6b21\u6570', field: 'drills', unit: '\u6b21' },
+  { category: 'QHSE\u4e3b\u52a8\u6027\u6307\u6807\u7edf\u8ba1', label: 'QHSE\u57f9\u8bad\u6b21\u6570', field: 'training', unit: '\u6b21' },
+  { category: 'QHSE\u4e3b\u52a8\u6027\u6307\u6807\u7edf\u8ba1', label: 'QHSE\u57f9\u8bad\u4eba\u6b21', field: 'participantsTraining', unit: '\u4eba\u6b21' },
+  {
+    category: 'QHSE\u4e3b\u52a8\u6027\u6307\u6807\u7edf\u8ba1',
+    label: 'QHSE\u57f9\u8bad\u5b66\u65f6\u6570\uff08\u5c0f\u65f6\uff09',
+    field: 'trainingsHours',
+    unit: '\u5c0f\u65f6'
+  },
+  { category: '\u73af\u5883\u6570\u636e', label: '\u6c34\u6d88\u8017\uff08\u5428\uff09', field: 'waterConsumption', unit: '\u5428' },
+  { category: '\u73af\u5883\u6570\u636e', label: '\u67f4\u6cb9\u6d88\u8017\uff08\u5347\uff09', field: 'dieselConsumption', unit: '\u5347' },
+  {
+    category: '\u73af\u5883\u6570\u636e',
+    label: '\u7528\u7535\u91cf\uff08\u5343\u74e6\u65f6\uff09',
+    field: 'electricityConsumption',
+    unit: '\u5343\u74e6\u65f6'
+  },
+  {
+    category: '\u73af\u5883\u6570\u636e',
+    label: '\u5929\u7136\u6c14\u6d88\u8017\u91cf\uff08\u7acb\u65b9\u7c73\uff09',
+    field: 'naturalGasConsumption',
+    unit: '\u7acb\u65b9\u7c73'
+  },
+  { category: '\u5176\u4ed6\u4fe1\u606f', label: '\u5907\u6ce8', field: 'remark', unit: '/' }
 ]
 
-const categoryRowSpanMap = computed(() => {
-  return metricRows.reduce<Record<string, number>>((acc, item) => {
+const companyColumns = computed<ReportCompanyColumn[]>(() =>
+  reportList.value.map((item, index) => ({
+    key: getCompanyKey(index),
+    label: item.deptName || `Company ${index + 1}`
+  }))
+)
+
+const companyRowMap = computed<Record<string, QhseMonthReportItem>>(() =>
+  Object.fromEntries(reportList.value.map((item, index) => [getCompanyKey(index), item]))
+)
+
+const categoryRowSpanMap = computed(() =>
+  metricRows.reduce<Record<string, number>>((acc, item) => {
     acc[item.category] = (acc[item.category] || 0) + 1
     return acc
   }, {})
-})
+)
 
-const firstRowIndexByCategory = computed(() => {
-  return metricRows.reduce<Record<string, number>>((acc, item, index) => {
+const firstRowIndexByCategory = computed(() =>
+  metricRows.reduce<Record<string, number>>((acc, item, index) => {
     if (acc[item.category] === undefined) acc[item.category] = index
     return acc
   }, {})
-})
-
-const mockMetricValueMap = computed<Record<string, Record<string, ReportMetricValue>>>(() => ({
-  employee: { rhxy: 32, scrd: 28, sxty: 25, eys: 18, rqny: 20, rljs: 14, bjhq: 12 },
-  subcontractors: { rhxy: 15, scrd: 12, sxty: 9, eys: 7, rqny: 6, rljs: 5, bjhq: 0 },
-  drivingMileage: {
-    rhxy: 12680.5,
-    scrd: 11024.2,
-    sxty: 9480.8,
-    eys: 6855.6,
-    rqny: 7742.4,
-    rljs: 4136.5,
-    bjhq: 980.2
-  },
-  totalManHours: {
-    rhxy: 3824,
-    scrd: 3416,
-    sxty: 2988,
-    eys: 2210,
-    rqny: 2456,
-    rljs: 1768,
-    bjhq: 960
-  },
-  withoutAccident: { rhxy: 186, scrd: 186, sxty: 186, eys: 132, rqny: 186, rljs: 186, bjhq: 186 },
-  fatality: { rhxy: 0, scrd: 0, sxty: 0, eys: 0, rqny: 0, rljs: 0, bjhq: 0 },
-  injury: { rhxy: 0, scrd: 1, sxty: 0, eys: 0, rqny: 0, rljs: 0, bjhq: 0 },
-  restrictedCase: { rhxy: 1, scrd: 0, sxty: 0, eys: 0, rqny: 1, rljs: 0, bjhq: 0 },
-  medicalCase: { rhxy: 1, scrd: 1, sxty: 0, eys: 0, rqny: 0, rljs: 0, bjhq: 0 },
-  firstAidCase: { rhxy: 2, scrd: 1, sxty: 1, eys: 0, rqny: 1, rljs: 0, bjhq: 0 },
-  vehicleAccident: { rhxy: 0, scrd: 0, sxty: 0, eys: 1, rqny: 0, rljs: 0, bjhq: 0 },
-  nearMiss: { rhxy: 3, scrd: 2, sxty: 1, eys: 1, rqny: 2, rljs: 1, bjhq: 0 },
-  spill: { rhxy: 0, scrd: 0, sxty: 0, eys: 0, rqny: 1, rljs: 0, bjhq: 0 },
-  lifeSavingRules: { rhxy: 0, scrd: 1, sxty: 0, eys: 0, rqny: 0, rljs: 0, bjhq: 0 },
-  toolboxTalk: { rhxy: 28, scrd: 24, sxty: 22, eys: 18, rqny: 20, rljs: 16, bjhq: 6 },
-  committeeMeeting: { rhxy: 1, scrd: 1, sxty: 1, eys: 1, rqny: 1, rljs: 1, bjhq: 1 },
-  monthlyMeeting: { rhxy: 1, scrd: 1, sxty: 1, eys: 1, rqny: 1, rljs: 1, bjhq: 1 },
-  companyHazard: { rhxy: 6, scrd: 5, sxty: 4, eys: 3, rqny: 4, rljs: 2, bjhq: 1 },
-  qhseInspection: { rhxy: 10, scrd: 9, sxty: 8, eys: 6, rqny: 7, rljs: 5, bjhq: 3 },
-  socCards: { rhxy: 42, scrd: 38, sxty: 31, eys: 22, rqny: 27, rljs: 18, bjhq: 12 },
-  ptwAudit: { rhxy: 18, scrd: 15, sxty: 13, eys: 8, rqny: 9, rljs: 6, bjhq: 2 },
-  jsa: { rhxy: 21, scrd: 18, sxty: 16, eys: 10, rqny: 12, rljs: 8, bjhq: 3 },
-  drills: { rhxy: 2, scrd: 2, sxty: 1, eys: 1, rqny: 1, rljs: 1, bjhq: 1 },
-  training: { rhxy: 5, scrd: 4, sxty: 4, eys: 3, rqny: 3, rljs: 2, bjhq: 2 },
-  participantsTraining: { rhxy: 96, scrd: 82, sxty: 74, eys: 48, rqny: 56, rljs: 35, bjhq: 24 },
-  trainingsHours: { rhxy: 64, scrd: 56, sxty: 48, eys: 32, rqny: 36, rljs: 24, bjhq: 16 },
-  waterConsumption: {
-    rhxy: 82.5,
-    scrd: 74.2,
-    sxty: 65.8,
-    eys: 48.6,
-    rqny: 53.4,
-    rljs: 31.8,
-    bjhq: 12.2
-  },
-  dieselConsumption: {
-    rhxy: 2680,
-    scrd: 2410,
-    sxty: 2085,
-    eys: 1530,
-    rqny: 1695,
-    rljs: 980,
-    bjhq: 220
-  },
-  electricityConsumption: {
-    rhxy: 4250,
-    scrd: 3980,
-    sxty: 3650,
-    eys: 2420,
-    rqny: 2860,
-    rljs: 1680,
-    bjhq: 920
-  },
-  naturalGasConsumption: {
-    rhxy: 1260,
-    scrd: 1140,
-    sxty: 980,
-    eys: 660,
-    rqny: 720,
-    rljs: 450,
-    bjhq: 180
-  },
-  remark: {
-    rhxy: '现场管理平稳',
-    scrd: '专项培训已完成',
-    sxty: '持续推进隐患整改',
-    eys: '强化车辆安全检查',
-    rqny: '开展环保专项复盘',
-    rljs: '重点盯控作业许可',
-    bjhq: '推进体系宣贯'
-  }
-}))
+)
 
-const tableRows = computed<TableRow[]>(() => {
-  return metricRows.map((row) => {
+const tableRows = computed<TableRow[]>(() =>
+  metricRows.map((row) => {
     const companyValues = Object.fromEntries(
-      companyColumns.map((company) => [company.key, getMetricCompanyValue(row.field, company.key)])
+      companyColumns.value.map((company) => [company.key, getMetricCompanyValue(row.field, company.key)])
     )
 
     return {
@@ -195,7 +210,7 @@ const tableRows = computed<TableRow[]>(() => {
       ...companyValues
     }
   })
-})
+)
 
 async function loadDetail() {
   loading.value = true
@@ -203,8 +218,7 @@ async function loadDetail() {
     const res = await QhseMonthReportSummaryApi.getQhseMonthReportSummary({
       yearMonths: props.yearMonths
     })
-
-    report.value = ((res as any)?.data ?? res ?? {}) as QhseMonthReportItem
+    reportList.value = ((res as any)?.data?.list ?? (res as any)?.list ?? []) as QhseMonthReportItem[]
   } finally {
     loading.value = false
   }
@@ -212,39 +226,45 @@ async function loadDetail() {
 
 function handleVisibleChange(visible: boolean) {
   emits('update:visible', visible)
-  if (!visible) report.value = undefined
+  if (!visible) reportList.value = []
+}
+
+function getCompanyKey(index: number) {
+  return `company_${index}`
 }
 
-function formatDisplayValue(field: keyof QhseMonthReportItem) {
-  const value = report.value?.[field]
+function formatMetricValue(value: QhseMonthReportItem[keyof QhseMonthReportItem]) {
   if (value === undefined || value === null || value === '') return '-'
-  if (field === 'createTime') {
-    const date = dayjs(value)
-    return date.isValid() ? date.format('YYYY-MM-DD') : String(value)
+  const numericValue = Number(value)
+  if (!Number.isNaN(numericValue) && String(value).trim() !== '') {
+    return Number.isInteger(numericValue) ? String(numericValue) : numericValue.toFixed(2)
   }
   return String(value)
 }
 
 function getMetricCompanyValue(field: keyof QhseMonthReportItem, companyKey: string) {
-  const rowData = mockMetricValueMap.value[String(field)] || {}
-  const value = rowData[companyKey]
-  if (value === undefined || value === null || value === '') return '-'
-  if (typeof value === 'number' && !Number.isInteger(value)) return value.toFixed(2)
-  return String(value)
+  const rowData = companyRowMap.value[companyKey]
+  return formatMetricValue(rowData?.[field])
 }
 
 function getMetricSummaryValue(field: keyof QhseMonthReportItem) {
-  const rowData = mockMetricValueMap.value[String(field)] || {}
-  const values = companyColumns
-    .map((company) => rowData[company.key])
+  const values = reportList.value
+    .map((item) => item[field])
     .filter((value) => value !== undefined && value !== null && value !== '')
 
   if (!values.length) return '-'
-  if (values.every((value) => typeof value === 'number')) {
-    const total = values.reduce((sum, value) => sum + Number(value), 0)
+
+  if (field === 'remark') {
+    return values.map((value) => String(value)).join('; ')
+  }
+
+  const numericValues = values.map((value) => Number(value))
+  if (numericValues.every((value) => !Number.isNaN(value))) {
+    const total = numericValues.reduce((sum, value) => sum + value, 0)
     return Number.isInteger(total) ? String(total) : total.toFixed(2)
   }
-  return values.map((value) => String(value)).join(';')
+
+  return values.map((value) => String(value)).join('; ')
 }
 
 function tableSpanMethod({
@@ -262,9 +282,21 @@ function tableSpanMethod({
   return { rowspan: categoryRowSpanMap.value[row.category], colspan: 1 }
 }
 
+const previewMeta = computed(() => {
+  const firstItem = reportList.value[0]
+  if (!firstItem) return { personName: '-', createTime: '-' }
+
+  const date = dayjs(firstItem.createTime)
+  return {
+    personName: firstItem.personName || '-',
+    createTime: date.isValid() ? date.format('YYYY-MM-DD') : '-'
+  }
+})
+
 watch(
   () => [props.visible, props.yearMonths] as const,
-  async ([visible, yearMonths], [previousVisible, previousYearMonths]) => {
+  async ([visible, yearMonths], previous = [false, undefined] as const) => {
+    const [previousVisible, previousYearMonths] = previous
     if (!visible || !yearMonths) return
     if (visible === previousVisible && yearMonths === previousYearMonths) return
     await loadDetail()
@@ -285,9 +317,9 @@ watch(
       <div class="qhse-report-preview__sheet">
         <div class="qhse-report-preview__sheet-title">QHSE 月度报告</div>
         <div class="qhse-report-preview__meta">
-          <span>年月:{{ props.yearMonths }}</span>
-          <!-- <span>填报人:{{ formatDisplayValue('personName') }}</span>
-          <span>创建日期:{{ formatDisplayValue('createTime') }}</span> -->
+          <span>年月:{{ props.yearMonths || '-' }}</span>
+          <span>填报人:{{ previewMeta.personName }}</span>
+          <span>创建日期:{{ previewMeta.createTime }}</span>
         </div>
 
         <div class="qhse-report-preview__table-wrap">
@@ -300,11 +332,11 @@ watch(
             class="qhse-report-preview__el-table">
             <el-table-column
               prop="category"
-              label="基本信息"
+              label="分组"
               fixed="left"
-              width="140"
+              width="170"
               align="center" />
-            <el-table-column prop="label" label="单位" fixed="left" width="220" align="center" />
+            <el-table-column prop="label" label="指标名称" fixed="left" width="240" align="center" />
             <el-table-column
               v-for="company in companyColumns"
               :key="company.key"