xiongxing пре 1 дан
родитељ
комит
7f135e3523
2 измењених фајлова са 118 додато и 159 уклоњено
  1. 18 1
      src/api/elderly/nursing/index.ts
  2. 100 158
      src/views/elderly/nursing/safety-check-log/index.vue

+ 18 - 1
src/api/elderly/nursing/index.ts

@@ -397,4 +397,21 @@ export const exportElderlyItemsRoundExcel = (params: Recordable) => {
     url: 'elderly-items-round/exportExcel',
     params
   })
-}
+}
+
+// =================安全检查日志================
+/** 安全检查日志(长者维度分页) */
+export const getElderlySafeCheckElderPage = (params: Recordable) => {
+  return request.get({
+    url: '/elderly-safe-check/page',
+    params
+  })
+}
+
+/** 安全检查日志记录分页(详情弹窗列表) */
+export const getElderlySafeCheckRecordPage = (params: Recordable) => {
+  return request.get({
+    url: '/elderly-safe-check/page-record',
+    params
+  })
+}

+ 100 - 158
src/views/elderly/nursing/safety-check-log/index.vue

@@ -13,6 +13,18 @@
       <el-form-item label="长者名称" prop="elderName">
         <TgInput @keyup.enter="handleQuery" v-model="queryParams.elderName" class="!w-160px" />
       </el-form-item>
+      <el-form-item label="检查日期" prop="checkDate">
+        <el-date-picker
+          v-model="queryParams.checkDate"
+          type="daterange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          value-format="YYYY-MM-DD"
+          clearable
+          class="!w-280px"
+        />
+      </el-form-item>
       <el-form-item>
         <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
         <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
@@ -25,9 +37,6 @@
       <template #pre="{ scope }">
         <el-button link type="primary" @click="openDetail(scope)">查看</el-button>
       </template>
-      <template #lastCheckTime="{ scope }">
-        {{ formatBackendDateTime(scope.row.lastCheckTime, 'YYYY-MM-DD HH:mm') || '-' }}
-      </template>
     </Table2>
 
     <Pagination
@@ -79,28 +88,22 @@
             <template #default="scope">
               <div class="expand-wrap">
                 <div class="expand-title">安全检查明细</div>
-                <el-descriptions :column="2" border size="small" class="mb-10px">
-                  <el-descriptions-item label="检查时间">
-                    {{ formatBackendDateTime(scope.row.checkTime, 'YYYY-MM-DD HH:mm') || '-' }}
-                  </el-descriptions-item>
-                  <el-descriptions-item label="提交时间">
-                    {{ formatBackendDateTime(scope.row.submitAt, 'YYYY-MM-DD HH:mm') || '-' }}
+                <el-descriptions :column="4" border size="small" class="mb-10px" label-width="130px">
+                  <el-descriptions-item label="被检查人签字">
+                    {{ scope.row.beCheckSign || '-' }}
                   </el-descriptions-item>
                   <el-descriptions-item label="长者自带电器设备">
-                    {{ scope.row.elderDevices || '-' }}
-                  </el-descriptions-item>
-                  <el-descriptions-item label="被检查人签字">
-                    {{ scope.row.checkedSign || '-' }}
+                    {{ scope.row.elderSelfEquipment || '-' }}
                   </el-descriptions-item>
-                  <el-descriptions-item label="存在问题及整改要求" :span="2">
-                    {{ scope.row.rectification || '-' }}
+                  <el-descriptions-item label="存在问题及整改要求">
+                    {{ scope.row.safeRemark || '-' }}
                   </el-descriptions-item>
-                  <el-descriptions-item label="其他" :span="2">
+                  <el-descriptions-item label="其他">
                     {{ scope.row.other || '-' }}
                   </el-descriptions-item>
                 </el-descriptions>
 
-                <el-table :data="scope.row.checklist || []" size="small" class="inner-table">
+                <el-table :data="scope.row.items || []" size="small" class="inner-table">
                   <el-table-column label="检查项" prop="label" min-width="220" show-overflow-tooltip />
                   <el-table-column label="结果" prop="status" width="96" align="center">
                     <template #default="s">
@@ -109,7 +112,6 @@
                       <span v-else>-</span>
                     </template>
                   </el-table-column>
-                  <el-table-column label="问题说明/整改要求" prop="remark" min-width="220" show-overflow-tooltip />
                 </el-table>
               </div>
             </template>
@@ -121,7 +123,7 @@
             </template>
           </el-table-column>
 
-          <el-table-column label="状态" prop="overallStatus" width="96" align="center">
+          <el-table-column label="状态" prop="overallStatus" align="center">
             <template #default="scope">
               <el-tag v-if="Number(scope.row.overallStatus) === 1" type="success" size="small">正常</el-tag>
               <el-tag v-else-if="Number(scope.row.overallStatus) === 0" type="danger" size="small">异常</el-tag>
@@ -129,12 +131,13 @@
             </template>
           </el-table-column>
 
-          <el-table-column label="异常项数" prop="abnormalCount" width="100" align="center" />
-          <el-table-column label="整改要求" prop="rectification" min-width="180" show-overflow-tooltip />
-          <el-table-column label="被检查人签字" prop="checkedSign" width="120" show-overflow-tooltip />
-          <el-table-column label="提交时间" prop="submitAt" min-width="160" show-overflow-tooltip>
+          <el-table-column label="异常项数" prop="failCount" align="center" />
+          <el-table-column label="记录人" prop="recorder" show-overflow-tooltip />
+          <!-- <el-table-column label="问题与要求" prop="question" min-width="180" show-overflow-tooltip /> -->
+          <el-table-column label="被检查人签字" prop="beCheckSign" show-overflow-tooltip />
+          <el-table-column label="创建时间" prop="createTime" min-width="160" show-overflow-tooltip>
             <template #default="scope">
-              {{ formatBackendDateTime(scope.row.submitAt, 'YYYY-MM-DD HH:mm') || '-' }}
+              {{ formatBackendDateTime(scope.row.createTime, 'YYYY-MM-DD HH:mm') || '-' }}
             </template>
           </el-table-column>
         </el-table>
@@ -159,6 +162,7 @@
 import { formatBackendDateTime } from '@/utils/formatTime'
 import dayjs from 'dayjs'
 import { useUserStore } from '@/store/modules/user'
+import { getElderlySafeCheckElderPage, getElderlySafeCheckRecordPage } from '@/api/elderly/nursing'
 
 defineOptions({ name: 'SafetyCheckLog' })
 
@@ -166,23 +170,6 @@ type SafetyChecklistItem = {
   key?: string
   label?: string
   status?: number | string
-  remark?: string
-}
-
-type SafetyCheckRecord = {
-  batchId?: string
-  elderId?: number | string
-  elderName?: string
-  bedName?: string
-  roomName?: string
-  checkTime?: number | string
-  other?: string
-  elderDevices?: string
-  rectification?: string
-  checkedSign?: string
-  checklist?: SafetyChecklistItem[]
-  submitBy?: string
-  submitAt?: number | string
 }
 
 type SafetyCheckElderRow = {
@@ -190,13 +177,29 @@ type SafetyCheckElderRow = {
   elderName: string
   roomName: string
   bedName: string
-  recordCount: number
-  lastCheckTime: number | string
 }
 
-type SafetyCheckDetailRow = SafetyCheckRecord & {
+type ElderlySafeCheckRespVO = {
+  id?: number | string
+  elderId?: number | string
+  elderName?: string
+  roomName?: string
+  bedName?: string
+  safeSituation?: string
+  safeRemark?: string
+  elderSelfEquipment?: string
+  question?: string
+  beCheckSign?: string
+  failCount?: number | string
+  creator?: string
+  createTime?: number | string
+}
+
+type SafetyCheckDetailRow = ElderlySafeCheckRespVO & {
+  checkTime?: number | string
+  items?: SafetyChecklistItem[]
+  other?: string
   overallStatus: 0 | 1
-  abnormalCount: number
 }
 
 const userStore = useUserStore()
@@ -205,15 +208,14 @@ const message = useMessage()
 const columns = reactive([
   { label: '长者姓名', field: 'elderName' },
   { label: '房间号', field: 'roomName' },
-  { label: '床位号', field: 'bedName' },
-  { label: '记录数', field: 'recordCount', width: 96 },
-  { label: '最近检查时间', field: 'lastCheckTime', type: 4 }
+  { label: '床位号', field: 'bedName' }
 ])
 
 const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
   elderName: '',
+  checkDate: undefined as string[] | undefined,
   tenantIds: userStore.orgTenantId
 })
 
@@ -222,75 +224,13 @@ const total = ref(0)
 const list = ref<SafetyCheckElderRow[]>([])
 const queryFormRef = ref()
 
-function safeParseJsonArray(raw: string | null): any[] {
-  if (!raw) return []
-  try {
-    const v = JSON.parse(raw)
-    return Array.isArray(v) ? v : []
-  } catch {
-    return []
-  }
-}
-
-function readAllRecords(): SafetyCheckRecord[] {
-  const fromLocal = safeParseJsonArray(localStorage.getItem('safetyCheckRecords'))
-  if (fromLocal.length) return fromLocal as SafetyCheckRecord[]
-  const fromSession = safeParseJsonArray(sessionStorage.getItem('safetyCheckRecords'))
-  return fromSession as SafetyCheckRecord[]
-}
-
-function normalizeText(v: unknown) {
-  return String(v ?? '').trim()
-}
-
-function toComparableTime(v: unknown): number {
-  if (v == null || v === '') return 0
-  if (typeof v === 'number' && Number.isFinite(v)) return v < 1e12 ? v * 1000 : v
-  const s = String(v).trim()
-  if (!s) return 0
-  if (/^\d+$/.test(s)) {
-    const n = Number(s)
-    return n < 1e12 ? n * 1000 : n
-  }
-  const d = dayjs(s)
-  return d.isValid() ? d.valueOf() : 0
-}
-
-function groupByElder(records: SafetyCheckRecord[]): SafetyCheckElderRow[] {
-  const map = new Map<number | string, SafetyCheckElderRow>()
-  for (const r of records) {
-    const elderId = (r as any)?.elderId
-    if (elderId == null || elderId === '') continue
-    const curr = map.get(elderId)
-    const elderName = normalizeText((r as any)?.elderName)
-    const roomName = normalizeText((r as any)?.roomName)
-    const bedName = normalizeText((r as any)?.bedName)
-    const checkTime = (r as any)?.checkTime ?? (r as any)?.submitAt
-    if (!curr) {
-      map.set(elderId, {
-        elderId,
-        elderName,
-        roomName,
-        bedName,
-        recordCount: 1,
-        lastCheckTime: checkTime
-      })
-      continue
-    }
-    curr.recordCount += 1
-    const prevMs = toComparableTime(curr.lastCheckTime)
-    const nextMs = toComparableTime(checkTime)
-    if (nextMs >= prevMs) curr.lastCheckTime = checkTime
-    if (!curr.elderName && elderName) curr.elderName = elderName
-    if (!curr.roomName && roomName) curr.roomName = roomName
-    if (!curr.bedName && bedName) curr.bedName = bedName
-  }
-  return Array.from(map.values()).sort((a, b) => toComparableTime(b.lastCheckTime) - toComparableTime(a.lastCheckTime))
-}
-
 function buildPageParams() {
   const p = { ...queryParams } as Recordable
   if (!p.elderName) delete p.elderName
+  const cd = p.checkDate as string[] | undefined
+  if (!Array.isArray(cd) || cd.length < 2 || !cd[0] || !cd[1]) {
+    delete p.checkDate
+  }
   return p
 }
 
@@ -307,15 +247,9 @@ const resetQuery = () => {
 const getList = async () => {
   loading.value = true
   try {
-    const p = buildPageParams()
-    const all = groupByElder(readAllRecords())
-    const keyword = normalizeText(p.elderName)
-    const filtered = keyword
-      ? all.filter((x) => normalizeText(x.elderName).includes(keyword))
-      : all
-    total.value = filtered.length
-    const start = (queryParams.pageNo - 1) * queryParams.pageSize
-    list.value = filtered.slice(start, start + queryParams.pageSize)
+    const data = await getElderlySafeCheckElderPage(buildPageParams())
+    list.value = (data?.list ?? []) as SafetyCheckElderRow[]
+    total.value = Number(data?.total ?? 0)
   } finally {
     loading.value = false
   }
@@ -335,7 +269,6 @@ const detailRecords = ref<SafetyCheckDetailRow[]>([])
 const detailPageNo = ref(1)
 const detailPageSize = ref(10)
 const detailTotal = ref(0)
-const detailAll = ref<SafetyCheckDetailRow[]>([])
 
 function createDetailDefaultDateRange(): string[] {
   const start = dayjs().startOf('month')
@@ -343,54 +276,65 @@ function createDetailDefaultDateRange(): string[] {
   return [start.format('YYYY-MM-DD'), end.format('YYYY-MM-DD')]
 }
 
-function computeOverallStatus(checklist: SafetyChecklistItem[] | undefined): { overallStatus: 0 | 1; abnormalCount: number } {
-  const list = Array.isArray(checklist) ? checklist : []
-  const abnormalCount = list.filter((x) => Number((x as any)?.status) === 0).length
-  return { overallStatus: abnormalCount > 0 ? 0 : 1, abnormalCount }
+function safeParseJson<T>(raw: unknown): T | undefined {
+  if (raw == null || raw === '') return undefined
+  if (typeof raw === 'object') return raw as T
+  const s = String(raw)
+  try {
+    return JSON.parse(s) as T
+  } catch {
+    return undefined
+  }
 }
 
-function matchesDateRange(checkTime: unknown, range: string[] | undefined): boolean {
-  if (!Array.isArray(range) || range.length < 2 || !range[0] || !range[1]) return true
-  const ms = toComparableTime(checkTime)
-  if (!ms) return false
-  const start = dayjs(range[0]).startOf('day').valueOf()
-  const end = dayjs(range[1]).endOf('day').valueOf()
-  return ms >= start && ms <= end
+function parseSafeSituation(raw: unknown): { checkTime?: number | string; items: SafetyChecklistItem[]; other?: string } {
+  const parsed = safeParseJson<any>(raw) ?? {}
+  const items = Array.isArray(parsed.items) ? (parsed.items as SafetyChecklistItem[]) : []
+  return { checkTime: parsed.checkTime, items, other: parsed.other }
 }
 
-function syncDetailPagedSlice() {
-  const all = detailAll.value
-  detailTotal.value = all.length
-  const start = (detailPageNo.value - 1) * detailPageSize.value
-  detailRecords.value = all.slice(start, start + detailPageSize.value)
+function computeOverallStatusByFailCountAndItems(failCount: unknown, items: SafetyChecklistItem[]): 0 | 1 {
+  if (failCount !== undefined && failCount !== null && failCount !== '') {
+    const n = Number(failCount)
+    if (!Number.isNaN(n)) return n > 0 ? 0 : 1
+  }
+  return items.some((x) => Number((x as any)?.status) === 0) ? 0 : 1
 }
 
 async function fetchDetailList() {
   if (detailHeader.elderId == null) return
   detailLoading.value = true
   try {
-    const all = readAllRecords()
-      .filter((r) => String((r as any)?.elderId) === String(detailHeader.elderId))
-      .filter((r) => matchesDateRange((r as any)?.checkTime ?? (r as any)?.submitAt, detailCheckDateRange.value))
-      .map((r) => {
-        const computed = computeOverallStatus((r as any)?.checklist)
-        return {
-          ...(r as any),
-          overallStatus: computed.overallStatus,
-          abnormalCount: computed.abnormalCount
-        } as SafetyCheckDetailRow
-      })
-      .sort((a, b) => toComparableTime((b as any)?.checkTime ?? (b as any)?.submitAt) - toComparableTime((a as any)?.checkTime ?? (a as any)?.submitAt))
-
-    detailAll.value = all
-    syncDetailPagedSlice()
+    const params: Recordable = {
+      tenantIds: queryParams.tenantIds,
+      elderId: detailHeader.elderId,
+      pageNo: detailPageNo.value,
+      pageSize: detailPageSize.value
+    }
+    const cd = detailCheckDateRange.value
+    if (Array.isArray(cd) && cd.length >= 2 && cd[0] && cd[1]) {
+      params.checkDate = [cd[0], cd[1]]
+    }
+    const data = await getElderlySafeCheckRecordPage(params)
+    detailTotal.value = Number(data?.total ?? 0)
+    const rawList = (data?.list ?? []) as ElderlySafeCheckRespVO[]
+    detailRecords.value = rawList.map((r) => {
+      const parsed = parseSafeSituation(r.safeSituation)
+      return {
+        ...r,
+        checkTime: parsed.checkTime,
+        items: parsed.items,
+        other: parsed.other,
+        overallStatus: computeOverallStatusByFailCountAndItems(r.failCount, parsed.items)
+      } as SafetyCheckDetailRow
+    })
   } finally {
     detailLoading.value = false
   }
 }
 
 function onDetailPagination() {
-  syncDetailPagedSlice()
+  fetchDetailList()
 }
 
 function handleDetailQuery() {
@@ -414,7 +358,6 @@ function openDetail(row: SafetyCheckElderRow) {
   detailPageNo.value = 1
   detailPageSize.value = 10
   detailCheckDateRange.value = createDetailDefaultDateRange()
-  detailAll.value = []
   detailRecords.value = []
 
   detailHeader.elderId = row.elderId
@@ -429,7 +372,6 @@ function closeDetail() {
   detailVisible.value = false
   resetDetailHeader()
   detailCheckDateRange.value = undefined
-  detailAll.value = []
   detailRecords.value = []
   detailTotal.value = 0
   detailPageNo.value = 1