Explorar o código

修改页面卡顿问题

unknown hai 1 mes
pai
achega
8c1c820217

+ 371 - 0
src/api/social-work/index.ts

@@ -362,3 +362,374 @@ export const sasPage = async (params: any) => {
 export const sasDelete = async (id: number) => {
   return await request.delete({ url: `/elderly-assess-anxiety/delete?id=${id}` })
 }
+
+
+// ==================== 消毒记录表 ====================
+
+// 消毒记录表数据接口
+export interface DisinfectFormData {
+  id?: number
+  elderId: number
+  tenantId: number
+  buildId?: number        // 楼栋ID
+  floorId?: number        // 楼层ID
+  floorName?: string      // 楼层名称
+  assessData: string      // JSON 字符串存储所有表单数据
+  assessor?: string       // 登记人(冗余字段,便于查询)
+  assessDate?: string     // 登记日期(冗余字段,便于查询)
+  createdAt?: string
+  updatedAt?: string
+}
+
+// 创建消毒记录
+export const disinfectCreate = async (data: DisinfectFormData) => {
+  return await request.post({ url: '/elderly-disinfect-record/create', data })
+}
+
+// 更新消毒记录
+export const disinfectUpdate = async (data: DisinfectFormData) => {
+  return await request.put({ url: '/elderly-disinfect-record/update', data })
+}
+
+// 根据ID获取消毒记录
+export const disinfectGetById = async (id: number) => {
+  return await request.get({ url: '/elderly-disinfect-record/get?id=' + id })
+}
+
+// 获取长者的消毒记录
+export const disinfectGetByElderId = async (elderId: number) => {
+  return await request.get({ url: '/elderly-disinfect-record/get-by-elder-id?elderId=' + elderId })
+}
+
+// 分页查询消毒记录
+export const disinfectPage = async (params: any) => {
+  return await request.get({ url: '/elderly-disinfect-record/page', params })
+}
+
+// 删除消毒记录
+export const disinfectDelete = async (id: number) => {
+  return await request.delete({ url: `/elderly-disinfect-record/delete?id=${id}` })
+}
+
+// 导出消毒记录
+export const disinfectExport = async (id: number) => {
+  return await request.download({ url: '/elderly-disinfect-record/export?id=' + id })
+}
+
+
+// ==================== 设施设备检查表 ====================
+
+// 设施设备检查表数据接口
+export interface FacilityEquipmentFormData {
+  id?: number
+  elderId: number
+  tenantId: number
+  buildId?: number        // 楼栋ID
+  floorId?: number        // 楼层ID
+  floorName?: string      // 楼层名称
+  assessData: string      // JSON 字符串存储所有表单数据
+  assessor?: string       // 检查人(冗余字段,便于查询)
+  assessDate?: string     // 检查日期(冗余字段,便于查询)
+  createdAt?: string
+  updatedAt?: string
+}
+
+// 创建设施设备检查记录
+export const facilityEquipmentCreate = async (data: FacilityEquipmentFormData) => {
+  return await request.post({ url: '/elderly-facility-equipment/create', data })
+}
+
+// 更新设施设备检查记录
+export const facilityEquipmentUpdate = async (data: FacilityEquipmentFormData) => {
+  return await request.put({ url: '/elderly-facility-equipment/update', data })
+}
+
+// 根据ID获取设施设备检查记录
+export const facilityEquipmentGetById = async (id: number) => {
+  return await request.get({ url: '/elderly-facility-equipment/get?id=' + id })
+}
+
+// 获取长者的设施设备检查记录
+export const facilityEquipmentGetByElderId = async (elderId: number) => {
+  return await request.get({ url: '/elderly-facility-equipment/get-by-elder-id?elderId=' + elderId })
+}
+
+// 分页查询设施设备检查记录
+export const facilityEquipmentPage = async (params: any) => {
+  return await request.get({ url: '/elderly-facility-equipment/page', params })
+}
+
+// 删除设施设备检查记录
+export const facilityEquipmentDelete = async (id: number) => {
+  return await request.delete({ url: `/elderly-facility-equipment/delete?id=${id}` })
+}
+
+// 导出设施设备检查记录
+export const facilityEquipmentExport = async (id: number) => {
+  return await request.download({ url: '/elderly-facility-equipment/export?id=' + id })
+}
+
+
+// ==================== 日常清洁消毒记录表 ====================
+
+// 日常清洁消毒记录表数据接口
+export interface CleaningRecordFormData {
+  id?: number
+  elderId: number
+  tenantId: number
+  buildId?: number        // 楼栋ID
+  floorId?: number        // 楼层ID
+  floorName?: string      // 楼层名称
+  assessData: string      // JSON 字符串存储所有表单数据
+  assessor?: string       // 登记人(冗余字段,便于查询)
+  assessDate?: string     // 登记日期(冗余字段,便于查询)
+  createdAt?: string
+  updatedAt?: string
+}
+
+// 创建日常清洁消毒记录
+export const cleaningRecordCreate = async (data: CleaningRecordFormData) => {
+  return await request.post({ url: '/elderly-cleaning-record/create', data })
+}
+
+// 更新日常清洁消毒记录
+export const cleaningRecordUpdate = async (data: CleaningRecordFormData) => {
+  return await request.put({ url: '/elderly-cleaning-record/update', data })
+}
+
+// 根据ID获取日常清洁消毒记录
+export const cleaningRecordGetById = async (id: number) => {
+  return await request.get({ url: '/elderly-cleaning-record/get?id=' + id })
+}
+
+// 获取长者的日常清洁消毒记录
+export const cleaningRecordGetByElderId = async (elderId: number) => {
+  return await request.get({ url: '/elderly-cleaning-record/get-by-elder-id?elderId=' + elderId })
+}
+
+// 分页查询日常清洁消毒记录
+export const cleaningRecordPage = async (params: any) => {
+  return await request.get({ url: '/elderly-cleaning-record/page', params })
+}
+
+// 删除日常清洁消毒记录
+export const cleaningRecordDelete = async (id: number) => {
+  return await request.delete({ url: `/elderly-cleaning-record/delete?id=${id}` })
+}
+
+// 导出日常清洁消毒记录
+export const cleaningRecordExport = async (id: number) => {
+  return await request.download({ url: '/elderly-cleaning-record/export?id=' + id })
+}
+
+
+// ==================== 楼宇清洁消毒记录表 ====================
+
+// 楼宇清洁消毒记录表数据接口
+export interface BuildingCleaningFormData {
+  id?: number
+  elderId: number
+  tenantId: number
+  buildId?: number        // 楼栋ID
+  floorId?: number        // 楼层ID
+  floorName?: string      // 楼层名称
+  assessData: string      // JSON 字符串存储所有表单数据
+  assessor?: string       // 登记人(冗余字段,便于查询)
+  assessDate?: string     // 登记日期(冗余字段,便于查询)
+  createdAt?: string
+  updatedAt?: string
+}
+
+// 创建楼宇清洁消毒记录
+export const buildingCleaningCreate = async (data: BuildingCleaningFormData) => {
+  return await request.post({ url: '/elderly-building-cleaning/create', data })
+}
+
+// 更新楼宇清洁消毒记录
+export const buildingCleaningUpdate = async (data: BuildingCleaningFormData) => {
+  return await request.put({ url: '/elderly-building-cleaning/update', data })
+}
+
+// 根据ID获取楼宇清洁消毒记录
+export const buildingCleaningGetById = async (id: number) => {
+  return await request.get({ url: '/elderly-building-cleaning/get?id=' + id })
+}
+
+// 获取长者的楼宇清洁消毒记录
+export const buildingCleaningGetByElderId = async (elderId: number) => {
+  return await request.get({ url: '/elderly-building-cleaning/get-by-elder-id?elderId=' + elderId })
+}
+
+// 分页查询楼宇清洁消毒记录
+export const buildingCleaningPage = async (params: any) => {
+  return await request.get({ url: '/elderly-building-cleaning/page', params })
+}
+
+// 删除楼宇清洁消毒记录
+export const buildingCleaningDelete = async (id: number) => {
+  return await request.delete({ url: `/elderly-building-cleaning/delete?id=${id}` })
+}
+
+// 导出楼宇清洁消毒记录
+export const buildingCleaningExport = async (id: number) => {
+  return await request.download({ url: '/elderly-building-cleaning/export?id=' + id })
+}
+
+
+// ==================== 纸尿裤领用登记表 ====================
+
+// 纸尿裤领用登记表数据接口
+export interface DiaperReceiveFormData {
+  id?: number
+  elderId: number
+  tenantId: number
+  buildId?: number        // 楼栋ID
+  floorId?: number        // 楼层ID
+  floorName?: string      // 楼层名称
+  assessData: string      // JSON 字符串存储所有表单数据
+  assessor?: string       // 登记人(冗余字段,便于查询)
+  assessDate?: string     // 登记日期(冗余字段,便于查询)
+  createdAt?: string
+  updatedAt?: string
+}
+
+// 创建纸尿裤领用登记记录
+export const diaperReceiveCreate = async (data: DiaperReceiveFormData) => {
+  return await request.post({ url: '/elderly-diaper-receive/create', data })
+}
+
+// 更新纸尿裤领用登记记录
+export const diaperReceiveUpdate = async (data: DiaperReceiveFormData) => {
+  return await request.put({ url: '/elderly-diaper-receive/update', data })
+}
+
+// 根据ID获取纸尿裤领用登记记录
+export const diaperReceiveGetById = async (id: number) => {
+  return await request.get({ url: '/elderly-diaper-receive/get?id=' + id })
+}
+
+// 获取长者的纸尿裤领用登记记录
+export const diaperReceiveGetByElderId = async (elderId: number) => {
+  return await request.get({ url: '/elderly-diaper-receive/get-by-elder-id?elderId=' + elderId })
+}
+
+// 分页查询纸尿裤领用登记记录
+export const diaperReceivePage = async (params: any) => {
+  return await request.get({ url: '/elderly-diaper-receive/page', params })
+}
+
+// 删除纸尿裤领用登记记录
+export const diaperReceiveDelete = async (id: number) => {
+  return await request.delete({ url: `/elderly-diaper-receive/delete?id=${id}` })
+}
+
+// 导出纸尿裤领用登记记录
+export const diaperReceiveExport = async (id: number) => {
+  return await request.download({ url: '/elderly-diaper-receive/export?id=' + id })
+}
+
+
+// ==================== 婴儿纸尿裤使用记录表 ====================
+
+// 婴儿纸尿裤使用记录表数据接口
+export interface BabyDiaperFormData {
+  id?: number
+  elderId: number
+  tenantId: number
+  buildId?: number        // 楼栋ID
+  floorId?: number        // 楼层ID
+  floorName?: string      // 楼层名称
+  assessData: string      // JSON 字符串存储所有表单数据
+  assessor?: string       // 登记人(冗余字段,便于查询)
+  assessDate?: string     // 登记日期(冗余字段,便于查询)
+  createdAt?: string
+  updatedAt?: string
+}
+
+// 创建婴儿纸尿裤使用记录
+export const babyDiaperCreate = async (data: BabyDiaperFormData) => {
+  return await request.post({ url: '/elderly-baby-diaper/create', data })
+}
+
+// 更新婴儿纸尿裤使用记录
+export const babyDiaperUpdate = async (data: BabyDiaperFormData) => {
+  return await request.put({ url: '/elderly-baby-diaper/update', data })
+}
+
+// 根据ID获取婴儿纸尿裤使用记录
+export const babyDiaperGetById = async (id: number) => {
+  return await request.get({ url: '/elderly-baby-diaper/get?id=' + id })
+}
+
+// 获取长者的婴儿纸尿裤使用记录
+export const babyDiaperGetByElderId = async (elderId: number) => {
+  return await request.get({ url: '/elderly-baby-diaper/get-by-elder-id?elderId=' + elderId })
+}
+
+// 分页查询婴儿纸尿裤使用记录
+export const babyDiaperPage = async (params: any) => {
+  return await request.get({ url: '/elderly-baby-diaper/page', params })
+}
+
+// 删除婴儿纸尿裤使用记录
+export const babyDiaperDelete = async (id: number) => {
+  return await request.delete({ url: `/elderly-baby-diaper/delete?id=${id}` })
+}
+
+// 导出婴儿纸尿裤使用记录
+export const babyDiaperExport = async (id: number) => {
+  return await request.download({ url: '/elderly-baby-diaper/export?id=' + id })
+}
+
+
+// ==================== 危险物品登记表 ====================
+
+// 危险物品登记表数据接口
+export interface DangerousGoodsFormData {
+  id?: number
+  elderId: number
+  tenantId: number
+  buildId?: number        // 楼栋ID
+  floorId?: number        // 楼层ID
+  floorName?: string      // 楼层名称
+  assessData: string      // JSON 字符串存储所有表单数据
+  assessor?: string       // 登记人(冗余字段,便于查询)
+  assessDate?: string     // 登记日期(冗余字段,便于查询)
+  createdAt?: string
+  updatedAt?: string
+}
+
+// 创建危险物品登记记录
+export const dangerousGoodsCreate = async (data: DangerousGoodsFormData) => {
+  return await request.post({ url: '/elderly-dangerous-goods/create', data })
+}
+
+// 更新危险物品登记记录
+export const dangerousGoodsUpdate = async (data: DangerousGoodsFormData) => {
+  return await request.put({ url: '/elderly-dangerous-goods/update', data })
+}
+
+// 根据ID获取危险物品登记记录
+export const dangerousGoodsGetById = async (id: number) => {
+  return await request.get({ url: '/elderly-dangerous-goods/get?id=' + id })
+}
+
+// 获取长者的危险物品登记记录
+export const dangerousGoodsGetByElderId = async (elderId: number) => {
+  return await request.get({ url: '/elderly-dangerous-goods/get-by-elder-id?elderId=' + elderId })
+}
+
+// 分页查询危险物品登记记录
+export const dangerousGoodsPage = async (params: any) => {
+  return await request.get({ url: '/elderly-dangerous-goods/page', params })
+}
+
+// 删除危险物品登记记录
+export const dangerousGoodsDelete = async (id: number) => {
+  return await request.delete({ url: `/elderly-dangerous-goods/delete?id=${id}` })
+}
+
+// 导出危险物品登记记录
+export const dangerousGoodsExport = async (id: number) => {
+  return await request.download({ url: '/elderly-dangerous-goods/export?id=' + id })
+}

+ 1 - 1
src/main.ts

@@ -51,7 +51,7 @@ import { Flex } from 'ant-design-vue'
 import 'ant-design-vue/dist/reset.css'
 import fetchPlugin from './config/axios/fetch';
 //版本号
-export const MAIN_VERSION = '4.3.4'
+export const MAIN_VERSION = '4.3.5'
 
 // 创建实例
 const setupAll = async () => {

+ 89 - 23
src/views/elderly/nursing/keep-fit/nine-prevention-measures-list/AddForm.vue

@@ -117,15 +117,14 @@
 
       <el-table-column prop="bedName" header-align="center" align="center" label="风险等级" width="130">
         <template #default="scope">
-          <el-select v-if="!isDetail" v-model="scope.row.riskLevel" placeholder="请选择">
-            <el-option
-              v-for="item in ['无风险','低风险','中风险','高风险']"
-              :key="item"
-              :label="item"
-              :value="item"
-            />
-          </el-select>
-          <el-text v-else>{{ scope.row.riskLevel || '-' }}</el-text>
+          <select v-if="!isDetail" v-model="scope.row.riskLevel" class="native-select-risk">
+            <option value="">请选择</option>
+            <option value="无风险">无风险</option>
+            <option value="低风险">低风险</option>
+            <option value="中风险">中风险</option>
+            <option value="高风险">高风险</option>
+          </select>
+          <span v-else class="risk-value">{{ scope.row.riskLevel || '-' }}</span>
         </template>
       </el-table-column>
 
@@ -145,20 +144,13 @@
               <span style="min-width: 26px; text-align: right; margin-right: 6px; color: #303133; font-size: 12px; font-weight: 600;">
                 {{ String(index + 1).padStart(2, '0') }}日:
               </span>
-              <el-select
-                v-if="!isDetail"
-                v-model="scope.row.executionStatus[index]"
-                size="small"
-                style="width: 85px"
-                :disabled="isDetail"
-                placeholder=""
-                clearable
-              >
-                <el-option label="正常" value="正常" />
-                <el-option label="请假外出" value="请假外出" />
-                <el-option label="退住" value="退住" />
-              </el-select>
-              <el-text v-else style="display: inline-block; width: 65px;">{{ scope.row.executionStatus[index] || '-' }}</el-text>
+              <select v-if="!isDetail" v-model="scope.row.executionStatus[index]" class="native-select-prevention">
+                <option value="">请选择</option>
+                <option value="正常">正常</option>
+                <option value="请假外出">请假外出</option>
+                <option value="退住">退住</option>
+              </select>
+              <span v-else class="prevention-value">{{ scope.row.executionStatus[index] || '-' }}</span>
             </div>
           </div>
         </template>
@@ -479,6 +471,80 @@ const handleClosed = () => {
     padding: 15px 0 !important;
   }
 
+  // 原生选择器样式
+  .native-select-prevention {
+    width: 85px;
+    height: 26px;
+    padding: 0 18px 0 6px;
+    font-size: 12px;
+    border: 1px solid #dcdfe6;
+    border-radius: 4px;
+    background-color: #fff;
+    text-align: center;
+    cursor: pointer;
+    appearance: none;
+    background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
+    background-repeat: no-repeat;
+    background-position: right 3px center;
+    background-size: 12px;
+
+    &:focus {
+      border-color: #409eff;
+      outline: none;
+    }
+
+    option {
+      font-size: 12px;
+    }
+  }
+
+  .prevention-value {
+    display: inline-block;
+    width: 85px;
+    height: 26px;
+    line-height: 26px;
+    font-size: 12px;
+    text-align: center;
+    color: #606266;
+  }
+
+  // 风险等级选择器样式
+  .native-select-risk {
+    width: 100px;
+    height: 28px;
+    padding: 0 20px 0 8px;
+    font-size: 12px;
+    border: 1px solid #dcdfe6;
+    border-radius: 4px;
+    background-color: #fff;
+    text-align: center;
+    cursor: pointer;
+    appearance: none;
+    background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
+    background-repeat: no-repeat;
+    background-position: right 4px center;
+    background-size: 14px;
+
+    &:focus {
+      border-color: #409eff;
+      outline: none;
+    }
+
+    option {
+      font-size: 12px;
+    }
+  }
+
+  .risk-value {
+    display: inline-block;
+    width: 100px;
+    height: 28px;
+    line-height: 28px;
+    font-size: 12px;
+    text-align: center;
+    color: #606266;
+  }
+
   .info-title {
     min-width: 75px;
     max-width: 180px;

+ 46 - 8
src/views/elderly/nursing/keep-fit/specialized-care-service-record/AddForm.vue

@@ -135,14 +135,13 @@
           <div style="display:flex;flex-direction: row;align-items: center">
             <div v-for="(item,index) in scope.row.executionStatus" :key="index" style="display:flex;flex-direction: row;align-items: center" >
               <el-tag size="large">{{item.day}}</el-tag>
-              <el-select v-model="scope.row.executionStatus[index]" placeholder="请选择"  style="width: 104px;margin-right: 8px" :disabled="isDetail">
-                <el-option
-                  v-for="itemSon in ['已完成','未完成','无']"
-                  :key="itemSon"
-                  :label="itemSon"
-                  :value="itemSon"
-                />
-              </el-select>
+              <select v-if="!isDetail" v-model="scope.row.executionStatus[index]" class="native-select-execution">
+                <option value="">请选择</option>
+                <option value="已完成">已完成</option>
+                <option value="未完成">未完成</option>
+                <option value="无">无</option>
+              </select>
+              <span v-else class="execution-value">{{ scope.row.executionStatus[index] || '-' }}</span>
             </div>
           </div>
 
@@ -413,6 +412,45 @@ const handleClosed = () => {
     padding: 15px 0 !important;
   }
 
+  // 原生选择器样式
+  .native-select-execution {
+    width: 90px;
+    height: 28px;
+    padding: 0 20px 0 8px;
+    margin-right: 8px;
+    font-size: 12px;
+    border: 1px solid #dcdfe6;
+    border-radius: 4px;
+    background-color: #fff;
+    text-align: center;
+    cursor: pointer;
+    appearance: none;
+    background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
+    background-repeat: no-repeat;
+    background-position: right 4px center;
+    background-size: 14px;
+
+    &:focus {
+      border-color: #409eff;
+      outline: none;
+    }
+
+    option {
+      font-size: 12px;
+    }
+  }
+
+  .execution-value {
+    display: inline-block;
+    width: 90px;
+    height: 28px;
+    line-height: 28px;
+    margin-right: 8px;
+    font-size: 12px;
+    text-align: center;
+    color: #606266;
+  }
+
   .info-title {
     min-width: 75px;
     max-width: 180px;

+ 1152 - 0
src/views/elderly/nursing/records/baby-diapers/AddForm.vue

@@ -0,0 +1,1152 @@
+<template>
+  <el-drawer
+    v-model="dialogVisible"
+    :title="title"
+    resizable
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    :destroy-on-close="true"
+    size="70%"
+    :before-close="handleClosed"
+  >
+
+    <div class="mmse-form">
+      <!-- 尿不湿情况 -->
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>长者姓名</text>
+          <search-the-elderly ref="selectElderRef" :disabled="isDetail" @update_elder="elderUp" v-model="dataForm.elderName" :tId="dataForm.tenantId"/>
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>档案号</text>
+          <el-input v-if="!isDetail" v-model="dataForm.contractNumber" disabled />
+          <el-text v-else disabled="">{{dataForm.contractNumber}}</el-text>
+        </el-col>
+      </el-row>
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>入院日期</text>
+          <el-input v-if="!isDetail" :model-value="dayjs(dataForm.checkInTime).format('YYYY-MM-DD')=='Invalid Date'?'':dayjs(dataForm.checkInTime).format('YYYY-MM-DD')" disabled />
+          <el-text v-else disabled="">{{dayjs(dataForm.checkInTime).format('YYYY-MM-DD')}}</el-text>
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>床位号</text>
+          <el-input v-if="!isDetail" v-model="dataForm.bedName" disabled />
+          <el-text v-else disabled="">{{dataForm.bedName}}</el-text>
+        </el-col>
+      </el-row>
+
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" class="row">
+          <text>楼栋</text>
+          <el-select :disabled="isDetail" v-model="dataForm.buildId" placeholder="选择楼栋" style="width: 100%" @change="handleBuildChange">
+            <el-option  v-for="(item,index) in buildList" :key="index" :label="item.buildName" :value="item.id" />
+          </el-select>
+
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" class="row">
+          <text>楼层</text>
+            <el-select :disabled="isDetail" v-model="dataForm.floorId" placeholder="选择楼层" style="width: 100%" @change="handleFloorChange">
+              <el-option v-for="(item,index) in floorList" :key="index" :label="item.floorName" :value="item.id" />
+            </el-select>
+
+        </el-col>
+      </el-row>
+
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>登记人</text>
+          <el-input :disabled="isDetail" v-model="form.assessor"  />
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>登记日期</text>
+          <el-date-picker :disabled="isDetail" v-model="form.assessDate" type="date" style="width: 100%;"/>
+        </el-col>
+      </el-row>
+
+      <!-- 表单内容区域 -->
+      <div class="form-body">
+        <!-- 婴儿纸尿裤使用记录表 -->
+        <div class="baby-diaper-table-wrapper">
+          <table class="baby-diaper-table">
+            <thead>
+              <tr>
+                <th rowspan="2" class="col-date">日期</th>
+                <th rowspan="2" class="col-shift">班次</th>
+                <th rowspan="2" class="col-use">使用</th>
+                <th rowspan="2" class="col-release">解除时间</th>
+                <th rowspan="2" class="col-count">更换<br/>次数</th>
+                <th colspan="3" class="col-skin">皮肤情况</th>
+                <th colspan="2" class="col-urine">尿液情况</th>
+                <th colspan="2" class="col-stool">粪便情况</th>
+                <th rowspan="2" class="col-remark">备注</th>
+                <th rowspan="2" class="col-sign">护理员<br/>签名</th>
+              </tr>
+              <tr>
+                <th class="col-obs">正常</th>
+                <th class="col-obs">潮红</th>
+                <th class="col-obs">湿疹</th>
+                <th class="col-obs">正常</th>
+                <th class="col-obs">异常</th>
+                <th class="col-obs">正常</th>
+                <th class="col-obs">异常</th>
+              </tr>
+            </thead>
+            <tbody>
+              <template v-for="day in 31" :key="day">
+                <!-- 白班 -->
+                <tr>
+                  <td :rowspan="2" class="day-cell" v-if="day === 1 || (day - 1) % 5 === 0">{{ day }}</td>
+                  <td class="shift-cell">白</td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].dayShift.used" class="native-select">
+                      <option value="">--</option>
+                      <option value="是">是</option>
+                      <option value="否">否</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].dayShift.used || '--' }}</span>
+                  </td>
+                  <td>
+                    <div v-if="!isDetail" class="release-time-cell">
+                      <select v-model="form.records[day-1].dayShift.releaseType" class="native-select release-select" @change="handleReleaseTypeChange(day-1, 'dayShift')">
+                        <option value="">--</option>
+                        <option value="未解除">未解除</option>
+                        <option value="已解除">已解除</option>
+                      </select>
+                      <el-time-picker 
+                        v-if="form.records[day-1].dayShift.releaseType === '已解除'" 
+                        v-model="form.records[day-1].dayShift.releaseTime" 
+                        format="HH:mm" 
+                        value-format="HH:mm"
+                        placeholder="时间"
+                        size="small"
+                        class="time-picker"
+                      />
+                    </div>
+                    <span v-else class="check-value">
+                      {{ form.records[day-1].dayShift.releaseType === '已解除' ? form.records[day-1].dayShift.releaseTime : (form.records[day-1].dayShift.releaseType || '--') }}
+                    </span>
+                  </td>
+                  <td>
+                    <el-input v-if="!isDetail" v-model.number="form.records[day-1].dayShift.changeCount" type="number" size="small" style="width: 50px;" />
+                    <span v-else>{{ form.records[day-1].dayShift.changeCount }}</span>
+                  </td>
+                  <!-- 皮肤情况 -->
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].dayShift.skin" class="native-select">
+                      <option value="">--</option>
+                      <option value="正常">正常</option>
+                      <option value="潮红">潮红</option>
+                      <option value="湿疹">湿疹</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].dayShift.skin || '--' }}</span>
+                  </td>
+                  <td class="obs-cell">-</td>
+                  <td class="obs-cell">-</td>
+                  <!-- 尿液情况 -->
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].dayShift.urine" class="native-select">
+                      <option value="">--</option>
+                      <option value="正常">正常</option>
+                      <option value="异常">异常</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].dayShift.urine || '--' }}</span>
+                  </td>
+                  <td class="obs-cell">-</td>
+                  <!-- 粪便情况 -->
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].dayShift.stool" class="native-select">
+                      <option value="">--</option>
+                      <option value="正常">正常</option>
+                      <option value="异常">异常</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].dayShift.stool || '--' }}</span>
+                  </td>
+                  <td class="obs-cell">-</td>
+                  <td>
+                    <el-input v-if="!isDetail" v-model="form.records[day-1].dayShift.remark" size="small" placeholder="备注" />
+                    <span v-else>{{ form.records[day-1].dayShift.remark }}</span>
+                  </td>
+                  <td>
+                    <el-input v-if="!isDetail" v-model="form.records[day-1].dayShift.nurseSign" size="small" placeholder="签名" />
+                    <span v-else>{{ form.records[day-1].dayShift.nurseSign }}</span>
+                  </td>
+                </tr>
+                <!-- 夜班 -->
+                <tr>
+                  <td class="shift-cell">夜</td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].nightShift.used" class="native-select">
+                      <option value="">--</option>
+                      <option value="是">是</option>
+                      <option value="否">否</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].nightShift.used || '--' }}</span>
+                  </td>
+                  <td>
+                    <div v-if="!isDetail" class="release-time-cell">
+                      <select v-model="form.records[day-1].nightShift.releaseType" class="native-select release-select" @change="handleReleaseTypeChange(day-1, 'nightShift')">
+                        <option value="">--</option>
+                        <option value="未解除">未解除</option>
+                        <option value="已解除">已解除</option>
+                      </select>
+                      <el-time-picker 
+                        v-if="form.records[day-1].nightShift.releaseType === '已解除'" 
+                        v-model="form.records[day-1].nightShift.releaseTime" 
+                        format="HH:mm" 
+                        value-format="HH:mm"
+                        placeholder="时间"
+                        size="small"
+                        class="time-picker"
+                      />
+                    </div>
+                    <span v-else class="check-value">
+                      {{ form.records[day-1].nightShift.releaseType === '已解除' ? form.records[day-1].nightShift.releaseTime : (form.records[day-1].nightShift.releaseType || '--') }}
+                    </span>
+                  </td>
+                  <td>
+                    <el-input v-if="!isDetail" v-model.number="form.records[day-1].nightShift.changeCount" type="number" size="small" style="width: 50px;" />
+                    <span v-else>{{ form.records[day-1].nightShift.changeCount }}</span>
+                  </td>
+                  <!-- 皮肤情况 -->
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].nightShift.skin" class="native-select">
+                      <option value="">--</option>
+                      <option value="正常">正常</option>
+                      <option value="潮红">潮红</option>
+                      <option value="湿疹">湿疹</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].nightShift.skin || '--' }}</span>
+                  </td>
+                  <td class="obs-cell">-</td>
+                  <td class="obs-cell">-</td>
+                  <!-- 尿液情况 -->
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].nightShift.urine" class="native-select">
+                      <option value="">--</option>
+                      <option value="正常">正常</option>
+                      <option value="异常">异常</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].nightShift.urine || '--' }}</span>
+                  </td>
+                  <td class="obs-cell">-</td>
+                  <!-- 粪便情况 -->
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].nightShift.stool" class="native-select">
+                      <option value="">--</option>
+                      <option value="正常">正常</option>
+                      <option value="异常">异常</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].nightShift.stool || '--' }}</span>
+                  </td>
+                  <td class="obs-cell">-</td>
+                  <td>
+                    <el-input v-if="!isDetail" v-model="form.records[day-1].nightShift.remark" size="small" placeholder="备注" />
+                    <span v-else>{{ form.records[day-1].nightShift.remark }}</span>
+                  </td>
+                  <td>
+                    <el-input v-if="!isDetail" v-model="form.records[day-1].nightShift.nurseSign" size="small" placeholder="签名" />
+                    <span v-else>{{ form.records[day-1].nightShift.nurseSign }}</span>
+                  </td>
+                </tr>
+              </template>
+            </tbody>
+          </table>
+        </div>
+
+        <!-- 备注说明 -->
+        <div class="note-section">
+          <div class="note-title">备注说明</div>
+          <div class="note-content">
+            <p>1、用24小时制。</p>
+            <p>2、异常情况在"备注"栏说明并跟踪情况。</p>
+            <p>3、各责任班记录一次,没解除用"/"表示。</p>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div>前端提交的数据,后端可以参照这个格式:
+      {
+      "buildId": 190,
+      "floorId": 644,
+      "floorName": "2层",
+      "contractNumber": "111",
+      "elderName": "0318",
+      "bedName": "测试楼-2层-201-10",
+      "elderAge": 86,
+      "elderSex": "男",
+      "elderId": 18697,
+      "tenantId": 195,
+      "buildName": "测试楼",
+      "assessData": " ",
+      "assessor": "啊啊啊",
+      "assessDate": "2026-03-27",
+      "orgType": 1
+      }
+    </div>
+
+
+
+    <template #footer>
+      <el-button @click="handleClosed">关闭</el-button>
+      <el-button style="margin-left: 22px;margin-right: 30px" v-loading="formLoading" type="primary" v-show="!isDetail" @click="submitForm">确定</el-button>
+      <el-button v-if="isDetail" type="success" @click="handleExport">打印</el-button>
+    </template>
+
+  </el-drawer>
+</template>
+
+<script lang="ts" setup>
+import { computed, ref } from 'vue'
+
+import dayjs from 'dayjs'
+
+import { babyDiaperCreate, babyDiaperGetById, babyDiaperUpdate } from "@/api/social-work";
+import {getBuildList} from "@/api/system/badManage";
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+const title = ref('')
+const dialogVisible = ref(false) // 弹窗
+const formRef = ref() // 表单 Ref
+const selectElderRef = ref() // 表单 Ref
+const isDetail = ref(false) // 是否详情打开
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+let dataForm = ref({
+  // 表单字段
+  id: undefined,
+  idCard: '',
+  buildId: '',
+  floorId: '',
+  floorName: '',
+  contractNumber: '', //档案号
+  elderName: '',//长者姓名
+  bedName: '', //床位号
+  elderAge: '', //年龄
+  elderSex: '', //性别
+  checkInTime: '', //入院日期
+  elderId: '',
+  tenantId: undefined
+})
+
+
+const buildList = ref([])
+const floorList = ref([])
+const handleBuildChange = (buildId: any) => {
+  const selectedBuild = buildList.value.find((item: any) => item.id === buildId)
+  if (selectedBuild) {
+    dataForm.value.buildName = selectedBuild.buildName
+    floorList.value = selectedBuild.floorList || []
+    // 清空楼层选择
+    dataForm.value.floorId = ''
+    dataForm.value.floorName = ''
+  }
+}
+const handleFloorChange = (floorId: any) => {
+  const selectedFloor = floorList.value.find((item: any) => item.id === floorId)
+  if (selectedFloor) {
+    dataForm.value.floorName = selectedFloor.floorName
+  }
+}
+
+const elderUp = (e) => {
+  dataForm.value.elderName = e.elderName
+  dataForm.value.elderId = e.id
+  dataForm.value.elderSex = e.elderSex === 1 ? '男' : '女'
+  dataForm.value.bedName = e.bedName || ''
+  dataForm.value.checkInTime = e.checkInTime
+  dataForm.value.contractNumber = e.contractNumber
+  dataForm.value.elderAge = e.elderAge
+}
+
+// ========== 感知觉与沟通评估表 表单序列化方法 ==========
+
+// 危险物品登记不需要计算总分,保留计算属性占位
+const totalScore = computed(() => {
+  return 0
+})
+
+
+/** 将表单数据序列化为 JSON 对象 */
+const serializeFormData = () => {
+  return {
+    // 基本信息
+    assessor: form.assessor || '',
+    assessDate: form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : '',
+
+    // 31天婴儿纸尿裤使用记录
+    records: form.records || []
+  }
+}
+
+/** 将 JSON 对象反序列化为表单数据 */
+const deserializeFormData = (formData: Record<string, any>) => {
+  if (!formData) return
+
+  // 基本信息
+  form.assessor = formData.assessor || ''
+  form.assessDate = formData.assessDate ? dayjs(formData.assessDate).toDate() : ''
+
+  // 31天婴儿纸尿裤使用记录
+  if (formData.records && formData.records.length > 0) {
+    form.records = formData.records
+  } else {
+    form.records = generate31DaysRecords()
+  }
+}
+
+/** 重置婴儿纸尿裤使用记录表表单数据 */
+const resetPerceptionForm = () => {
+  form.assessor = ''
+  form.assessDate = ''
+
+  // 重置31天婴儿纸尿裤使用记录
+  form.records = generate31DaysRecords()
+}
+
+/** 打开弹窗 */
+const open = async (tenantId, id?: any, detail: boolean = false) => {
+  resetForm()
+  dialogVisible.value = true
+  dataForm.value.id = id || undefined
+  dataForm.value.tenantId = tenantId
+  isDetail.value = detail
+  try {
+    buildList.value = await getBuildList({tenantIds: tenantId})
+  }catch (e) {}
+
+  if (id) {
+    title.value = "编辑-婴儿纸尿裤使用记录"
+    // 加载登记数据
+    await loadDangerousGoodsData(id)
+  } else {
+    title.value = "新增-婴儿纸尿裤使用记录"
+
+  }
+}
+
+/** 加载登记数据 */
+const loadDangerousGoodsData = async (id: number) => {
+  try {
+    const res = await babyDiaperGetById(id)
+    if (res) {
+      // 填充长者基本信息
+      dataForm.value.elderName = res.elderName || ''
+      dataForm.value.elderId = res.elderId || ''
+      dataForm.value.elderSex = res.elderSex || ''
+      dataForm.value.bedName = res.bedName || ''
+      dataForm.value.checkInTime = res.checkInTime || ''
+      dataForm.value.contractNumber = res.fileNumber || ''
+      dataForm.value.elderAge = res.elderAge || ''
+      await selectElderRef.value.upData(res.elderName, res.elderId)
+      // 解析 assessData
+      if (res.assessData) {
+        const formData = JSON.parse(res.assessData)
+        deserializeFormData(formData)
+      }
+    }
+  } catch (error) {
+    message.error('加载婴儿纸尿裤使用记录数据失败')
+  }
+}
+
+
+
+// 生成31天的记录数据结构(每天白班+夜班)
+const generate31DaysRecords = () => {
+  return Array.from({ length: 31 }, () => ({
+    dayShift: {
+      used: '',           // 使用(是/否)
+      releaseType: '',    // 解除类型(未解除/已解除)
+      releaseTime: '',    // 解除时间
+      changeCount: 0,     // 更换次数
+      skin: '',           // 皮肤情况(正常/潮红/湿疹)
+      urine: '',          // 尿液情况(正常/异常)
+      stool: '',          // 粪便情况(正常/异常)
+      remark: '',         // 备注
+      nurseSign: ''       // 护理员签名
+    },
+    nightShift: {
+      used: '',
+      releaseType: '',
+      releaseTime: '',
+      changeCount: 0,
+      skin: '',
+      urine: '',
+      stool: '',
+      remark: '',
+      nurseSign: ''
+    }
+  }))
+}
+
+// 处理解除类型变化
+const handleReleaseTypeChange = (dayIndex: number, shift: 'dayShift' | 'nightShift') => {
+  if (form.records[dayIndex][shift].releaseType !== '已解除') {
+    form.records[dayIndex][shift].releaseTime = ''
+  }
+}
+
+const form = reactive({
+  // 基本信息
+  assessor: '',
+  assessDate: '',
+
+  // 31天婴儿纸尿裤使用记录
+  records: generate31DaysRecords()
+})
+
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  if (formLoading.value) {
+    return
+  }
+  formLoading.value = true
+  // 提交请求
+    try {
+      const assessData = serializeFormData()
+      const tempParams = {
+        ...dataForm.value,
+        assessData: JSON.stringify(assessData),
+        assessor: form.assessor,
+        assessDate: form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : ''
+      }
+
+    if (dataForm.value.id) {
+      const res = await babyDiaperUpdate(tempParams)
+      if (res) {
+        message.success(t('common.updateSuccess'))
+        dialogVisible.value = false
+        // 发送操作成功的事件
+        emit('success')
+      }
+    } else {
+      const res = await babyDiaperCreate(tempParams)
+      if (res) {
+        message.success(t('common.createSuccess'))
+        dialogVisible.value = false
+        // 发送操作成功的事件
+        emit('success')
+      }
+    }
+  } finally {
+    setTimeout(() => {
+      formLoading.value = false
+    }, 500)
+  }
+}
+
+
+
+/** 重置表单 */
+const resetForm = () => {
+  dataForm.value = {
+    id: undefined,
+    idCard: '',
+    buildId: '',
+    floorId: '',
+    floorName: '',
+    contractNumber: '', //档案号
+    elderName: '',//长者姓名
+    bedName: '', //床位号
+    elderAge: '', //年龄
+    elderSex: '', //性别
+    checkInTime: '', //入院日期
+    elderId: '',
+    tenantId: undefined
+  }
+  formRef.value?.resetFields()
+
+  // 重置感知觉与沟通评估表表单
+  resetPerceptionForm()
+}
+
+// 关闭表单
+const handleClosed = () => {
+  dialogVisible.value = false
+  resetForm()
+}
+
+
+
+</script>
+
+<style scoped lang="scss">
+.mmse-form {
+  max-width: 1200px;
+  margin: 0 auto;
+  background: #fff;
+
+  .form-title {
+    text-align: center;
+    font-size: 24px;
+    font-weight: bold;
+    margin-bottom: 20px;
+  }
+
+
+
+  .info-row {
+    display: flex;
+    gap: 40px;
+    width: 100%;
+    flex-direction: row;
+    align-items: center;
+    margin-bottom: 10px;
+
+    .info-item {
+      display: flex;
+      align-items: center;
+      gap: 8px;
+
+      .label {
+        width: 82px;
+        text-align: right;
+        margin-right: 4px;
+        white-space: nowrap;
+      }
+    }
+  }
+
+
+  .form-body {
+    border: 1px solid #333;
+    padding: 15px;
+
+    .baby-diaper-table-wrapper {
+      overflow-x: auto;
+      margin-bottom: 20px;
+
+      .baby-diaper-table {
+        min-width: 1400px;
+        border-collapse: collapse;
+        border: 1px solid #333;
+
+        th, td {
+          border: 1px solid #333;
+          padding: 4px 2px;
+          text-align: center;
+          vertical-align: middle;
+        }
+
+        th {
+          background: #f5f7fa;
+          font-weight: bold;
+          font-size: 11px;
+        }
+
+        .col-date {
+          width: 40px;
+          min-width: 40px;
+        }
+
+        .col-shift {
+          width: 30px;
+          min-width: 30px;
+        }
+
+        .col-use {
+          width: 50px;
+          min-width: 50px;
+        }
+
+        .col-release {
+          width: 120px;
+          min-width: 120px;
+        }
+
+        .col-count {
+          width: 45px;
+          min-width: 45px;
+        }
+
+        .col-skin, .col-urine, .col-stool {
+          background: #e8f4f8;
+        }
+
+        .col-obs {
+          width: 40px;
+          min-width: 40px;
+          font-size: 10px;
+        }
+
+        .col-remark {
+          width: 80px;
+          min-width: 80px;
+        }
+
+        .col-sign {
+          width: 70px;
+          min-width: 70px;
+        }
+
+        .day-cell {
+          font-weight: bold;
+          background: #f5f7fa;
+        }
+
+        .shift-cell {
+          font-weight: bold;
+          background: #fafafa;
+        }
+
+        .obs-cell {
+          background: #f0f0f0;
+          color: #ccc;
+        }
+
+        tbody {
+          tr {
+            height: 36px;
+          }
+
+          td {
+            .native-select {
+              width: 100%;
+              height: 26px;
+              padding: 0 14px 0 2px;
+              font-size: 11px;
+              border: 1px solid #dcdfe6;
+              border-radius: 3px;
+              background-color: #fff;
+              text-align: center;
+              cursor: pointer;
+              appearance: none;
+              background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
+              background-repeat: no-repeat;
+              background-position: right 2px center;
+              background-size: 12px;
+
+              &:focus {
+                border-color: #409eff;
+                outline: none;
+              }
+
+              option {
+                font-size: 12px;
+              }
+            }
+
+            .release-select {
+              width: 70px;
+            }
+
+            .release-time-cell {
+              display: flex;
+              align-items: center;
+              gap: 4px;
+
+              .time-picker {
+                width: 90px;
+              }
+            }
+
+            .check-value {
+              font-size: 11px;
+              display: inline-block;
+              min-width: 20px;
+            }
+          }
+        }
+      }
+    }
+
+    .dangerous-goods-table {
+      margin-bottom: 20px;
+
+      .goods-table {
+        width: 100%;
+        border-collapse: collapse;
+        border: 1px solid #333;
+
+        th, td {
+          border: 1px solid #333;
+          padding: 10px 8px;
+          text-align: center;
+          vertical-align: middle;
+        }
+
+        th {
+          background: #f5f7fa;
+          font-weight: bold;
+          font-size: 14px;
+        }
+
+        .col-no {
+          width: 50px;
+        }
+
+        .col-bed {
+          width: 80px;
+        }
+
+        .col-name {
+          width: 80px;
+        }
+
+        .col-goods-title {
+          background: #f5f7fa;
+          font-weight: bold;
+        }
+
+        .col-goods {
+          width: 100px;
+        }
+
+        .col-storage {
+          width: 120px;
+        }
+
+        .col-sign {
+          width: 120px;
+        }
+
+        .col-remark {
+          width: 150px;
+        }
+
+        tbody {
+          td {
+            .el-input {
+              width: 100%;
+            }
+
+            .el-textarea {
+              width: 100%;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  .section {
+    margin-bottom: 20px;
+
+    &:last-child {
+      margin-bottom: 0;
+    }
+
+    .section-title {
+      font-weight: bold;
+      margin-bottom: 10px;
+    }
+  }
+
+  .form-item {
+    display: flex;
+    align-items: center;
+    margin-bottom: 12px;
+    flex-wrap: wrap;
+    gap: 8px;
+
+    .item-number {
+      font-weight: bold;
+      min-width: 25px;
+    }
+
+    .item-label {
+      white-space: nowrap;
+      min-width: fit-content;
+    }
+
+  }
+
+  .other-input {
+    width: 200px;
+    margin-left: 10px;
+  }
+
+  // 调整 Element Plus 组件样式
+  :deep(.el-input__inner) {
+    height: 28px;
+    line-height: 28px;
+    border-top: none;
+    border-left: none;
+    border-right: none;
+    border-radius: 0;
+    padding: 0 4px;
+
+    &:focus {
+      border-color: #409eff;
+    }
+  }
+
+
+  :deep(.el-checkbox__label),
+  :deep(.el-radio__label) {
+    padding-left: 4px;
+  }
+}
+.row{
+  margin-bottom: 12px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  text{
+    text-align: right;
+    margin-right: 4px;
+    width: 82px;
+  }
+}
+
+// 感知觉与沟通评估表 特有样式
+.total-score-section {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  margin-bottom: 20px;
+
+  .total-score {
+    display: flex;
+    align-items: baseline;
+    gap: 4px;
+
+    .score-label {
+      font-size: 16px;
+      font-weight: bold;
+    }
+
+    .score-value {
+      font-size: 28px;
+      font-weight: bold;
+      color: #409eff;
+    }
+
+    .score-max {
+      font-size: 14px;
+      color: #909399;
+    }
+  }
+
+  .risk-level {
+    font-size: 16px;
+    font-weight: bold;
+    padding: 8px 16px;
+    border-radius: 4px;
+
+    &.risk-none {
+      color: #67c23a;
+      background: #f0f9eb;
+    }
+
+    &.risk-low {
+      color: #e6a23c;
+      background: #fdf6ec;
+    }
+
+    &.risk-medium {
+      color: #f56c6c;
+      background: #fef0f0;
+    }
+
+    &.risk-high {
+      color: #f56c6c;
+      background: #fef0f0;
+      border: 1px solid #f56c6c;
+    }
+  }
+}
+
+.assessment-table {
+  width: 100%;
+  border-collapse: collapse;
+  margin-bottom: 20px;
+
+  table {
+    width: 100%;
+    border: 1px solid #333;
+
+    th, td {
+      border: 1px solid #333;
+      padding: 12px;
+      text-align: left;
+    }
+
+    th {
+      background: #f5f7fa;
+      font-weight: bold;
+      text-align: center;
+    }
+
+    .criteria-col {
+      width: 60%;
+    }
+
+    .score-col {
+      width: 15%;
+      text-align: center;
+    }
+
+    .select-col {
+      width: 25%;
+      text-align: center;
+    }
+
+    .criteria {
+      text-align: left;
+    }
+
+    .score {
+      text-align: center;
+      font-weight: bold;
+    }
+
+    .select {
+      text-align: center;
+
+      :deep(.el-radio) {
+        margin-right: 0;
+      }
+    }
+  }
+}
+
+.remark-section {
+  margin: 15px 0;
+  padding: 12px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .remark-label {
+    font-weight: bold;
+    color: #606266;
+  }
+
+  .remark-text {
+    color: #606266;
+  }
+}
+
+.risk-judgment-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .risk-judgment-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .risk-options {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20px;
+
+    :deep(.el-radio) {
+      margin-right: 0;
+    }
+  }
+}
+
+.preventive-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .preventive-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .preventive-options {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 15px;
+
+    :deep(.el-checkbox) {
+      margin-right: 20px;
+      margin-bottom: 8px;
+    }
+
+    .other-input {
+      width: 200px;
+      margin-left: 10px;
+    }
+  }
+}
+
+.signature-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .signature-row {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    gap: 20px;
+  }
+
+  .signature-item {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+
+    &.date-item {
+      :deep(.el-date-picker) {
+        width: 150px;
+      }
+    }
+  }
+
+  .signature-label {
+    font-weight: bold;
+    white-space: nowrap;
+  }
+
+  .signature-input {
+    width: 150px;
+  }
+
+  .date-picker {
+    width: 150px;
+  }
+}
+
+.note-section {
+  margin-top: 20px;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .note-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .note-content {
+    font-size: 13px;
+    line-height: 1.8;
+    color: #606266;
+
+    p {
+      margin: 5px 0;
+    }
+
+    .indent {
+      margin-left: 20px;
+    }
+  }
+}
+</style>

+ 390 - 0
src/views/elderly/nursing/records/baby-diapers/index.vue

@@ -0,0 +1,390 @@
+<template>
+  <ContentWrap>
+    <!-- 工单记录 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="110px"
+    >
+      <el-form-item label="长者姓名">
+        <el-input
+          v-model="queryParams.elderName"
+          placeholder="长者姓名"
+          class="!w-240px"
+          clearable
+        />
+      </el-form-item>
+
+      <el-form-item label="楼栋">
+        <el-select v-model="queryParams.buidId" placeholder="选择楼栋" style="width: 180px" @change="handleBuildChange">
+          <el-option v-for="(item,index) in buildList" :key="index" :label="item.buildName" :value="item.id" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="楼层">
+        <el-select  v-model="queryParams.floorId" placeholder="选择楼层" style="width: 180px" >
+          <el-option v-for="(item,index) in floorList" :key="index" :label="item.floorName" :value="item.id" />
+        </el-select>
+      </el-form-item>
+
+
+      <el-form-item label="登记日期">
+        <el-date-picker
+          size="default"
+          ref="selectRef"
+          class="!w-240px"
+          v-model="queryParams.discoveryTime"
+          type="daterange"
+          :clearable="true"
+          :editable="false"
+          placeholder="选择工单日期"
+          value-format="YYYY-MM-DD"
+          format="YYYY-MM-DD"
+          date-format="YYYY-MM-DD"
+        />
+      </el-form-item>
+
+      <el-form-item>
+        <el-button @click="handleQuery" style="margin-left: 2vw"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <div class="mb-10px">
+
+      <ButtonAdd @click="openForm(undefined)"  />
+      <el-button @click="inputH" type="success"><Icon icon="fa:cloud-upload" :size="16" class="mr-1"/>导入</el-button>
+      <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">
+        <template #default="scope">
+          {{
+            scope.$index + (queryParams.pageNo * queryParams.pageSize - queryParams.pageSize) + 1
+          }}
+        </template>
+      </el-table-column>
+
+
+      <el-table-column prop="elderName" header-align="center" align="center" label="长者姓名" min-width="120" show-overflow-tooltip/>
+      <el-table-column prop="elderSex" header-align="center" align="center" label="性别" min-width="90" show-overflow-tooltip/>
+      <el-table-column prop="elderAge" header-align="center" align="center" label="年龄" min-width="90" show-overflow-tooltip/>
+      <el-table-column prop="serviceItem" header-align="center" align="center" label="服务项目" min-width="200" show-overflow-tooltip/>
+      <el-table-column prop="serviceName" header-align="center" align="center" label="服务人员姓名" min-width="160" show-overflow-tooltip/>
+      <el-table-column prop="orderTime" header-align="center" align="center" label="订单时间" min-width="180" show-overflow-tooltip>
+        <template #default="scope">
+          {{(formatToDateTime(scope.row.orderTime))}}
+        </template>
+      </el-table-column>
+      <el-table-column prop="comeTime" header-align="center" align="center" label="上门时间" min-width="180" show-overflow-tooltip>
+        <template #default="scope">
+          {{formatToDateTime(scope.row.serviceBeginTime)}}
+        </template>
+      </el-table-column>
+      <el-table-column prop="elderAddress" header-align="center" align="center" label="地址" min-width="220" show-overflow-tooltip/>
+      <el-table-column prop="isExpire" header-align="center" align="center" label="是否过期" min-width="120" show-overflow-tooltip/>
+      <el-table-column prop="orderStatus" header-align="center" align="center" label="订单状态" min-width="160" show-overflow-tooltip/>
+
+      <el-table-column label="操作" align="center" width="200" fixed="right">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openFormEdit(scope.row, scope.row.id)"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="warning"
+            @click="openFormDetail(scope.row.id)"
+          >
+            详情
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="openClose(scope.row)"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </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"
+  />
+
+
+  <Import
+    ref="importRef"
+    @success="getList"
+    :config="{
+      title: '导入',
+      downloadUrl: 'elderly-service-order/get-import-template',
+      excelTempName: '居家工单-【导入】模板',
+      importUrl: '/elderly-service-order/import',
+      failExportUrl: '',
+    }"
+  />
+
+</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 {
+  careRecordsPage, elderlyServiceOrderDelete, elderlyServiceOrderPage,
+} from "@/api/member/appointment";
+import download from "@/utils/download";
+import { useUserStore } from '@/store/modules/user'
+import {formatToDate, formatToDateTime, getCurrentMonthRange} from "@/utils/dateUtil";
+import * as UserApi from "@/api/system/user";
+import Import from "@/components/ImportFile/index.vue";
+import {ref} from "vue";
+import {getBuildList} from "@/api/system/badManage";
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+const userStore = useUserStore()
+const loading = ref(true) // 列表的加载中
+const detailRef = ref()
+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,
+  elderName: '',
+  elderPhone: '',
+  discoveryTime: ["2025-12-01",formatToDate()],
+  tenantIds: userStore.orgTenantId[0]
+})
+const queryFormRef = ref() // 搜索的表单
+
+const inputH = () => {
+  importRef.value.open(queryParams.tenantIds[0])
+}
+// 打开导出弹窗
+const handleImportCard = async () => {
+  try {
+    const queryParams = reactive({
+      pageNo: 1,
+      pageSize: 1000,
+      tenantIds: userStore.orgTenantId,
+    })
+    const data = await UserApi.exportElderlyServiceOrder(queryParams)
+    download.excel(data, '工单报表数据.xls')
+  }catch (e) {
+
+  }
+
+
+  // exportConfig.value = {
+  //   title: "批量导出",
+  //   batchMin: 1,
+  //   batchMax: 999,
+  //   countMin: 1,
+  //   countMax: 500,
+  //   defaultBatch: 1,
+  //   defaultCount: 500,
+  //   description: [
+  //     '1. 请输入需要导出的数量',
+  //     '2. 一次导不完的话,输入批次 2 再次导出,以此类推。',
+  //     '3. 建议单次导出数量不超过500,以免影响系统性能',
+  //     '4. 导出需要较长时间,请耐心等待。'
+  //   ]
+  // }
+  // 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 (_) {}
+
+}
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    //let queryP = {...queryParams,discoveryTime:queryParams.discoveryTime?[queryParams.discoveryTime[0]+" 00:00:00",queryParams.discoveryTime[1]+" 23:59:59"]:null}
+    const data = await elderlyServiceOrderPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = async () => {
+  if (!queryFormRef.value) return
+  const valid = await queryFormRef.value.validate()
+  if (!valid) return
+  queryParams.pageNo = 1
+  await getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryParams.elderName = ''
+  queryParams.tenantId = userStore.orgTenantId[0]
+  queryParams.discoveryTime= ["2025-12-01",formatToDate()]
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (id?: number) => {
+  // if(queryParams.tenantIds.length == 0 || queryParams.tenantIds.length > 1){
+  //   message.error('新增只能选择一个机构')
+  //   return
+  // }
+  formRef.value.open(queryParams.tenantIds, id,false)
+}
+
+const editRef = ref()
+const openFormEdit = (row: any = {}, id?: number) => {
+  formRef.value.open(row.tenantId, id,false)
+}
+
+
+const openFormDetail = (id?: number) => {
+  formRef.value.open(undefined,id,true)
+}
+
+
+
+
+
+const openClose = async (item) => {
+  try {
+    console.log("任务ID",item)
+    const res = await message.confirm('确定要删除吗?', '提示')
+    if (res == 'confirm') {
+      // 发起
+      try {
+        const res = await elderlyServiceOrderDelete(item.id)
+        if (res){
+          message.success(t('common.updateSuccess'))
+        }
+      }catch(err) {}
+    }
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 取消按钮操作 */
+const cancelDelete = async (id: number) => {
+  try {
+    // 取消的二次确认
+    await message.cancelConfirm()
+    // 发起取消
+    // await elderlyBakDel(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+
+const buildList = ref([])
+const floorList = ref([])
+
+const route = useRoute()
+/** 初始化 **/
+onMounted(async () => {
+  if(route.query && route.query.elderName){
+    queryParams.elderName = route.query.elderName as string
+  }
+  getList()
+  try {
+    buildList.value = await getBuildList({tenantIds: queryParams.tenantId})
+  }catch (e) {}
+})
+
+// 表头格式
+const tableHeaderColor = ({ rowIndex }: any) => {
+  if (rowIndex === 0) {
+    return {
+      backgroundColor: '#f8f8f9',
+      color: '#666666',
+      fontWeight: 'bold'
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss"></style>

+ 1349 - 0
src/views/elderly/nursing/records/build-dustman/AddForm.vue

@@ -0,0 +1,1349 @@
+<template>
+  <el-drawer
+    v-model="dialogVisible"
+    :title="title"
+    resizable
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    :destroy-on-close="true"
+    size="85%"
+    :before-close="handleClosed"
+  >
+
+    <div class="mmse-form">
+      <!-- 楼层清洁 -->
+
+
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" class="row">
+          <text>楼栋</text>
+          <el-select :disabled="isDetail" v-model="dataForm.buildId" placeholder="选择楼栋" style="width: 100%" @change="handleBuildChange">
+            <el-option  v-for="(item,index) in buildList" :key="index" :label="item.buildName" :value="item.id" />
+          </el-select>
+
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" class="row">
+          <text>楼层</text>
+            <el-select :disabled="isDetail" v-model="dataForm.floorId" placeholder="选择楼层" style="width: 100%" @change="handleFloorChange">
+              <el-option v-for="(item,index) in floorList" :key="index" :label="item.floorName" :value="item.id" />
+            </el-select>
+
+        </el-col>
+      </el-row>
+
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>登记人</text>
+          <el-input :disabled="isDetail" v-model="form.assessor"  />
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>登记月份</text>
+          <el-date-picker :disabled="isDetail" v-model="form.assessDate" type="month" style="width: 100%;"/>
+        </el-col>
+      </el-row>
+
+      <!-- 表单内容区域 -->
+      <div class="form-body">
+        <!-- 楼宇清洁消毒记录表 -->
+        <div class="building-cleaning-table-wrapper">
+          <table class="building-cleaning-table">
+            <thead>
+              <!-- 日期行 -->
+              <tr>
+                <th colspan="2" rowspan="2" class="col-area-header">区域/日期</th>
+                <th v-for="day in 31" :key="'day-'+day" colspan="3" class="col-day-header">{{ day }}</th>
+              </tr>
+              <!-- 时段行 -->
+              <tr>
+                <template v-for="day in 31" :key="'time-'+day">
+                  <th class="col-time">早</th>
+                  <th class="col-time">中</th>
+                  <th class="col-time">晚</th>
+                </template>
+              </tr>
+            </thead>
+            <tbody>
+              <!-- 护理站 -->
+              <tr>
+                <td rowspan="3" class="area-name">护理站</td>
+                <td class="item-name">台面电话</td>
+                <template v-for="day in 31" :key="'nurse1-'+day">
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].nurseStation.phone.morning" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].nurseStation.phone.morning || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].nurseStation.phone.noon" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].nurseStation.phone.noon || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].nurseStation.phone.evening" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].nurseStation.phone.evening || '--' }}</span>
+                  </td>
+                </template>
+              </tr>
+              <tr>
+                <td class="item-name">桌子</td>
+                <template v-for="day in 31" :key="'nurse2-'+day">
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].nurseStation.table.morning" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].nurseStation.table.morning || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].nurseStation.table.noon" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].nurseStation.table.noon || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].nurseStation.table.evening" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].nurseStation.table.evening || '--' }}</span>
+                  </td>
+                </template>
+              </tr>
+              <tr>
+                <td class="item-name">椅子</td>
+                <template v-for="day in 31" :key="'nurse3-'+day">
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].nurseStation.chair.morning" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].nurseStation.chair.morning || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].nurseStation.chair.noon" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].nurseStation.chair.noon || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].nurseStation.chair.evening" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].nurseStation.chair.evening || '--' }}</span>
+                  </td>
+                </template>
+              </tr>
+
+              <!-- 长者房间 -->
+              <tr>
+                <td rowspan="4" class="area-name">长者房间<br/>(含氯250mg/L)</td>
+                <td class="item-name">床头柜</td>
+                <template v-for="day in 31" :key="'room1-'+day">
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].elderRoom.bedsideTable.morning" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].elderRoom.bedsideTable.morning || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].elderRoom.bedsideTable.noon" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].elderRoom.bedsideTable.noon || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].elderRoom.bedsideTable.evening" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].elderRoom.bedsideTable.evening || '--' }}</span>
+                  </td>
+                </template>
+              </tr>
+              <tr>
+                <td class="item-name">床围栏</td>
+                <template v-for="day in 31" :key="'room2-'+day">
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].elderRoom.bedRail.morning" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].elderRoom.bedRail.morning || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].elderRoom.bedRail.noon" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].elderRoom.bedRail.noon || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].elderRoom.bedRail.evening" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].elderRoom.bedRail.evening || '--' }}</span>
+                  </td>
+                </template>
+              </tr>
+              <tr>
+                <td class="item-name">开关按钮</td>
+                <template v-for="day in 31" :key="'room3-'+day">
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].elderRoom.switchBtn.morning" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].elderRoom.switchBtn.morning || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].elderRoom.switchBtn.noon" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].elderRoom.switchBtn.noon || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].elderRoom.switchBtn.evening" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].elderRoom.switchBtn.evening || '--' }}</span>
+                  </td>
+                </template>
+              </tr>
+              <tr>
+                <td class="item-name">门把手</td>
+                <template v-for="day in 31" :key="'room4-'+day">
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].elderRoom.doorHandle.morning" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].elderRoom.doorHandle.morning || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].elderRoom.doorHandle.noon" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].elderRoom.doorHandle.noon || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].elderRoom.doorHandle.evening" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].elderRoom.doorHandle.evening || '--' }}</span>
+                  </td>
+                </template>
+              </tr>
+
+              <!-- 居室 -->
+              <tr>
+                <td rowspan="3" class="area-name">居室<br/>(含氯250mg/L)</td>
+                <td class="item-name">地面</td>
+                <template v-for="day in 31" :key="'living1-'+day">
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].livingRoom.floor.morning" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].livingRoom.floor.morning || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].livingRoom.floor.noon" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].livingRoom.floor.noon || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].livingRoom.floor.evening" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].livingRoom.floor.evening || '--' }}</span>
+                  </td>
+                </template>
+              </tr>
+              <tr>
+                <td class="item-name">窗台</td>
+                <template v-for="day in 31" :key="'living2-'+day">
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].livingRoom.windowsill.morning" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].livingRoom.windowsill.morning || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].livingRoom.windowsill.noon" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].livingRoom.windowsill.noon || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].livingRoom.windowsill.evening" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].livingRoom.windowsill.evening || '--' }}</span>
+                  </td>
+                </template>
+              </tr>
+              <tr>
+                <td class="item-name">走廊扶手</td>
+                <template v-for="day in 31" :key="'living3-'+day">
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].livingRoom.handrail.morning" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].livingRoom.handrail.morning || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].livingRoom.handrail.noon" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].livingRoom.handrail.noon || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].livingRoom.handrail.evening" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].livingRoom.handrail.evening || '--' }}</span>
+                  </td>
+                </template>
+              </tr>
+
+              <!-- 卫生间 -->
+              <tr>
+                <td rowspan="2" class="area-name">卫生间<br/>(含氯500mg/L)</td>
+                <td class="item-name">水龙头</td>
+                <template v-for="day in 31" :key="'toilet1-'+day">
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].toilet.faucet.morning" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].toilet.faucet.morning || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].toilet.faucet.noon" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].toilet.faucet.noon || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].toilet.faucet.evening" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].toilet.faucet.evening || '--' }}</span>
+                  </td>
+                </template>
+              </tr>
+              <tr>
+                <td class="item-name">马桶</td>
+                <template v-for="day in 31" :key="'toilet2-'+day">
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].toilet.toilet.morning" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].toilet.toilet.morning || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].toilet.toilet.noon" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].toilet.toilet.noon || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].toilet.toilet.evening" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].toilet.toilet.evening || '--' }}</span>
+                  </td>
+                </template>
+              </tr>
+
+              <!-- 开水间 -->
+              <tr>
+                <td class="area-name">开水间<br/>(含氯500mg/L)</td>
+                <td class="item-name">-</td>
+                <template v-for="day in 31" :key="'water-'+day">
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].waterRoom.morning" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].waterRoom.morning || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].waterRoom.noon" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].waterRoom.noon || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].waterRoom.evening" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].waterRoom.evening || '--' }}</span>
+                  </td>
+                </template>
+              </tr>
+
+              <!-- 垃圾存放处 -->
+              <tr>
+                <td class="area-name">垃圾存放处<br/>(含氯500mg/L)</td>
+                <td class="item-name">-</td>
+                <template v-for="day in 31" :key="'garbage-'+day">
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].garbage.morning" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].garbage.morning || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].garbage.noon" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].garbage.noon || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].garbage.evening" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].garbage.evening || '--' }}</span>
+                  </td>
+                </template>
+              </tr>
+
+              <!-- 开窗通风 -->
+              <tr>
+                <td class="area-name">开窗通风</td>
+                <td class="item-name">-</td>
+                <template v-for="day in 31" :key="'vent-'+day">
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].ventilation.morning" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].ventilation.morning || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].ventilation.noon" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].ventilation.noon || '--' }}</span>
+                  </td>
+                  <td>
+                    <select v-if="!isDetail" v-model="form.records[day-1].ventilation.evening" class="native-select">
+                      <option value="">--</option>
+                      <option value="已完成">已完成</option>
+                    </select>
+                    <span v-else class="check-value">{{ form.records[day-1].ventilation.evening || '--' }}</span>
+                  </td>
+                </template>
+              </tr>
+
+              <!-- 执行签名 -->
+              <tr>
+                <td class="area-name">执行签名</td>
+                <td class="item-name">-</td>
+                <template v-for="day in 31" :key="'sign-'+day">
+                  <td colspan="3">
+                    <el-input v-if="!isDetail" v-model="form.records[day-1].signature" size="small" placeholder="签名" />
+                    <span v-else>{{ form.records[day-1].signature }}</span>
+                  </td>
+                </template>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+
+        <!-- 备注说明 -->
+        <div class="note-section">
+          <div class="note-title">备注说明</div>
+          <div class="note-content">
+            <p>1、护理站、长者房间、居室区域均予250mg/L含氯消毒液擦拭消毒;</p>
+            <p>2、卫生间、开水间、垃圾存放处均予500mg/L含氯消毒液擦拭消毒。</p>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div>前端提交的数据,后端可以参照这个格式:
+      {
+      "buildId": 190,
+      "floorId": 644,
+      "floorName": "2层",
+      "elderName": "0318",
+      "bedName": "测试楼-2层-201-10",
+      "tenantId": 195,
+      "buildName": "测试楼",
+      "assessData": " ",
+      "assessor": "啊啊啊",
+      "assessDate": "2026-03-27",
+      "orgType": 1
+      }
+    </div>
+
+
+
+    <template #footer>
+      <el-button @click="handleClosed">关闭</el-button>
+      <el-button style="margin-left: 22px;margin-right: 30px" v-loading="formLoading" type="primary" v-show="!isDetail" @click="submitForm">确定</el-button>
+      <el-button v-if="isDetail" type="success" @click="handleExport">打印</el-button>
+    </template>
+
+  </el-drawer>
+</template>
+
+<script lang="ts" setup>
+import { computed, ref } from 'vue'
+
+import dayjs from 'dayjs'
+
+import { buildingCleaningCreate, buildingCleaningGetById, buildingCleaningUpdate } from "@/api/social-work";
+import {getBuildList} from "@/api/system/badManage";
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+const title = ref('')
+const dialogVisible = ref(false) // 弹窗
+const formRef = ref() // 表单 Ref
+const selectElderRef = ref() // 表单 Ref
+const isDetail = ref(false) // 是否详情打开
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+let dataForm = ref({
+  // 表单字段
+  id: undefined,
+  idCard: '',
+  buildId: '',
+  floorId: '',
+  floorName: '',
+  contractNumber: '', //档案号
+  elderName: '',//长者姓名
+  bedName: '', //床位号
+  elderAge: '', //年龄
+  elderSex: '', //性别
+  checkInTime: '', //入院日期
+  elderId: '',
+  tenantId: undefined
+})
+
+
+const buildList = ref([])
+const floorList = ref([])
+const handleBuildChange = (buildId: any) => {
+  const selectedBuild = buildList.value.find((item: any) => item.id === buildId)
+  if (selectedBuild) {
+    dataForm.value.buildName = selectedBuild.buildName
+    floorList.value = selectedBuild.floorList || []
+    // 清空楼层选择
+    dataForm.value.floorId = ''
+    dataForm.value.floorName = ''
+  }
+}
+const handleFloorChange = (floorId: any) => {
+  const selectedFloor = floorList.value.find((item: any) => item.id === floorId)
+  if (selectedFloor) {
+    dataForm.value.floorName = selectedFloor.floorName
+  }
+}
+
+const elderUp = (e) => {
+  dataForm.value.elderName = e.elderName
+  dataForm.value.elderId = e.id
+  dataForm.value.elderSex = e.elderSex === 1 ? '男' : '女'
+  dataForm.value.bedName = e.bedName || ''
+  dataForm.value.checkInTime = e.checkInTime
+  dataForm.value.contractNumber = e.contractNumber
+  dataForm.value.elderAge = e.elderAge
+}
+
+// ========== 感知觉与沟通评估表 表单序列化方法 ==========
+
+// 危险物品登记不需要计算总分,保留计算属性占位
+const totalScore = computed(() => {
+  return 0
+})
+
+
+/** 将表单数据序列化为 JSON 对象 */
+const serializeFormData = () => {
+  return {
+    // 基本信息
+    assessor: form.assessor || '',
+    assessDate: form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : '',
+
+    // 31天楼宇清洁记录
+    records: form.records || []
+  }
+}
+
+/** 将 JSON 对象反序列化为表单数据 */
+const deserializeFormData = (formData: Record<string, any>) => {
+  if (!formData) return
+
+  // 基本信息
+  form.assessor = formData.assessor || ''
+  form.assessDate = formData.assessDate ? dayjs(formData.assessDate).toDate() : ''
+
+  // 31天楼宇清洁记录
+  if (formData.records && formData.records.length > 0) {
+    form.records = formData.records
+  } else {
+    form.records = generate31DaysRecords()
+  }
+}
+
+/** 重置楼宇清洁消毒记录表表单数据 */
+const resetPerceptionForm = () => {
+  form.assessor = ''
+  form.assessDate = ''
+
+  // 重置31天楼宇清洁记录
+  form.records = generate31DaysRecords()
+}
+
+/** 打开弹窗 */
+const open = async (tenantId, id?: any, detail: boolean = false) => {
+  resetForm()
+  dialogVisible.value = true
+  dataForm.value.id = id || undefined
+  dataForm.value.tenantId = tenantId
+  isDetail.value = detail
+  try {
+    buildList.value = await getBuildList({tenantIds: tenantId})
+  }catch (e) {}
+
+  if (id) {
+    title.value = "编辑-楼宇清洁消毒记录"
+    // 加载登记数据
+    await loadDangerousGoodsData(id)
+  } else {
+    title.value = "新增-楼宇清洁消毒记录"
+
+  }
+}
+
+/** 加载登记数据 */
+const loadDangerousGoodsData = async (id: number) => {
+  try {
+    const res = await buildingCleaningGetById(id)
+    if (res) {
+      // 填充长者基本信息
+      dataForm.value.elderName = res.elderName || ''
+      dataForm.value.elderId = res.elderId || ''
+      dataForm.value.elderSex = res.elderSex || ''
+      dataForm.value.bedName = res.bedName || ''
+      dataForm.value.checkInTime = res.checkInTime || ''
+      dataForm.value.contractNumber = res.fileNumber || ''
+      dataForm.value.elderAge = res.elderAge || ''
+      await selectElderRef.value.upData(res.elderName, res.elderId)
+      // 解析 assessData
+      if (res.assessData) {
+        const formData = JSON.parse(res.assessData)
+        deserializeFormData(formData)
+      }
+    }
+  } catch (error) {
+    message.error('加载楼宇清洁消毒记录数据失败')
+  }
+}
+
+
+
+// 生成31天的记录数据结构
+const generate31DaysRecords = () => {
+  return Array.from({ length: 31 }, () => ({
+    // 护理站
+    nurseStation: {
+      phone: { morning: '', noon: '', evening: '' },
+      table: { morning: '', noon: '', evening: '' },
+      chair: { morning: '', noon: '', evening: '' }
+    },
+    // 长者房间
+    elderRoom: {
+      bedsideTable: { morning: '', noon: '', evening: '' },
+      bedRail: { morning: '', noon: '', evening: '' },
+      switchBtn: { morning: '', noon: '', evening: '' },
+      doorHandle: { morning: '', noon: '', evening: '' }
+    },
+    // 居室
+    livingRoom: {
+      floor: { morning: '', noon: '', evening: '' },
+      windowsill: { morning: '', noon: '', evening: '' },
+      handrail: { morning: '', noon: '', evening: '' }
+    },
+    // 卫生间
+    toilet: {
+      faucet: { morning: '', noon: '', evening: '' },
+      toilet: { morning: '', noon: '', evening: '' }
+    },
+    // 开水间
+    waterRoom: { morning: '', noon: '', evening: '' },
+    // 垃圾存放处
+    garbage: { morning: '', noon: '', evening: '' },
+    // 开窗通风
+    ventilation: { morning: '', noon: '', evening: '' },
+    // 执行签名
+    signature: ''
+  }))
+}
+
+const form = reactive({
+  // 基本信息
+  assessor: '',
+  assessDate: '',
+
+  // 31天楼宇清洁记录
+  records: generate31DaysRecords()
+})
+
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  if (formLoading.value) {
+    return
+  }
+  formLoading.value = true
+  // 提交请求
+    try {
+      const assessData = serializeFormData()
+      const tempParams = {
+        ...dataForm.value,
+        assessData: JSON.stringify(assessData),
+        assessor: form.assessor,
+        assessDate: form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : ''
+      }
+
+    if (dataForm.value.id) {
+      const res = await buildingCleaningUpdate(tempParams)
+      if (res) {
+        message.success(t('common.updateSuccess'))
+        dialogVisible.value = false
+        // 发送操作成功的事件
+        emit('success')
+      }
+    } else {
+      const res = await buildingCleaningCreate(tempParams)
+      if (res) {
+        message.success(t('common.createSuccess'))
+        dialogVisible.value = false
+        // 发送操作成功的事件
+        emit('success')
+      }
+    }
+  } finally {
+    setTimeout(() => {
+      formLoading.value = false
+    }, 500)
+  }
+}
+
+
+
+/** 重置表单 */
+const resetForm = () => {
+  dataForm.value = {
+    id: undefined,
+    idCard: '',
+    buildId: '',
+    floorId: '',
+    floorName: '',
+    contractNumber: '', //档案号
+    elderName: '',//长者姓名
+    bedName: '', //床位号
+    elderAge: '', //年龄
+    elderSex: '', //性别
+    checkInTime: '', //入院日期
+    elderId: '',
+    tenantId: undefined
+  }
+  formRef.value?.resetFields()
+
+  // 重置感知觉与沟通评估表表单
+  resetPerceptionForm()
+}
+
+// 关闭表单
+const handleClosed = () => {
+  dialogVisible.value = false
+  resetForm()
+}
+
+
+
+</script>
+
+<style scoped lang="scss">
+.mmse-form {
+  margin: 0 auto;
+  background: #fff;
+
+  .form-title {
+    text-align: center;
+    font-size: 24px;
+    font-weight: bold;
+    margin-bottom: 20px;
+  }
+
+
+
+  .info-row {
+    display: flex;
+    gap: 40px;
+    width: 100%;
+    flex-direction: row;
+    align-items: center;
+    margin-bottom: 10px;
+
+    .info-item {
+      display: flex;
+      align-items: center;
+      gap: 8px;
+
+      .label {
+        width: 82px;
+        text-align: right;
+        margin-right: 4px;
+        white-space: nowrap;
+      }
+    }
+  }
+
+
+  .form-body {
+    border: 1px solid #333;
+    padding: 15px;
+
+    .building-cleaning-table-wrapper {
+      overflow-x: auto;
+      margin-bottom: 20px;
+
+      .building-cleaning-table {
+        min-width: 2400px;
+        border-collapse: collapse;
+        border: 1px solid #333;
+
+        th, td {
+          border: 1px solid #333;
+          padding: 2px;
+          text-align: center;
+          vertical-align: middle;
+        }
+
+        th {
+          background: #f5f7fa;
+          font-weight: bold;
+          font-size: 11px;
+        }
+
+        .col-area-header {
+          width: 80px;
+          min-width: 80px;
+          background: #e8f4f8;
+        }
+
+        .col-day-header {
+          width: 75px;
+          min-width: 75px;
+          font-size: 12px;
+        }
+
+        .col-time {
+          width: 55px;
+          min-width: 55px;
+          font-size: 12px;
+          background: #fffbe6;
+        }
+
+        .col-day-header {
+          width: 165px;
+          min-width: 165px;
+          font-size: 13px;
+          background: #f5f7fa;
+        }
+
+        .area-name {
+          font-weight: bold;
+          background: #f5f7fa;
+          font-size: 11px;
+        }
+
+        .item-name {
+          width: 60px;
+          min-width: 60px;
+          font-size: 11px;
+          background: #fafafa;
+        }
+
+        tbody {
+          tr {
+            height: 32px;
+          }
+
+          td {
+            .native-select {
+              width: 100%;
+              height: 26px;
+              padding: 0 16px 0 2px;
+              font-size: 11px;
+              border: 1px solid #dcdfe6;
+              border-radius: 3px;
+              background-color: #fff;
+              text-align: center;
+              cursor: pointer;
+              appearance: none;
+              background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
+              background-repeat: no-repeat;
+              background-position: right 2px center;
+              background-size: 12px;
+
+              &:focus {
+                border-color: #409eff;
+                outline: none;
+              }
+
+              option {
+                font-size: 12px;
+              }
+            }
+
+            .check-value {
+              font-size: 11px;
+              display: inline-block;
+              min-width: 24px;
+            }
+          }
+        }
+      }
+    }
+
+    .dangerous-goods-table {
+      margin-bottom: 20px;
+
+      .goods-table {
+        width: 100%;
+        border-collapse: collapse;
+        border: 1px solid #333;
+
+        th, td {
+          border: 1px solid #333;
+          padding: 10px 8px;
+          text-align: center;
+          vertical-align: middle;
+        }
+
+        th {
+          background: #f5f7fa;
+          font-weight: bold;
+          font-size: 14px;
+        }
+
+        .col-no {
+          width: 50px;
+        }
+
+        .col-bed {
+          width: 80px;
+        }
+
+        .col-name {
+          width: 80px;
+        }
+
+        .col-goods-title {
+          background: #f5f7fa;
+          font-weight: bold;
+        }
+
+        .col-goods {
+          width: 100px;
+        }
+
+        .col-storage {
+          width: 120px;
+        }
+
+        .col-sign {
+          width: 120px;
+        }
+
+        .col-remark {
+          width: 150px;
+        }
+
+        tbody {
+          td {
+            .el-input {
+              width: 100%;
+            }
+
+            .el-textarea {
+              width: 100%;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  .section {
+    margin-bottom: 20px;
+
+    &:last-child {
+      margin-bottom: 0;
+    }
+
+    .section-title {
+      font-weight: bold;
+      margin-bottom: 10px;
+    }
+  }
+
+  .form-item {
+    display: flex;
+    align-items: center;
+    margin-bottom: 12px;
+    flex-wrap: wrap;
+    gap: 8px;
+
+    .item-number {
+      font-weight: bold;
+      min-width: 25px;
+    }
+
+    .item-label {
+      white-space: nowrap;
+      min-width: fit-content;
+    }
+
+  }
+
+  .other-input {
+    width: 200px;
+    margin-left: 10px;
+  }
+
+  // 调整 Element Plus 组件样式
+  :deep(.el-input__inner) {
+    height: 28px;
+    line-height: 28px;
+    border-top: none;
+    border-left: none;
+    border-right: none;
+    border-radius: 0;
+    padding: 0 4px;
+
+    &:focus {
+      border-color: #409eff;
+    }
+  }
+
+
+  :deep(.el-checkbox__label),
+  :deep(.el-radio__label) {
+    padding-left: 4px;
+  }
+}
+.row{
+  margin-bottom: 12px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  text{
+    text-align: right;
+    margin-right: 4px;
+    width: 82px;
+  }
+}
+
+// 感知觉与沟通评估表 特有样式
+.total-score-section {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  margin-bottom: 20px;
+
+  .total-score {
+    display: flex;
+    align-items: baseline;
+    gap: 4px;
+
+    .score-label {
+      font-size: 16px;
+      font-weight: bold;
+    }
+
+    .score-value {
+      font-size: 28px;
+      font-weight: bold;
+      color: #409eff;
+    }
+
+    .score-max {
+      font-size: 14px;
+      color: #909399;
+    }
+  }
+
+  .risk-level {
+    font-size: 16px;
+    font-weight: bold;
+    padding: 8px 16px;
+    border-radius: 4px;
+
+    &.risk-none {
+      color: #67c23a;
+      background: #f0f9eb;
+    }
+
+    &.risk-low {
+      color: #e6a23c;
+      background: #fdf6ec;
+    }
+
+    &.risk-medium {
+      color: #f56c6c;
+      background: #fef0f0;
+    }
+
+    &.risk-high {
+      color: #f56c6c;
+      background: #fef0f0;
+      border: 1px solid #f56c6c;
+    }
+  }
+}
+
+.assessment-table {
+  width: 100%;
+  border-collapse: collapse;
+  margin-bottom: 20px;
+
+  table {
+    width: 100%;
+    border: 1px solid #333;
+
+    th, td {
+      border: 1px solid #333;
+      padding: 12px;
+      text-align: left;
+    }
+
+    th {
+      background: #f5f7fa;
+      font-weight: bold;
+      text-align: center;
+    }
+
+    .criteria-col {
+      width: 60%;
+    }
+
+    .score-col {
+      width: 15%;
+      text-align: center;
+    }
+
+    .select-col {
+      width: 25%;
+      text-align: center;
+    }
+
+    .criteria {
+      text-align: left;
+    }
+
+    .score {
+      text-align: center;
+      font-weight: bold;
+    }
+
+    .select {
+      text-align: center;
+
+      :deep(.el-radio) {
+        margin-right: 0;
+      }
+    }
+  }
+}
+
+.remark-section {
+  margin: 15px 0;
+  padding: 12px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .remark-label {
+    font-weight: bold;
+    color: #606266;
+  }
+
+  .remark-text {
+    color: #606266;
+  }
+}
+
+.risk-judgment-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .risk-judgment-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .risk-options {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20px;
+
+    :deep(.el-radio) {
+      margin-right: 0;
+    }
+  }
+}
+
+.preventive-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .preventive-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .preventive-options {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 15px;
+
+    :deep(.el-checkbox) {
+      margin-right: 20px;
+      margin-bottom: 8px;
+    }
+
+    .other-input {
+      width: 200px;
+      margin-left: 10px;
+    }
+  }
+}
+
+.signature-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .signature-row {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    gap: 20px;
+  }
+
+  .signature-item {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+
+    &.date-item {
+      :deep(.el-date-picker) {
+        width: 150px;
+      }
+    }
+  }
+
+  .signature-label {
+    font-weight: bold;
+    white-space: nowrap;
+  }
+
+  .signature-input {
+    width: 150px;
+  }
+
+  .date-picker {
+    width: 150px;
+  }
+}
+
+.note-section {
+  margin-top: 20px;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .note-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .note-content {
+    font-size: 13px;
+    line-height: 1.8;
+    color: #606266;
+
+    p {
+      margin: 5px 0;
+    }
+
+    .indent {
+      margin-left: 20px;
+    }
+  }
+}
+</style>

+ 390 - 0
src/views/elderly/nursing/records/build-dustman/index.vue

@@ -0,0 +1,390 @@
+<template>
+  <ContentWrap>
+    <!-- 工单记录 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="110px"
+    >
+      <el-form-item label="长者姓名">
+        <el-input
+          v-model="queryParams.elderName"
+          placeholder="长者姓名"
+          class="!w-240px"
+          clearable
+        />
+      </el-form-item>
+
+      <el-form-item label="楼栋">
+        <el-select v-model="queryParams.buidId" placeholder="选择楼栋" style="width: 180px" @change="handleBuildChange">
+          <el-option v-for="(item,index) in buildList" :key="index" :label="item.buildName" :value="item.id" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="楼层">
+        <el-select  v-model="queryParams.floorId" placeholder="选择楼层" style="width: 180px" >
+          <el-option v-for="(item,index) in floorList" :key="index" :label="item.floorName" :value="item.id" />
+        </el-select>
+      </el-form-item>
+
+
+      <el-form-item label="登记月份">
+        <el-date-picker
+          size="default"
+          ref="selectRef"
+          class="!w-240px"
+          v-model="queryParams.discoveryTime"
+          type="monthrange"
+          :clearable="true"
+          :editable="false"
+          placeholder="选择月份"
+          value-format="YYYY-MM-DD"
+          format="YYYY-MM-DD"
+          date-format="YYYY-MM-DD"
+        />
+      </el-form-item>
+
+      <el-form-item>
+        <el-button @click="handleQuery" style="margin-left: 2vw"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <div class="mb-10px">
+
+      <ButtonAdd @click="openForm(undefined)"  />
+      <el-button @click="inputH" type="success"><Icon icon="fa:cloud-upload" :size="16" class="mr-1"/>导入</el-button>
+      <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">
+        <template #default="scope">
+          {{
+            scope.$index + (queryParams.pageNo * queryParams.pageSize - queryParams.pageSize) + 1
+          }}
+        </template>
+      </el-table-column>
+
+
+      <el-table-column prop="elderName" header-align="center" align="center" label="长者姓名" min-width="120" show-overflow-tooltip/>
+      <el-table-column prop="elderSex" header-align="center" align="center" label="性别" min-width="90" show-overflow-tooltip/>
+      <el-table-column prop="elderAge" header-align="center" align="center" label="年龄" min-width="90" show-overflow-tooltip/>
+      <el-table-column prop="serviceItem" header-align="center" align="center" label="服务项目" min-width="200" show-overflow-tooltip/>
+      <el-table-column prop="serviceName" header-align="center" align="center" label="服务人员姓名" min-width="160" show-overflow-tooltip/>
+      <el-table-column prop="orderTime" header-align="center" align="center" label="订单时间" min-width="180" show-overflow-tooltip>
+        <template #default="scope">
+          {{(formatToDateTime(scope.row.orderTime))}}
+        </template>
+      </el-table-column>
+      <el-table-column prop="comeTime" header-align="center" align="center" label="上门时间" min-width="180" show-overflow-tooltip>
+        <template #default="scope">
+          {{formatToDateTime(scope.row.serviceBeginTime)}}
+        </template>
+      </el-table-column>
+      <el-table-column prop="elderAddress" header-align="center" align="center" label="地址" min-width="220" show-overflow-tooltip/>
+      <el-table-column prop="isExpire" header-align="center" align="center" label="是否过期" min-width="120" show-overflow-tooltip/>
+      <el-table-column prop="orderStatus" header-align="center" align="center" label="订单状态" min-width="160" show-overflow-tooltip/>
+
+      <el-table-column label="操作" align="center" width="200" fixed="right">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openFormEdit(scope.row, scope.row.id)"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="warning"
+            @click="openFormDetail(scope.row.id)"
+          >
+            详情
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="openClose(scope.row)"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </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"
+  />
+
+
+  <Import
+    ref="importRef"
+    @success="getList"
+    :config="{
+      title: '导入',
+      downloadUrl: 'elderly-service-order/get-import-template',
+      excelTempName: '居家工单-【导入】模板',
+      importUrl: '/elderly-service-order/import',
+      failExportUrl: '',
+    }"
+  />
+
+</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 {
+  careRecordsPage, elderlyServiceOrderDelete, elderlyServiceOrderPage,
+} from "@/api/member/appointment";
+import download from "@/utils/download";
+import { useUserStore } from '@/store/modules/user'
+import {formatToDate, formatToDateTime, getCurrentMonthRange} from "@/utils/dateUtil";
+import * as UserApi from "@/api/system/user";
+import Import from "@/components/ImportFile/index.vue";
+import {ref} from "vue";
+import {getBuildList} from "@/api/system/badManage";
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+const userStore = useUserStore()
+const loading = ref(true) // 列表的加载中
+const detailRef = ref()
+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,
+  elderName: '',
+  elderPhone: '',
+  discoveryTime: ["2025-12-01",formatToDate()],
+  tenantIds: userStore.orgTenantId[0]
+})
+const queryFormRef = ref() // 搜索的表单
+
+const inputH = () => {
+  importRef.value.open(queryParams.tenantIds[0])
+}
+// 打开导出弹窗
+const handleImportCard = async () => {
+  try {
+    const queryParams = reactive({
+      pageNo: 1,
+      pageSize: 1000,
+      tenantIds: userStore.orgTenantId,
+    })
+    const data = await UserApi.exportElderlyServiceOrder(queryParams)
+    download.excel(data, '工单报表数据.xls')
+  }catch (e) {
+
+  }
+
+
+  // exportConfig.value = {
+  //   title: "批量导出",
+  //   batchMin: 1,
+  //   batchMax: 999,
+  //   countMin: 1,
+  //   countMax: 500,
+  //   defaultBatch: 1,
+  //   defaultCount: 500,
+  //   description: [
+  //     '1. 请输入需要导出的数量',
+  //     '2. 一次导不完的话,输入批次 2 再次导出,以此类推。',
+  //     '3. 建议单次导出数量不超过500,以免影响系统性能',
+  //     '4. 导出需要较长时间,请耐心等待。'
+  //   ]
+  // }
+  // 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 (_) {}
+
+}
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    //let queryP = {...queryParams,discoveryTime:queryParams.discoveryTime?[queryParams.discoveryTime[0]+" 00:00:00",queryParams.discoveryTime[1]+" 23:59:59"]:null}
+    const data = await elderlyServiceOrderPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = async () => {
+  if (!queryFormRef.value) return
+  const valid = await queryFormRef.value.validate()
+  if (!valid) return
+  queryParams.pageNo = 1
+  await getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryParams.elderName = ''
+  queryParams.tenantId = userStore.orgTenantId[0]
+  queryParams.discoveryTime= ["2025-12-01",formatToDate()]
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (id?: number) => {
+  // if(queryParams.tenantIds.length == 0 || queryParams.tenantIds.length > 1){
+  //   message.error('新增只能选择一个机构')
+  //   return
+  // }
+  formRef.value.open(queryParams.tenantIds, id,false)
+}
+
+const editRef = ref()
+const openFormEdit = (row: any = {}, id?: number) => {
+  formRef.value.open(row.tenantId, id,false)
+}
+
+
+const openFormDetail = (id?: number) => {
+  formRef.value.open(undefined,id,true)
+}
+
+
+
+
+
+const openClose = async (item) => {
+  try {
+    console.log("任务ID",item)
+    const res = await message.confirm('确定要删除吗?', '提示')
+    if (res == 'confirm') {
+      // 发起
+      try {
+        const res = await elderlyServiceOrderDelete(item.id)
+        if (res){
+          message.success(t('common.updateSuccess'))
+        }
+      }catch(err) {}
+    }
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 取消按钮操作 */
+const cancelDelete = async (id: number) => {
+  try {
+    // 取消的二次确认
+    await message.cancelConfirm()
+    // 发起取消
+    // await elderlyBakDel(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+
+const buildList = ref([])
+const floorList = ref([])
+
+const route = useRoute()
+/** 初始化 **/
+onMounted(async () => {
+  if(route.query && route.query.elderName){
+    queryParams.elderName = route.query.elderName as string
+  }
+  getList()
+  try {
+    buildList.value = await getBuildList({tenantIds: queryParams.tenantId})
+  }catch (e) {}
+})
+
+// 表头格式
+const tableHeaderColor = ({ rowIndex }: any) => {
+  if (rowIndex === 0) {
+    return {
+      backgroundColor: '#f8f8f9',
+      color: '#666666',
+      fontWeight: 'bold'
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss"></style>

+ 865 - 0
src/views/elderly/nursing/records/dangerous-records/AddForm.vue

@@ -0,0 +1,865 @@
+<template>
+  <el-drawer
+    v-model="dialogVisible"
+    :title="title"
+    resizable
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    :destroy-on-close="true"
+    size="70%"
+    :before-close="handleClosed"
+  >
+
+    <div class="mmse-form">
+      <!-- 危险用品记录 -->
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>长者姓名</text>
+          <search-the-elderly ref="selectElderRef" :disabled="isDetail" @update_elder="elderUp" v-model="dataForm.elderName" :tId="dataForm.tenantId"/>
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>档案号</text>
+          <el-input v-if="!isDetail" v-model="dataForm.contractNumber" disabled />
+          <el-text v-else disabled="">{{dataForm.contractNumber}}</el-text>
+        </el-col>
+      </el-row>
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>入院日期</text>
+          <el-input v-if="!isDetail" :model-value="dayjs(dataForm.checkInTime).format('YYYY-MM-DD')=='Invalid Date'?'':dayjs(dataForm.checkInTime).format('YYYY-MM-DD')" disabled />
+          <el-text v-else disabled="">{{dayjs(dataForm.checkInTime).format('YYYY-MM-DD')}}</el-text>
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>床位号</text>
+          <el-input v-if="!isDetail" v-model="dataForm.bedName" disabled />
+          <el-text v-else disabled="">{{dataForm.bedName}}</el-text>
+        </el-col>
+      </el-row>
+
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" class="row">
+          <text>楼栋</text>
+          <el-select :disabled="isDetail" v-model="dataForm.buildId" placeholder="选择楼栋" style="width: 100%" @change="handleBuildChange">
+            <el-option  v-for="(item,index) in buildList" :key="index" :label="item.buildName" :value="item.id" />
+          </el-select>
+
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" class="row">
+          <text>楼层</text>
+            <el-select :disabled="isDetail" v-model="dataForm.floorId" placeholder="选择楼层" style="width: 100%" @change="handleFloorChange">
+              <el-option v-for="(item,index) in floorList" :key="index" :label="item.floorName" :value="item.id" />
+            </el-select>
+
+        </el-col>
+      </el-row>
+
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>登记人</text>
+          <el-input :disabled="isDetail" v-model="form.assessor"  />
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>登记日期</text>
+          <el-date-picker :disabled="isDetail" v-model="form.assessDate" type="date" style="width: 100%;"/>
+        </el-col>
+      </el-row>
+
+      <!-- 表单内容区域 -->
+      <div class="form-body">
+        <!-- 危险物品登记表 -->
+        <div class="dangerous-goods-table">
+          <table class="goods-table">
+            <thead>
+              <tr>
+                <th colspan="4" class="col-goods-title">危险物品种类及数量</th>
+                <th rowspan="2" class="col-storage">保管方式</th>
+                <th rowspan="2" class="col-sign">老年人/相关第三方签名</th>
+                <th rowspan="2" class="col-remark">备注</th>
+              </tr>
+              <tr>
+                <th class="col-goods">利器类</th>
+                <th class="col-goods">电器类</th>
+                <th class="col-goods">热源产品</th>
+                <th class="col-goods">其它</th>
+              </tr>
+            </thead>
+            <tbody>
+              <tr>
+                <td>
+                  <el-input v-if="!isDetail" v-model="form.sharpTools" type="textarea" :rows="3" placeholder="数量/描述" />
+                  <span v-else>{{ form.sharpTools }}</span>
+                </td>
+                <td>
+                  <el-input v-if="!isDetail" v-model="form.electrical" type="textarea" :rows="3" placeholder="数量/描述" />
+                  <span v-else>{{ form.electrical }}</span>
+                </td>
+                <td>
+                  <el-input v-if="!isDetail" v-model="form.heatSource" type="textarea" :rows="3" placeholder="数量/描述" />
+                  <span v-else>{{ form.heatSource }}</span>
+                </td>
+                <td>
+                  <el-input v-if="!isDetail" v-model="form.otherGoods" type="textarea" :rows="3" placeholder="数量/描述" />
+                  <span v-else>{{ form.otherGoods }}</span>
+                </td>
+                <td>
+                  <el-input v-if="!isDetail" v-model="form.storageMethod" type="textarea" :rows="3" placeholder="自行保管/工作人员保管/其它" />
+                  <span v-else>{{ form.storageMethod }}</span>
+                </td>
+                <td>
+                  <el-input v-if="!isDetail" v-model="form.elderSignature" type="textarea" :rows="3" placeholder="签名" />
+                  <span v-else>{{ form.elderSignature }}</span>
+                </td>
+                <td>
+                  <el-input v-if="!isDetail" v-model="form.remark" type="textarea" :rows="3" placeholder="备注" />
+                  <span v-else>{{ form.remark }}</span>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+
+        <!-- 备注说明 -->
+        <div class="note-section">
+          <div class="note-title">备注说明</div>
+          <div class="note-content">
+            <p>1. 老年人危险物品包括:</p>
+            <p class="indent">• 利器类(菜刀、餐刀、水果刀、剪刀、螺丝刀、美工刀等)</p>
+            <p class="indent">• 电器类(电饭锅、电磁炉、冰箱、电吹风等)</p>
+            <p class="indent">• 热源产品(热水袋、取暖器等)</p>
+            <p>2. 保管方式填写:①自行保管,②工作人员保管,③其它:按实际填写。</p>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div>前端提交的数据,后端可以参照这个格式:
+      {
+      "buildId": 190,
+      "floorId": 644,
+      "floorName": "2层",
+      "contractNumber": "111",
+      "elderName": "0318",
+      "bedName": "测试楼-2层-201-10",
+      "elderAge": 86,
+      "elderSex": "男",
+      "elderId": 18697,
+      "tenantId": 195,
+      "buildName": "测试楼",
+      "assessData": " ",
+      "assessor": "啊啊啊",
+      "assessDate": "2026-03-27",
+      "orgType": 1
+      }
+    </div>
+
+
+
+    <template #footer>
+      <el-button @click="handleClosed">关闭</el-button>
+      <el-button style="margin-left: 22px;margin-right: 30px" v-loading="formLoading" type="primary" v-show="!isDetail" @click="submitForm">确定</el-button>
+      <el-button v-if="isDetail" type="success" @click="handleExport">打印</el-button>
+    </template>
+
+  </el-drawer>
+</template>
+
+<script lang="ts" setup>
+import { computed, ref } from 'vue'
+
+import dayjs from 'dayjs'
+
+import { dangerousGoodsCreate, dangerousGoodsGetById, dangerousGoodsUpdate } from "@/api/social-work";
+import {getBuildList} from "@/api/system/badManage";
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+const title = ref('')
+const dialogVisible = ref(false) // 弹窗
+const formRef = ref() // 表单 Ref
+const selectElderRef = ref() // 表单 Ref
+const isDetail = ref(false) // 是否详情打开
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+let dataForm = ref({
+  // 表单字段
+  id: undefined,
+  idCard: '',
+  buildId: '',
+  floorId: '',
+  floorName: '',
+  contractNumber: '', //档案号
+  elderName: '',//长者姓名
+  bedName: '', //床位号
+  elderAge: '', //年龄
+  elderSex: '', //性别
+  checkInTime: '', //入院日期
+  elderId: '',
+  tenantId: undefined
+})
+
+
+const buildList = ref([])
+const floorList = ref([])
+const handleBuildChange = (buildId: any) => {
+  const selectedBuild = buildList.value.find((item: any) => item.id === buildId)
+  if (selectedBuild) {
+    dataForm.value.buildName = selectedBuild.buildName
+    floorList.value = selectedBuild.floorList || []
+    // 清空楼层选择
+    dataForm.value.floorId = ''
+    dataForm.value.floorName = ''
+  }
+}
+const handleFloorChange = (floorId: any) => {
+  const selectedFloor = floorList.value.find((item: any) => item.id === floorId)
+  if (selectedFloor) {
+    dataForm.value.floorName = selectedFloor.floorName
+  }
+}
+
+const elderUp = (e) => {
+  dataForm.value.elderName = e.elderName
+  dataForm.value.elderId = e.id
+  dataForm.value.elderSex = e.elderSex === 1 ? '男' : '女'
+  dataForm.value.bedName = e.bedName || ''
+  dataForm.value.checkInTime = e.checkInTime
+  dataForm.value.contractNumber = e.contractNumber
+  dataForm.value.elderAge = e.elderAge
+}
+
+// ========== 感知觉与沟通评估表 表单序列化方法 ==========
+
+// 危险物品登记不需要计算总分,保留计算属性占位
+const totalScore = computed(() => {
+  return 0
+})
+
+
+/** 将表单数据序列化为 JSON 对象 */
+const serializeFormData = () => {
+  return {
+    // 基本信息
+    assessor: form.assessor || '',
+    assessDate: form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : '',
+
+    // 危险物品登记
+    sharpTools: form.sharpTools || '',
+    electrical: form.electrical || '',
+    heatSource: form.heatSource || '',
+    otherGoods: form.otherGoods || '',
+    storageMethod: form.storageMethod || '',
+    elderSignature: form.elderSignature || '',
+    remark: form.remark || ''
+  }
+}
+
+/** 将 JSON 对象反序列化为表单数据 */
+const deserializeFormData = (formData: Record<string, any>) => {
+  if (!formData) return
+
+  // 基本信息
+  form.assessor = formData.assessor || ''
+  form.assessDate = formData.assessDate ? dayjs(formData.assessDate).toDate() : ''
+
+  // 危险物品登记
+  form.sharpTools = formData.sharpTools || ''
+  form.electrical = formData.electrical || ''
+  form.heatSource = formData.heatSource || ''
+  form.otherGoods = formData.otherGoods || ''
+  form.storageMethod = formData.storageMethod || ''
+  form.elderSignature = formData.elderSignature || ''
+  form.remark = formData.remark || ''
+}
+
+/** 重置危险物品登记表单数据 */
+const resetPerceptionForm = () => {
+  form.assessor = ''
+  form.assessDate = ''
+
+  // 危险物品登记
+  form.sharpTools = ''
+  form.electrical = ''
+  form.heatSource = ''
+  form.otherGoods = ''
+  form.storageMethod = ''
+  form.elderSignature = ''
+  form.remark = ''
+}
+
+/** 打开弹窗 */
+const open = async (tenantId, id?: any, detail: boolean = false) => {
+  resetForm()
+  dialogVisible.value = true
+  dataForm.value.id = id || undefined
+  dataForm.value.tenantId = tenantId
+  isDetail.value = detail
+  try {
+    buildList.value = await getBuildList({tenantIds: tenantId})
+  }catch (e) {}
+
+  if (id) {
+    title.value = "编辑-危险物品登记"
+    // 加载登记数据
+    await loadDangerousGoodsData(id)
+  } else {
+    title.value = "新增-危险物品登记"
+
+  }
+}
+
+/** 加载登记数据 */
+const loadDangerousGoodsData = async (id: number) => {
+  try {
+    const res = await dangerousGoodsGetById(id)
+    if (res) {
+      // 填充长者基本信息
+      dataForm.value.elderName = res.elderName || ''
+      dataForm.value.elderId = res.elderId || ''
+      dataForm.value.elderSex = res.elderSex || ''
+      dataForm.value.bedName = res.bedName || ''
+      dataForm.value.checkInTime = res.checkInTime || ''
+      dataForm.value.contractNumber = res.fileNumber || ''
+      dataForm.value.elderAge = res.elderAge || ''
+      await selectElderRef.value.upData(res.elderName, res.elderId)
+      // 解析 assessData
+      if (res.assessData) {
+        const formData = JSON.parse(res.assessData)
+        deserializeFormData(formData)
+      }
+    }
+  } catch (error) {
+    message.error('加载登记数据失败')
+  }
+}
+
+
+
+const form = reactive({
+  // 基本信息
+  assessor: '',
+  assessDate: '',
+
+  // 危险物品登记
+  sharpTools: '',      // 利器类
+  electrical: '',      // 电器类
+  heatSource: '',      // 热源产品
+  otherGoods: '',      // 其它
+  storageMethod: '',   // 保管方式
+  elderSignature: '',  // 老年人/相关第三方签名
+  remark: ''           // 备注
+})
+
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  if (formLoading.value) {
+    return
+  }
+  formLoading.value = true
+  // 提交请求
+    try {
+      const assessData = serializeFormData()
+      const tempParams = {
+        ...dataForm.value,
+        assessData: JSON.stringify(assessData),
+        assessor: form.assessor,
+        assessDate: form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : ''
+      }
+
+    if (dataForm.value.id) {
+      const res = await dangerousGoodsUpdate(tempParams)
+      if (res) {
+        message.success(t('common.updateSuccess'))
+        dialogVisible.value = false
+        // 发送操作成功的事件
+        emit('success')
+      }
+    } else {
+      const res = await dangerousGoodsCreate(tempParams)
+      if (res) {
+        message.success(t('common.createSuccess'))
+        dialogVisible.value = false
+        // 发送操作成功的事件
+        emit('success')
+      }
+    }
+  } finally {
+    setTimeout(() => {
+      formLoading.value = false
+    }, 500)
+  }
+}
+
+
+
+/** 重置表单 */
+const resetForm = () => {
+  dataForm.value = {
+    id: undefined,
+    idCard: '',
+    buildId: '',
+    floorId: '',
+    floorName: '',
+    contractNumber: '', //档案号
+    elderName: '',//长者姓名
+    bedName: '', //床位号
+    elderAge: '', //年龄
+    elderSex: '', //性别
+    checkInTime: '', //入院日期
+    elderId: '',
+    tenantId: undefined
+  }
+  formRef.value?.resetFields()
+
+  // 重置感知觉与沟通评估表表单
+  resetPerceptionForm()
+}
+
+// 关闭表单
+const handleClosed = () => {
+  dialogVisible.value = false
+  resetForm()
+}
+
+
+
+</script>
+
+<style scoped lang="scss">
+.mmse-form {
+  max-width: 1200px;
+  margin: 0 auto;
+  background: #fff;
+
+  .form-title {
+    text-align: center;
+    font-size: 24px;
+    font-weight: bold;
+    margin-bottom: 20px;
+  }
+
+
+
+  .info-row {
+    display: flex;
+    gap: 40px;
+    width: 100%;
+    flex-direction: row;
+    align-items: center;
+    margin-bottom: 10px;
+
+    .info-item {
+      display: flex;
+      align-items: center;
+      gap: 8px;
+
+      .label {
+        width: 82px;
+        text-align: right;
+        margin-right: 4px;
+        white-space: nowrap;
+      }
+    }
+  }
+
+
+  .form-body {
+    border: 1px solid #333;
+    padding: 15px;
+
+    .dangerous-goods-table {
+      margin-bottom: 20px;
+
+      .goods-table {
+        width: 100%;
+        border-collapse: collapse;
+        border: 1px solid #333;
+
+        th, td {
+          border: 1px solid #333;
+          padding: 10px 8px;
+          text-align: center;
+          vertical-align: middle;
+        }
+
+        th {
+          background: #f5f7fa;
+          font-weight: bold;
+          font-size: 14px;
+        }
+
+        .col-no {
+          width: 50px;
+        }
+
+        .col-bed {
+          width: 80px;
+        }
+
+        .col-name {
+          width: 80px;
+        }
+
+        .col-goods-title {
+          background: #f5f7fa;
+          font-weight: bold;
+        }
+
+        .col-goods {
+          width: 100px;
+        }
+
+        .col-storage {
+          width: 120px;
+        }
+
+        .col-sign {
+          width: 120px;
+        }
+
+        .col-remark {
+          width: 150px;
+        }
+
+        tbody {
+          td {
+            .el-input {
+              width: 100%;
+            }
+
+            .el-textarea {
+              width: 100%;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  .section {
+    margin-bottom: 20px;
+
+    &:last-child {
+      margin-bottom: 0;
+    }
+
+    .section-title {
+      font-weight: bold;
+      margin-bottom: 10px;
+    }
+  }
+
+  .form-item {
+    display: flex;
+    align-items: center;
+    margin-bottom: 12px;
+    flex-wrap: wrap;
+    gap: 8px;
+
+    .item-number {
+      font-weight: bold;
+      min-width: 25px;
+    }
+
+    .item-label {
+      white-space: nowrap;
+      min-width: fit-content;
+    }
+
+  }
+
+  .other-input {
+    width: 200px;
+    margin-left: 10px;
+  }
+
+  // 调整 Element Plus 组件样式
+  :deep(.el-input__inner) {
+    height: 28px;
+    line-height: 28px;
+    border-top: none;
+    border-left: none;
+    border-right: none;
+    border-radius: 0;
+    padding: 0 4px;
+
+    &:focus {
+      border-color: #409eff;
+    }
+  }
+
+
+  :deep(.el-checkbox__label),
+  :deep(.el-radio__label) {
+    padding-left: 4px;
+  }
+}
+.row{
+  margin-bottom: 12px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  text{
+    text-align: right;
+    margin-right: 4px;
+    width: 82px;
+  }
+}
+
+// 感知觉与沟通评估表 特有样式
+.total-score-section {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  margin-bottom: 20px;
+
+  .total-score {
+    display: flex;
+    align-items: baseline;
+    gap: 4px;
+
+    .score-label {
+      font-size: 16px;
+      font-weight: bold;
+    }
+
+    .score-value {
+      font-size: 28px;
+      font-weight: bold;
+      color: #409eff;
+    }
+
+    .score-max {
+      font-size: 14px;
+      color: #909399;
+    }
+  }
+
+  .risk-level {
+    font-size: 16px;
+    font-weight: bold;
+    padding: 8px 16px;
+    border-radius: 4px;
+
+    &.risk-none {
+      color: #67c23a;
+      background: #f0f9eb;
+    }
+
+    &.risk-low {
+      color: #e6a23c;
+      background: #fdf6ec;
+    }
+
+    &.risk-medium {
+      color: #f56c6c;
+      background: #fef0f0;
+    }
+
+    &.risk-high {
+      color: #f56c6c;
+      background: #fef0f0;
+      border: 1px solid #f56c6c;
+    }
+  }
+}
+
+.assessment-table {
+  width: 100%;
+  border-collapse: collapse;
+  margin-bottom: 20px;
+
+  table {
+    width: 100%;
+    border: 1px solid #333;
+
+    th, td {
+      border: 1px solid #333;
+      padding: 12px;
+      text-align: left;
+    }
+
+    th {
+      background: #f5f7fa;
+      font-weight: bold;
+      text-align: center;
+    }
+
+    .criteria-col {
+      width: 60%;
+    }
+
+    .score-col {
+      width: 15%;
+      text-align: center;
+    }
+
+    .select-col {
+      width: 25%;
+      text-align: center;
+    }
+
+    .criteria {
+      text-align: left;
+    }
+
+    .score {
+      text-align: center;
+      font-weight: bold;
+    }
+
+    .select {
+      text-align: center;
+
+      :deep(.el-radio) {
+        margin-right: 0;
+      }
+    }
+  }
+}
+
+.remark-section {
+  margin: 15px 0;
+  padding: 12px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .remark-label {
+    font-weight: bold;
+    color: #606266;
+  }
+
+  .remark-text {
+    color: #606266;
+  }
+}
+
+.risk-judgment-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .risk-judgment-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .risk-options {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20px;
+
+    :deep(.el-radio) {
+      margin-right: 0;
+    }
+  }
+}
+
+.preventive-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .preventive-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .preventive-options {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 15px;
+
+    :deep(.el-checkbox) {
+      margin-right: 20px;
+      margin-bottom: 8px;
+    }
+
+    .other-input {
+      width: 200px;
+      margin-left: 10px;
+    }
+  }
+}
+
+.signature-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .signature-row {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    gap: 20px;
+  }
+
+  .signature-item {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+
+    &.date-item {
+      :deep(.el-date-picker) {
+        width: 150px;
+      }
+    }
+  }
+
+  .signature-label {
+    font-weight: bold;
+    white-space: nowrap;
+  }
+
+  .signature-input {
+    width: 150px;
+  }
+
+  .date-picker {
+    width: 150px;
+  }
+}
+
+.note-section {
+  margin-top: 20px;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .note-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .note-content {
+    font-size: 13px;
+    line-height: 1.8;
+    color: #606266;
+
+    p {
+      margin: 5px 0;
+    }
+
+    .indent {
+      margin-left: 20px;
+    }
+  }
+}
+</style>

+ 390 - 0
src/views/elderly/nursing/records/dangerous-records/index.vue

@@ -0,0 +1,390 @@
+<template>
+  <ContentWrap>
+    <!-- 工单记录 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="110px"
+    >
+      <el-form-item label="长者姓名">
+        <el-input
+          v-model="queryParams.elderName"
+          placeholder="长者姓名"
+          class="!w-240px"
+          clearable
+        />
+      </el-form-item>
+
+      <el-form-item label="楼栋">
+        <el-select v-model="queryParams.buidId" placeholder="选择楼栋" style="width: 180px" @change="handleBuildChange">
+          <el-option v-for="(item,index) in buildList" :key="index" :label="item.buildName" :value="item.id" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="楼层">
+        <el-select  v-model="queryParams.floorId" placeholder="选择楼层" style="width: 180px" >
+          <el-option v-for="(item,index) in floorList" :key="index" :label="item.floorName" :value="item.id" />
+        </el-select>
+      </el-form-item>
+
+
+      <el-form-item label="登记日期">
+        <el-date-picker
+          size="default"
+          ref="selectRef"
+          class="!w-240px"
+          v-model="queryParams.discoveryTime"
+          type="daterange"
+          :clearable="true"
+          :editable="false"
+          placeholder="选择工单日期"
+          value-format="YYYY-MM-DD"
+          format="YYYY-MM-DD"
+          date-format="YYYY-MM-DD"
+        />
+      </el-form-item>
+
+      <el-form-item>
+        <el-button @click="handleQuery" style="margin-left: 2vw"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <div class="mb-10px">
+
+      <ButtonAdd @click="openForm(undefined)"  />
+      <el-button @click="inputH" type="success"><Icon icon="fa:cloud-upload" :size="16" class="mr-1"/>导入</el-button>
+      <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">
+        <template #default="scope">
+          {{
+            scope.$index + (queryParams.pageNo * queryParams.pageSize - queryParams.pageSize) + 1
+          }}
+        </template>
+      </el-table-column>
+
+
+      <el-table-column prop="elderName" header-align="center" align="center" label="长者姓名" min-width="120" show-overflow-tooltip/>
+      <el-table-column prop="elderSex" header-align="center" align="center" label="性别" min-width="90" show-overflow-tooltip/>
+      <el-table-column prop="elderAge" header-align="center" align="center" label="年龄" min-width="90" show-overflow-tooltip/>
+      <el-table-column prop="serviceItem" header-align="center" align="center" label="服务项目" min-width="200" show-overflow-tooltip/>
+      <el-table-column prop="serviceName" header-align="center" align="center" label="服务人员姓名" min-width="160" show-overflow-tooltip/>
+      <el-table-column prop="orderTime" header-align="center" align="center" label="订单时间" min-width="180" show-overflow-tooltip>
+        <template #default="scope">
+          {{(formatToDateTime(scope.row.orderTime))}}
+        </template>
+      </el-table-column>
+      <el-table-column prop="comeTime" header-align="center" align="center" label="上门时间" min-width="180" show-overflow-tooltip>
+        <template #default="scope">
+          {{formatToDateTime(scope.row.serviceBeginTime)}}
+        </template>
+      </el-table-column>
+      <el-table-column prop="elderAddress" header-align="center" align="center" label="地址" min-width="220" show-overflow-tooltip/>
+      <el-table-column prop="isExpire" header-align="center" align="center" label="是否过期" min-width="120" show-overflow-tooltip/>
+      <el-table-column prop="orderStatus" header-align="center" align="center" label="订单状态" min-width="160" show-overflow-tooltip/>
+
+      <el-table-column label="操作" align="center" width="200" fixed="right">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openFormEdit(scope.row, scope.row.id)"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="warning"
+            @click="openFormDetail(scope.row.id)"
+          >
+            详情
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="openClose(scope.row)"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </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"
+  />
+
+
+  <Import
+    ref="importRef"
+    @success="getList"
+    :config="{
+      title: '导入',
+      downloadUrl: 'elderly-service-order/get-import-template',
+      excelTempName: '居家工单-【导入】模板',
+      importUrl: '/elderly-service-order/import',
+      failExportUrl: '',
+    }"
+  />
+
+</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 {
+  careRecordsPage, elderlyServiceOrderDelete, elderlyServiceOrderPage,
+} from "@/api/member/appointment";
+import download from "@/utils/download";
+import { useUserStore } from '@/store/modules/user'
+import {formatToDate, formatToDateTime, getCurrentMonthRange} from "@/utils/dateUtil";
+import * as UserApi from "@/api/system/user";
+import Import from "@/components/ImportFile/index.vue";
+import {ref} from "vue";
+import {getBuildList} from "@/api/system/badManage";
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+const userStore = useUserStore()
+const loading = ref(true) // 列表的加载中
+const detailRef = ref()
+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,
+  elderName: '',
+  elderPhone: '',
+  discoveryTime: ["2025-12-01",formatToDate()],
+  tenantIds: userStore.orgTenantId[0]
+})
+const queryFormRef = ref() // 搜索的表单
+
+const inputH = () => {
+  importRef.value.open(queryParams.tenantIds[0])
+}
+// 打开导出弹窗
+const handleImportCard = async () => {
+  try {
+    const queryParams = reactive({
+      pageNo: 1,
+      pageSize: 1000,
+      tenantIds: userStore.orgTenantId,
+    })
+    const data = await UserApi.exportElderlyServiceOrder(queryParams)
+    download.excel(data, '工单报表数据.xls')
+  }catch (e) {
+
+  }
+
+
+  // exportConfig.value = {
+  //   title: "批量导出",
+  //   batchMin: 1,
+  //   batchMax: 999,
+  //   countMin: 1,
+  //   countMax: 500,
+  //   defaultBatch: 1,
+  //   defaultCount: 500,
+  //   description: [
+  //     '1. 请输入需要导出的数量',
+  //     '2. 一次导不完的话,输入批次 2 再次导出,以此类推。',
+  //     '3. 建议单次导出数量不超过500,以免影响系统性能',
+  //     '4. 导出需要较长时间,请耐心等待。'
+  //   ]
+  // }
+  // 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 (_) {}
+
+}
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    //let queryP = {...queryParams,discoveryTime:queryParams.discoveryTime?[queryParams.discoveryTime[0]+" 00:00:00",queryParams.discoveryTime[1]+" 23:59:59"]:null}
+    const data = await elderlyServiceOrderPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = async () => {
+  if (!queryFormRef.value) return
+  const valid = await queryFormRef.value.validate()
+  if (!valid) return
+  queryParams.pageNo = 1
+  await getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryParams.elderName = ''
+  queryParams.tenantId = userStore.orgTenantId[0]
+  queryParams.discoveryTime= ["2025-12-01",formatToDate()]
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (id?: number) => {
+  // if(queryParams.tenantIds.length == 0 || queryParams.tenantIds.length > 1){
+  //   message.error('新增只能选择一个机构')
+  //   return
+  // }
+  formRef.value.open(queryParams.tenantIds, id,false)
+}
+
+const editRef = ref()
+const openFormEdit = (row: any = {}, id?: number) => {
+  formRef.value.open(row.tenantId, id,false)
+}
+
+
+const openFormDetail = (id?: number) => {
+  formRef.value.open(undefined,id,true)
+}
+
+
+
+
+
+const openClose = async (item) => {
+  try {
+    console.log("任务ID",item)
+    const res = await message.confirm('确定要删除吗?', '提示')
+    if (res == 'confirm') {
+      // 发起
+      try {
+        const res = await elderlyServiceOrderDelete(item.id)
+        if (res){
+          message.success(t('common.updateSuccess'))
+        }
+      }catch(err) {}
+    }
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 取消按钮操作 */
+const cancelDelete = async (id: number) => {
+  try {
+    // 取消的二次确认
+    await message.cancelConfirm()
+    // 发起取消
+    // await elderlyBakDel(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+
+const buildList = ref([])
+const floorList = ref([])
+
+const route = useRoute()
+/** 初始化 **/
+onMounted(async () => {
+  if(route.query && route.query.elderName){
+    queryParams.elderName = route.query.elderName as string
+  }
+  getList()
+  try {
+    buildList.value = await getBuildList({tenantIds: queryParams.tenantId})
+  }catch (e) {}
+})
+
+// 表头格式
+const tableHeaderColor = ({ rowIndex }: any) => {
+  if (rowIndex === 0) {
+    return {
+      backgroundColor: '#f8f8f9',
+      color: '#666666',
+      fontWeight: 'bold'
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss"></style>

+ 875 - 0
src/views/elderly/nursing/records/disinfect/AddForm.vue

@@ -0,0 +1,875 @@
+<template>
+  <el-drawer
+    v-model="dialogVisible"
+    :title="title"
+    resizable
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    :destroy-on-close="true"
+    size="70%"
+    :before-close="handleClosed"
+  >
+
+    <div class="mmse-form">
+      <!-- 公告区域消毒记录 -->
+
+
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" class="row">
+          <text>楼栋</text>
+          <el-select :disabled="isDetail" v-model="dataForm.buildId" placeholder="选择楼栋" style="width: 100%" @change="handleBuildChange">
+            <el-option  v-for="(item,index) in buildList" :key="index" :label="item.buildName" :value="item.id" />
+          </el-select>
+
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" class="row">
+          <text>楼层</text>
+            <el-select :disabled="isDetail" v-model="dataForm.floorId" placeholder="选择楼层" style="width: 100%" @change="handleFloorChange">
+              <el-option v-for="(item,index) in floorList" :key="index" :label="item.floorName" :value="item.id" />
+            </el-select>
+
+        </el-col>
+      </el-row>
+
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>登记人</text>
+          <el-input :disabled="isDetail" v-model="form.assessor"  />
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>登记日期</text>
+          <el-date-picker :disabled="isDetail" v-model="form.assessDate" type="date" style="width: 100%;"/>
+        </el-col>
+      </el-row>
+
+      <!-- 表单内容区域 -->
+      <div class="form-body">
+        <!-- 消毒场所说明 -->
+        <div class="disinfect-location-note">
+          <strong>消毒场所:</strong>
+          <span>1、房间空气</span>
+          <span>2、房间地面、物体表面</span>
+          <span>3、长者生活区域地面公共区域</span>
+          <span>4、长者生活区域扶手、物体表面</span>
+          <span>5、公共区域(注明具体场所)</span>
+        </div>
+
+        <!-- 消毒记录表 -->
+        <div class="disinfect-table">
+          <table class="record-table">
+            <thead>
+              <tr>
+                <th class="col-location">消毒场所</th>
+                <th class="col-method">消毒方式</th>
+                <th class="col-disinfector">消毒人员签名</th>
+                <th class="col-supervisor">监督人员签名</th>
+                <th class="col-remark">备注</th>
+              </tr>
+            </thead>
+            <tbody>
+              <tr v-for="(item, index) in form.records" :key="index">
+                <td>
+                  <el-input v-if="!isDetail" v-model="item.location" placeholder="填写消毒场所" />
+                  <span v-else>{{ item.location }}</span>
+                </td>
+                <td>
+                  <el-input v-if="!isDetail" v-model="item.method" placeholder="消毒方式" />
+                  <span v-else>{{ item.method }}</span>
+                </td>
+                <td>
+                  <el-input v-if="!isDetail" v-model="item.disinfector" placeholder="签名" />
+                  <span v-else>{{ item.disinfector }}</span>
+                </td>
+                <td>
+                  <el-input v-if="!isDetail" v-model="item.supervisor" placeholder="签名" />
+                  <span v-else>{{ item.supervisor }}</span>
+                </td>
+                <td>
+                  <el-input v-if="!isDetail" v-model="item.remark" type="textarea" :rows="1" placeholder="备注" />
+                  <span v-else>{{ item.remark }}</span>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+
+        <!-- 添加/删除行按钮 -->
+        <div class="table-actions" v-if="!isDetail">
+          <el-button type="primary" size="small" @click="addRecord">添加行</el-button>
+          <el-button type="danger" size="small" @click="removeRecord" :disabled="form.records.length <= 1">删除行</el-button>
+        </div>
+
+        <!-- 消毒方式说明 -->
+        <div class="note-section">
+          <div class="note-title">消毒方式说明</div>
+          <div class="note-content">
+            <p><strong>A、日常空气消毒:</strong>紫外线灯照射消毒。紫外线灯照射消毒:在无人条件下开启,每次照射不少于 0.5小时,每天一次。</p>
+            <p><strong>B、日常地面、物体表面消毒:</strong>地面可用含有效氯浓度为250mg/L 的含氯消毒剂拖拭,作用 30 分钟后再用清水拖拭干净。桌椅、窗台、门窗把手、床栏、电器开关、等高频接触的部位可用 250mg/L 的含氯消毒剂擦拭,作用 30 分钟后,再用清水擦拭干净, 每天至少一次。(消毒粉(标识有效氯含量 12%,20 克/包):1 包消毒粉加 4.8 升水;)</p>
+            <p><strong>C、75%乙醇消毒液:</strong>直接使用。</p>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div>前端提交的数据,后端可以参照这个格式:
+      {
+      "buildId": 190,
+      "floorId": 644,
+      "floorName": "2层",
+      "contractNumber": "111",
+      "elderName": "0318",
+      "bedName": "测试楼-2层-201-10",
+      "elderAge": 86,
+      "elderSex": "男",
+      "elderId": 18697,
+      "tenantId": 195,
+      "buildName": "测试楼",
+      "assessData": " ",
+      "assessor": "啊啊啊",
+      "assessDate": "2026-03-27",
+      "orgType": 1
+      }
+    </div>
+
+
+
+    <template #footer>
+      <el-button @click="handleClosed">关闭</el-button>
+      <el-button style="margin-left: 22px;margin-right: 30px" v-loading="formLoading" type="primary" v-show="!isDetail" @click="submitForm">确定</el-button>
+      <el-button v-if="isDetail" type="success" @click="handleExport">打印</el-button>
+    </template>
+
+  </el-drawer>
+</template>
+
+<script lang="ts" setup>
+import { computed, ref } from 'vue'
+
+import dayjs from 'dayjs'
+
+import { disinfectCreate, disinfectGetById, disinfectUpdate } from "@/api/social-work";
+import {getBuildList} from "@/api/system/badManage";
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+const title = ref('')
+const dialogVisible = ref(false) // 弹窗
+const formRef = ref() // 表单 Ref
+const selectElderRef = ref() // 表单 Ref
+const isDetail = ref(false) // 是否详情打开
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+let dataForm = ref({
+  // 表单字段
+  id: undefined,
+  idCard: '',
+  buildId: '',
+  floorId: '',
+  floorName: '',
+  contractNumber: '', //档案号
+  elderName: '',//长者姓名
+  bedName: '', //床位号
+  elderAge: '', //年龄
+  elderSex: '', //性别
+  checkInTime: '', //入院日期
+  elderId: '',
+  tenantId: undefined
+})
+
+
+const buildList = ref([])
+const floorList = ref([])
+const handleBuildChange = (buildId: any) => {
+  const selectedBuild = buildList.value.find((item: any) => item.id === buildId)
+  if (selectedBuild) {
+    dataForm.value.buildName = selectedBuild.buildName
+    floorList.value = selectedBuild.floorList || []
+    // 清空楼层选择
+    dataForm.value.floorId = ''
+    dataForm.value.floorName = ''
+  }
+}
+const handleFloorChange = (floorId: any) => {
+  const selectedFloor = floorList.value.find((item: any) => item.id === floorId)
+  if (selectedFloor) {
+    dataForm.value.floorName = selectedFloor.floorName
+  }
+}
+
+const elderUp = (e) => {
+  dataForm.value.elderName = e.elderName
+  dataForm.value.elderId = e.id
+  dataForm.value.elderSex = e.elderSex === 1 ? '男' : '女'
+  dataForm.value.bedName = e.bedName || ''
+  dataForm.value.checkInTime = e.checkInTime
+  dataForm.value.contractNumber = e.contractNumber
+  dataForm.value.elderAge = e.elderAge
+}
+
+// ========== 感知觉与沟通评估表 表单序列化方法 ==========
+
+// 危险物品登记不需要计算总分,保留计算属性占位
+const totalScore = computed(() => {
+  return 0
+})
+
+
+/** 将表单数据序列化为 JSON 对象 */
+const serializeFormData = () => {
+  return {
+    // 基本信息
+    assessor: form.assessor || '',
+    assessDate: form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : '',
+
+    // 消毒记录列表
+    records: form.records || []
+  }
+}
+
+/** 将 JSON 对象反序列化为表单数据 */
+const deserializeFormData = (formData: Record<string, any>) => {
+  if (!formData) return
+
+  // 基本信息
+  form.assessor = formData.assessor || ''
+  form.assessDate = formData.assessDate ? dayjs(formData.assessDate).toDate() : ''
+
+  // 消毒记录列表
+  if (formData.records && formData.records.length > 0) {
+    form.records = formData.records
+  } else {
+    // 默认至少有一行
+    form.records = [{
+      location: '',
+      method: '',
+      disinfector: '',
+      supervisor: '',
+      remark: ''
+    }]
+  }
+}
+
+/** 重置消毒记录表单数据 */
+const resetPerceptionForm = () => {
+  form.assessor = ''
+  form.assessDate = ''
+
+  // 消毒记录列表 - 默认一行
+  form.records = [{
+    location: '',
+    method: '',
+    disinfector: '',
+    supervisor: '',
+    remark: ''
+  }]
+}
+
+/** 打开弹窗 */
+const open = async (tenantId, id?: any, detail: boolean = false) => {
+  resetForm()
+  dialogVisible.value = true
+  dataForm.value.id = id || undefined
+  dataForm.value.tenantId = tenantId
+  isDetail.value = detail
+  try {
+    buildList.value = await getBuildList({tenantIds: tenantId})
+  }catch (e) {}
+
+  if (id) {
+    title.value = "编辑-消毒记录"
+    // 加载登记数据
+    await loadDangerousGoodsData(id)
+  } else {
+    title.value = "新增-消毒记录"
+
+  }
+}
+
+/** 加载登记数据 */
+const loadDangerousGoodsData = async (id: number) => {
+  try {
+    const res = await disinfectGetById(id)
+    if (res) {
+      // 填充长者基本信息
+      dataForm.value.elderName = res.elderName || ''
+      dataForm.value.elderId = res.elderId || ''
+      dataForm.value.elderSex = res.elderSex || ''
+      dataForm.value.bedName = res.bedName || ''
+      dataForm.value.checkInTime = res.checkInTime || ''
+      dataForm.value.contractNumber = res.fileNumber || ''
+      dataForm.value.elderAge = res.elderAge || ''
+      await selectElderRef.value.upData(res.elderName, res.elderId)
+      // 解析 assessData
+      if (res.assessData) {
+        const formData = JSON.parse(res.assessData)
+        deserializeFormData(formData)
+      }
+    }
+  } catch (error) {
+    message.error('加载消毒记录数据失败')
+  }
+}
+
+
+
+const form = reactive({
+  // 基本信息
+  assessor: '',
+  assessDate: '',
+
+  // 消毒记录列表
+  records: [
+    {
+      location: '',      // 消毒场所
+      method: '',        // 消毒方式
+      disinfector: '',   // 消毒人员签名
+      supervisor: '',    // 监督人员签名
+      remark: ''         // 备注
+    }
+  ]
+})
+
+// 添加消毒记录行
+const addRecord = () => {
+  form.records.push({
+    location: '',
+    method: '',
+    disinfector: '',
+    supervisor: '',
+    remark: ''
+  })
+}
+
+// 删除最后一行消毒记录
+const removeRecord = () => {
+  if (form.records.length > 1) {
+    form.records.pop()
+  }
+}
+
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  if (formLoading.value) {
+    return
+  }
+  formLoading.value = true
+  // 提交请求
+    try {
+      const assessData = serializeFormData()
+      const tempParams = {
+        ...dataForm.value,
+        assessData: JSON.stringify(assessData),
+        assessor: form.assessor,
+        assessDate: form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : ''
+      }
+
+    if (dataForm.value.id) {
+      const res = await disinfectUpdate(tempParams)
+      if (res) {
+        message.success(t('common.updateSuccess'))
+        dialogVisible.value = false
+        // 发送操作成功的事件
+        emit('success')
+      }
+    } else {
+      const res = await disinfectCreate(tempParams)
+      if (res) {
+        message.success(t('common.createSuccess'))
+        dialogVisible.value = false
+        // 发送操作成功的事件
+        emit('success')
+      }
+    }
+  } finally {
+    setTimeout(() => {
+      formLoading.value = false
+    }, 500)
+  }
+}
+
+
+
+/** 重置表单 */
+const resetForm = () => {
+  dataForm.value = {
+    id: undefined,
+    idCard: '',
+    buildId: '',
+    floorId: '',
+    floorName: '',
+    contractNumber: '', //档案号
+    elderName: '',//长者姓名
+    bedName: '', //床位号
+    elderAge: '', //年龄
+    elderSex: '', //性别
+    checkInTime: '', //入院日期
+    elderId: '',
+    tenantId: undefined
+  }
+  formRef.value?.resetFields()
+
+  // 重置感知觉与沟通评估表表单
+  resetPerceptionForm()
+}
+
+// 关闭表单
+const handleClosed = () => {
+  dialogVisible.value = false
+  resetForm()
+}
+
+
+
+</script>
+
+<style scoped lang="scss">
+.mmse-form {
+  max-width: 1200px;
+  margin: 0 auto;
+  background: #fff;
+
+  .form-title {
+    text-align: center;
+    font-size: 24px;
+    font-weight: bold;
+    margin-bottom: 20px;
+  }
+
+
+
+  .info-row {
+    display: flex;
+    gap: 40px;
+    width: 100%;
+    flex-direction: row;
+    align-items: center;
+    margin-bottom: 10px;
+
+    .info-item {
+      display: flex;
+      align-items: center;
+      gap: 8px;
+
+      .label {
+        width: 82px;
+        text-align: right;
+        margin-right: 4px;
+        white-space: nowrap;
+      }
+    }
+  }
+
+
+  .form-body {
+    border: 1px solid #333;
+    padding: 15px;
+
+    .disinfect-location-note {
+      margin-bottom: 15px;
+      padding: 10px;
+      background: #f5f7fa;
+      border-radius: 4px;
+      font-size: 13px;
+
+      strong {
+        margin-right: 10px;
+      }
+
+      span {
+        margin-right: 20px;
+      }
+    }
+
+    .disinfect-table {
+      margin-bottom: 15px;
+
+      .record-table {
+        width: 100%;
+        border-collapse: collapse;
+        border: 1px solid #333;
+
+        th, td {
+          border: 1px solid #333;
+          padding: 8px;
+          text-align: center;
+          vertical-align: middle;
+        }
+
+        th {
+          background: #f5f7fa;
+          font-weight: bold;
+          font-size: 14px;
+        }
+
+        .col-location {
+          width: 25%;
+        }
+
+        .col-method {
+          width: 20%;
+        }
+
+        .col-disinfector {
+          width: 15%;
+        }
+
+        .col-supervisor {
+          width: 15%;
+        }
+
+        .col-remark {
+          width: 25%;
+        }
+
+        tbody {
+          tr {
+            height: 45px;
+          }
+
+          td {
+            .el-input, .el-select {
+              width: 100%;
+            }
+
+            .el-textarea {
+              width: 100%;
+            }
+          }
+        }
+      }
+    }
+
+    .table-actions {
+      margin-bottom: 20px;
+      text-align: center;
+    }
+  }
+
+  .section {
+    margin-bottom: 20px;
+
+    &:last-child {
+      margin-bottom: 0;
+    }
+
+    .section-title {
+      font-weight: bold;
+      margin-bottom: 10px;
+    }
+  }
+
+  .form-item {
+    display: flex;
+    align-items: center;
+    margin-bottom: 12px;
+    flex-wrap: wrap;
+    gap: 8px;
+
+    .item-number {
+      font-weight: bold;
+      min-width: 25px;
+    }
+
+    .item-label {
+      white-space: nowrap;
+      min-width: fit-content;
+    }
+
+  }
+
+  .other-input {
+    width: 200px;
+    margin-left: 10px;
+  }
+
+  // 调整 Element Plus 组件样式
+  :deep(.el-input__inner) {
+    height: 28px;
+    line-height: 28px;
+    border-top: none;
+    border-left: none;
+    border-right: none;
+    border-radius: 0;
+    padding: 0 4px;
+
+    &:focus {
+      border-color: #409eff;
+    }
+  }
+
+
+  :deep(.el-checkbox__label),
+  :deep(.el-radio__label) {
+    padding-left: 4px;
+  }
+}
+.row{
+  margin-bottom: 12px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  text{
+    text-align: right;
+    margin-right: 4px;
+    width: 82px;
+  }
+}
+
+// 感知觉与沟通评估表 特有样式
+.total-score-section {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  margin-bottom: 20px;
+
+  .total-score {
+    display: flex;
+    align-items: baseline;
+    gap: 4px;
+
+    .score-label {
+      font-size: 16px;
+      font-weight: bold;
+    }
+
+    .score-value {
+      font-size: 28px;
+      font-weight: bold;
+      color: #409eff;
+    }
+
+    .score-max {
+      font-size: 14px;
+      color: #909399;
+    }
+  }
+
+  .risk-level {
+    font-size: 16px;
+    font-weight: bold;
+    padding: 8px 16px;
+    border-radius: 4px;
+
+    &.risk-none {
+      color: #67c23a;
+      background: #f0f9eb;
+    }
+
+    &.risk-low {
+      color: #e6a23c;
+      background: #fdf6ec;
+    }
+
+    &.risk-medium {
+      color: #f56c6c;
+      background: #fef0f0;
+    }
+
+    &.risk-high {
+      color: #f56c6c;
+      background: #fef0f0;
+      border: 1px solid #f56c6c;
+    }
+  }
+}
+
+.assessment-table {
+  width: 100%;
+  border-collapse: collapse;
+  margin-bottom: 20px;
+
+  table {
+    width: 100%;
+    border: 1px solid #333;
+
+    th, td {
+      border: 1px solid #333;
+      padding: 12px;
+      text-align: left;
+    }
+
+    th {
+      background: #f5f7fa;
+      font-weight: bold;
+      text-align: center;
+    }
+
+    .criteria-col {
+      width: 60%;
+    }
+
+    .score-col {
+      width: 15%;
+      text-align: center;
+    }
+
+    .select-col {
+      width: 25%;
+      text-align: center;
+    }
+
+    .criteria {
+      text-align: left;
+    }
+
+    .score {
+      text-align: center;
+      font-weight: bold;
+    }
+
+    .select {
+      text-align: center;
+
+      :deep(.el-radio) {
+        margin-right: 0;
+      }
+    }
+  }
+}
+
+.remark-section {
+  margin: 15px 0;
+  padding: 12px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .remark-label {
+    font-weight: bold;
+    color: #606266;
+  }
+
+  .remark-text {
+    color: #606266;
+  }
+}
+
+.risk-judgment-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .risk-judgment-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .risk-options {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20px;
+
+    :deep(.el-radio) {
+      margin-right: 0;
+    }
+  }
+}
+
+.preventive-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .preventive-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .preventive-options {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 15px;
+
+    :deep(.el-checkbox) {
+      margin-right: 20px;
+      margin-bottom: 8px;
+    }
+
+    .other-input {
+      width: 200px;
+      margin-left: 10px;
+    }
+  }
+}
+
+.signature-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .signature-row {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    gap: 20px;
+  }
+
+  .signature-item {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+
+    &.date-item {
+      :deep(.el-date-picker) {
+        width: 150px;
+      }
+    }
+  }
+
+  .signature-label {
+    font-weight: bold;
+    white-space: nowrap;
+  }
+
+  .signature-input {
+    width: 150px;
+  }
+
+  .date-picker {
+    width: 150px;
+  }
+}
+
+.note-section {
+  margin-top: 20px;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .note-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .note-content {
+    font-size: 13px;
+    line-height: 1.8;
+    color: #606266;
+
+    p {
+      margin: 5px 0;
+    }
+
+    .indent {
+      margin-left: 20px;
+    }
+  }
+}
+</style>

+ 383 - 0
src/views/elderly/nursing/records/disinfect/index.vue

@@ -0,0 +1,383 @@
+<template>
+  <ContentWrap>
+    <!-- 工单记录 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="110px"
+    >
+
+
+      <el-form-item label="楼栋">
+        <el-select v-model="queryParams.buidId" placeholder="选择楼栋" style="width: 180px" @change="handleBuildChange">
+          <el-option v-for="(item,index) in buildList" :key="index" :label="item.buildName" :value="item.id" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="楼层">
+        <el-select  v-model="queryParams.floorId" placeholder="选择楼层" style="width: 180px" >
+          <el-option v-for="(item,index) in floorList" :key="index" :label="item.floorName" :value="item.id" />
+        </el-select>
+      </el-form-item>
+
+
+      <el-form-item label="登记日期">
+        <el-date-picker
+          size="default"
+          ref="selectRef"
+          class="!w-240px"
+          v-model="queryParams.discoveryTime"
+          type="daterange"
+          :clearable="true"
+          :editable="false"
+          placeholder="选择工单日期"
+          value-format="YYYY-MM-DD"
+          format="YYYY-MM-DD"
+          date-format="YYYY-MM-DD"
+        />
+      </el-form-item>
+
+      <el-form-item>
+        <el-button @click="handleQuery" style="margin-left: 2vw"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <div class="mb-10px">
+
+      <ButtonAdd @click="openForm(undefined)"  />
+      <el-button @click="inputH" type="success"><Icon icon="fa:cloud-upload" :size="16" class="mr-1"/>导入</el-button>
+      <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">
+        <template #default="scope">
+          {{
+            scope.$index + (queryParams.pageNo * queryParams.pageSize - queryParams.pageSize) + 1
+          }}
+        </template>
+      </el-table-column>
+
+
+      <el-table-column prop="elderName" header-align="center" align="center" label="长者姓名" min-width="120" show-overflow-tooltip/>
+      <el-table-column prop="elderSex" header-align="center" align="center" label="性别" min-width="90" show-overflow-tooltip/>
+      <el-table-column prop="elderAge" header-align="center" align="center" label="年龄" min-width="90" show-overflow-tooltip/>
+      <el-table-column prop="serviceItem" header-align="center" align="center" label="服务项目" min-width="200" show-overflow-tooltip/>
+      <el-table-column prop="serviceName" header-align="center" align="center" label="服务人员姓名" min-width="160" show-overflow-tooltip/>
+      <el-table-column prop="orderTime" header-align="center" align="center" label="订单时间" min-width="180" show-overflow-tooltip>
+        <template #default="scope">
+          {{(formatToDateTime(scope.row.orderTime))}}
+        </template>
+      </el-table-column>
+      <el-table-column prop="comeTime" header-align="center" align="center" label="上门时间" min-width="180" show-overflow-tooltip>
+        <template #default="scope">
+          {{formatToDateTime(scope.row.serviceBeginTime)}}
+        </template>
+      </el-table-column>
+      <el-table-column prop="elderAddress" header-align="center" align="center" label="地址" min-width="220" show-overflow-tooltip/>
+      <el-table-column prop="isExpire" header-align="center" align="center" label="是否过期" min-width="120" show-overflow-tooltip/>
+      <el-table-column prop="orderStatus" header-align="center" align="center" label="订单状态" min-width="160" show-overflow-tooltip/>
+
+      <el-table-column label="操作" align="center" width="200" fixed="right">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openFormEdit(scope.row, scope.row.id)"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="warning"
+            @click="openFormDetail(scope.row.id)"
+          >
+            详情
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="openClose(scope.row)"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </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"
+  />
+
+
+  <Import
+    ref="importRef"
+    @success="getList"
+    :config="{
+      title: '导入',
+      downloadUrl: 'elderly-service-order/get-import-template',
+      excelTempName: '居家工单-【导入】模板',
+      importUrl: '/elderly-service-order/import',
+      failExportUrl: '',
+    }"
+  />
+
+</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 {
+  careRecordsPage, elderlyServiceOrderDelete, elderlyServiceOrderPage,
+} from "@/api/member/appointment";
+import download from "@/utils/download";
+import { useUserStore } from '@/store/modules/user'
+import {formatToDate, formatToDateTime, getCurrentMonthRange} from "@/utils/dateUtil";
+import * as UserApi from "@/api/system/user";
+import Import from "@/components/ImportFile/index.vue";
+import {ref} from "vue";
+import {getBuildList} from "@/api/system/badManage";
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+const userStore = useUserStore()
+const loading = ref(true) // 列表的加载中
+const detailRef = ref()
+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,
+  elderName: '',
+  elderPhone: '',
+  discoveryTime: ["2025-12-01",formatToDate()],
+  tenantIds: userStore.orgTenantId[0]
+})
+const queryFormRef = ref() // 搜索的表单
+
+const inputH = () => {
+  importRef.value.open(queryParams.tenantIds[0])
+}
+// 打开导出弹窗
+const handleImportCard = async () => {
+  try {
+    const queryParams = reactive({
+      pageNo: 1,
+      pageSize: 1000,
+      tenantIds: userStore.orgTenantId,
+    })
+    const data = await UserApi.exportElderlyServiceOrder(queryParams)
+    download.excel(data, '工单报表数据.xls')
+  }catch (e) {
+
+  }
+
+
+  // exportConfig.value = {
+  //   title: "批量导出",
+  //   batchMin: 1,
+  //   batchMax: 999,
+  //   countMin: 1,
+  //   countMax: 500,
+  //   defaultBatch: 1,
+  //   defaultCount: 500,
+  //   description: [
+  //     '1. 请输入需要导出的数量',
+  //     '2. 一次导不完的话,输入批次 2 再次导出,以此类推。',
+  //     '3. 建议单次导出数量不超过500,以免影响系统性能',
+  //     '4. 导出需要较长时间,请耐心等待。'
+  //   ]
+  // }
+  // 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 (_) {}
+
+}
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    //let queryP = {...queryParams,discoveryTime:queryParams.discoveryTime?[queryParams.discoveryTime[0]+" 00:00:00",queryParams.discoveryTime[1]+" 23:59:59"]:null}
+    const data = await elderlyServiceOrderPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = async () => {
+  if (!queryFormRef.value) return
+  const valid = await queryFormRef.value.validate()
+  if (!valid) return
+  queryParams.pageNo = 1
+  await getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryParams.elderName = ''
+  queryParams.tenantId = userStore.orgTenantId[0]
+  queryParams.discoveryTime= ["2025-12-01",formatToDate()]
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (id?: number) => {
+  // if(queryParams.tenantIds.length == 0 || queryParams.tenantIds.length > 1){
+  //   message.error('新增只能选择一个机构')
+  //   return
+  // }
+  formRef.value.open(queryParams.tenantIds, id,false)
+}
+
+const editRef = ref()
+const openFormEdit = (row: any = {}, id?: number) => {
+  formRef.value.open(row.tenantId, id,false)
+}
+
+
+const openFormDetail = (id?: number) => {
+  formRef.value.open(undefined,id,true)
+}
+
+
+
+
+
+const openClose = async (item) => {
+  try {
+    console.log("任务ID",item)
+    const res = await message.confirm('确定要删除吗?', '提示')
+    if (res == 'confirm') {
+      // 发起
+      try {
+        const res = await elderlyServiceOrderDelete(item.id)
+        if (res){
+          message.success(t('common.updateSuccess'))
+        }
+      }catch(err) {}
+    }
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 取消按钮操作 */
+const cancelDelete = async (id: number) => {
+  try {
+    // 取消的二次确认
+    await message.cancelConfirm()
+    // 发起取消
+    // await elderlyBakDel(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+
+const buildList = ref([])
+const floorList = ref([])
+
+const route = useRoute()
+/** 初始化 **/
+onMounted(async () => {
+  if(route.query && route.query.elderName){
+    queryParams.elderName = route.query.elderName as string
+  }
+  getList()
+  try {
+    buildList.value = await getBuildList({tenantIds: queryParams.tenantId})
+  }catch (e) {}
+})
+
+// 表头格式
+const tableHeaderColor = ({ rowIndex }: any) => {
+  if (rowIndex === 0) {
+    return {
+      backgroundColor: '#f8f8f9',
+      color: '#666666',
+      fontWeight: 'bold'
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss"></style>

+ 1069 - 0
src/views/elderly/nursing/records/dustman/AddForm.vue

@@ -0,0 +1,1069 @@
+<template>
+  <el-drawer
+    v-model="dialogVisible"
+    :title="title"
+    resizable
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    :destroy-on-close="true"
+    size="80%"
+    :before-close="handleClosed"
+  >
+
+    <div class="mmse-form">
+      <!-- 日常清洁 -->
+
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" class="row">
+          <text>楼栋</text>
+          <el-select :disabled="isDetail" v-model="dataForm.buildId" placeholder="选择楼栋" style="width: 100%" @change="handleBuildChange">
+            <el-option  v-for="(item,index) in buildList" :key="index" :label="item.buildName" :value="item.id" />
+          </el-select>
+
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" class="row">
+          <text>楼层</text>
+            <el-select :disabled="isDetail" v-model="dataForm.floorId" placeholder="选择楼层" style="width: 100%" @change="handleFloorChange">
+              <el-option v-for="(item,index) in floorList" :key="index" :label="item.floorName" :value="item.id" />
+            </el-select>
+
+        </el-col>
+      </el-row>
+
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>登记人</text>
+          <el-input :disabled="isDetail" v-model="form.assessor"  />
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>登记月份</text>
+          <el-date-picker :disabled="isDetail" v-model="form.assessDate" type="month" style="width: 100%;"/>
+        </el-col>
+      </el-row>
+
+      <!-- 表单内容区域 -->
+      <div class="form-body">
+        <!-- 日常清洁消毒记录表 -->
+        <div class="cleaning-table-wrapper">
+          <table class="cleaning-table">
+            <thead>
+              <tr>
+                <th rowspan="2" class="col-date">日期</th>
+                <th colspan="6" class="col-category">日用品</th>
+                <th colspan="5" class="col-category">清洁用具</th>
+                <th colspan="3" class="col-category">便器</th>
+                <th rowspan="2" class="col-sign">执行人<br/>签名</th>
+                <th rowspan="2" class="col-remark">备注</th>
+              </tr>
+              <tr>
+                <!-- 日用品 -->
+                <th class="col-item">口杯</th>
+                <th class="col-item">毛巾</th>
+                <th class="col-item">浴巾</th>
+                <th class="col-item">脸盆<br/>足盆</th>
+                <th class="col-item">吐泻物<br/>容器</th>
+                <th class="col-item">痰盂<br/>(杯)</th>
+                <!-- 清洁用具 -->
+                <th class="col-item">抹布</th>
+                <th class="col-item">扫把</th>
+                <th class="col-item">拖把</th>
+                <th class="col-item">清洁<br/>盛器</th>
+                <th class="col-item">马桶刷</th>
+                <!-- 便器 -->
+                <th class="col-item">便盆</th>
+                <th class="col-item">坐便椅</th>
+                <th class="col-item">尿壶</th>
+              </tr>
+              <tr class="freq-row">
+                <th class="col-date">频率</th>
+                <!-- 日用品频率 -->
+                <th class="col-freq">每天1次</th>
+                <th class="col-freq">每天1次</th>
+                <th class="col-freq">每周1次</th>
+                <th class="col-freq">每周1次</th>
+                <th class="col-freq">需要时</th>
+                <th class="col-freq">需要时</th>
+                <!-- 清洁用具频率 -->
+                <th class="col-freq">每天1次</th>
+                <th class="col-freq">每天1次</th>
+                <th class="col-freq">每天1次</th>
+                <th class="col-freq">每天1次</th>
+                <th class="col-freq">每天1次</th>
+                <!-- 便器频率 -->
+                <th class="col-freq">每天1次</th>
+                <th class="col-freq">每天1次</th>
+                <th class="col-freq">每天1次</th>
+                <th class="col-freq">-</th>
+                <th class="col-freq">-</th>
+              </tr>
+            </thead>
+            <tbody>
+              <tr v-for="day in 31" :key="day">
+                <td class="day-cell">{{ day }}</td>
+                <!-- 日用品 -->
+                <td>
+                  <select v-if="!isDetail" v-model="form.records[day-1].cup" class="native-select">
+                    <option value="">--</option>
+                    <option value="已完成">已完成</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.records[day-1].cup || '--' }}</span>
+                </td>
+                <td>
+                  <select v-if="!isDetail" v-model="form.records[day-1].towel" class="native-select">
+                    <option value="">--</option>
+                    <option value="已完成">已完成</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.records[day-1].towel || '--' }}</span>
+                </td>
+                <td>
+                  <select v-if="!isDetail" v-model="form.records[day-1].bathTowel" class="native-select">
+                    <option value="">--</option>
+                    <option value="已完成">已完成</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.records[day-1].bathTowel || '--' }}</span>
+                </td>
+                <td>
+                  <select v-if="!isDetail" v-model="form.records[day-1].basin" class="native-select">
+                    <option value="">--</option>
+                    <option value="已完成">已完成</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.records[day-1].basin || '--' }}</span>
+                </td>
+                <td>
+                  <select v-if="!isDetail" v-model="form.records[day-1].vomitContainer" class="native-select">
+                    <option value="">--</option>
+                    <option value="已完成">已完成</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.records[day-1].vomitContainer || '--' }}</span>
+                </td>
+                <td>
+                  <select v-if="!isDetail" v-model="form.records[day-1].spittoon" class="native-select">
+                    <option value="">--</option>
+                    <option value="已完成">已完成</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.records[day-1].spittoon || '--' }}</span>
+                </td>
+                <!-- 清洁用具 -->
+                <td>
+                  <select v-if="!isDetail" v-model="form.records[day-1].rag" class="native-select">
+                    <option value="">--</option>
+                    <option value="已完成">已完成</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.records[day-1].rag || '--' }}</span>
+                </td>
+                <td>
+                  <select v-if="!isDetail" v-model="form.records[day-1].broom" class="native-select">
+                    <option value="">--</option>
+                    <option value="已完成">已完成</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.records[day-1].broom || '--' }}</span>
+                </td>
+                <td>
+                  <select v-if="!isDetail" v-model="form.records[day-1].mop" class="native-select">
+                    <option value="">--</option>
+                    <option value="已完成">已完成</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.records[day-1].mop || '--' }}</span>
+                </td>
+                <td>
+                  <select v-if="!isDetail" v-model="form.records[day-1].cleaningContainer" class="native-select">
+                    <option value="">--</option>
+                    <option value="已完成">已完成</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.records[day-1].cleaningContainer || '--' }}</span>
+                </td>
+                <td>
+                  <select v-if="!isDetail" v-model="form.records[day-1].toiletBrush" class="native-select">
+                    <option value="">--</option>
+                    <option value="已完成">已完成</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.records[day-1].toiletBrush || '--' }}</span>
+                </td>
+                <!-- 便器 -->
+                <td>
+                  <select v-if="!isDetail" v-model="form.records[day-1].bedPan" class="native-select">
+                    <option value="">--</option>
+                    <option value="已完成">已完成</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.records[day-1].bedPan || '--' }}</span>
+                </td>
+                <td>
+                  <select v-if="!isDetail" v-model="form.records[day-1].commode" class="native-select">
+                    <option value="">--</option>
+                    <option value="已完成">已完成</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.records[day-1].commode || '--' }}</span>
+                </td>
+                <td>
+                  <select v-if="!isDetail" v-model="form.records[day-1].urinal" class="native-select">
+                    <option value="">--</option>
+                    <option value="已完成">已完成</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.records[day-1].urinal || '--' }}</span>
+                </td>
+                <!-- 签名和备注 -->
+                <td>
+                  <el-input v-if="!isDetail" v-model="form.records[day-1].signature" size="small" placeholder="签名" />
+                  <span v-else>{{ form.records[day-1].signature }}</span>
+                </td>
+                <td>
+                  <el-input v-if="!isDetail" v-model="form.records[day-1].remark" size="small" placeholder="备注" />
+                  <span v-else>{{ form.records[day-1].remark }}</span>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+
+        <!-- 备注说明 -->
+        <div class="note-section">
+          <div class="note-title">备注说明</div>
+          <div class="note-content">
+            <p>1. 口杯、毛巾、浴巾、脸盆、足盆用250 mg/L有效氯消毒液浸泡30分钟后,用流动水冲净晾干备用。</p>
+            <p>2. 盛装吐泻物的容器、痰盂(杯)每次使用后消毒,用500 mg/L有效氯消毒液完全浸没,浸泡30分钟后用流动水冲净备用。</p>
+            <p>3. 清洁用具抹布、扫把、拖把、清洁盛器、马桶刷500mg/L有效氯消毒液浸泡30分钟后用流动水冲净晾干备用。</p>
+            <p>4. 专用便器消毒频率为每周一次,公用便器每次使用后消毒。用1000 mg/L有效氯消毒液完全浸没,浸泡30分钟后用流动水冲净备用。</p>
+            <p>5. 执行操作后"已完成"记录并签名。</p>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div>前端提交的数据,后端可以参照这个格式:
+      {
+      "buildId": 190,
+      "floorId": 644,
+      "floorName": "2层",
+      "bedName": "测试楼-2层-201-10",
+      "tenantId": 195,
+      "buildName": "测试楼",
+      "assessData": " ",
+      "assessor": "啊啊啊",
+      "assessDate": "2026-03-27",
+      "orgType": 1
+      }
+    </div>
+
+
+
+    <template #footer>
+      <el-button @click="handleClosed">关闭</el-button>
+      <el-button style="margin-left: 22px;margin-right: 30px" v-loading="formLoading" type="primary" v-show="!isDetail" @click="submitForm">确定</el-button>
+      <el-button v-if="isDetail" type="success" @click="handleExport">打印</el-button>
+    </template>
+
+  </el-drawer>
+</template>
+
+<script lang="ts" setup>
+import { computed, ref } from 'vue'
+
+import dayjs from 'dayjs'
+
+import { cleaningRecordCreate, cleaningRecordGetById, cleaningRecordUpdate } from "@/api/social-work";
+import {getBuildList} from "@/api/system/badManage";
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+const title = ref('')
+const dialogVisible = ref(false) // 弹窗
+const formRef = ref() // 表单 Ref
+const selectElderRef = ref() // 表单 Ref
+const isDetail = ref(false) // 是否详情打开
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+let dataForm = ref({
+  // 表单字段
+  id: undefined,
+  idCard: '',
+  buildId: '',
+  floorId: '',
+  floorName: '',
+  contractNumber: '', //档案号
+  elderName: '',//长者姓名
+  bedName: '', //床位号
+  elderAge: '', //年龄
+  elderSex: '', //性别
+  checkInTime: '', //入院日期
+  elderId: '',
+  tenantId: undefined
+})
+
+
+const buildList = ref([])
+const floorList = ref([])
+const handleBuildChange = (buildId: any) => {
+  const selectedBuild = buildList.value.find((item: any) => item.id === buildId)
+  if (selectedBuild) {
+    dataForm.value.buildName = selectedBuild.buildName
+    floorList.value = selectedBuild.floorList || []
+    // 清空楼层选择
+    dataForm.value.floorId = ''
+    dataForm.value.floorName = ''
+  }
+}
+const handleFloorChange = (floorId: any) => {
+  const selectedFloor = floorList.value.find((item: any) => item.id === floorId)
+  if (selectedFloor) {
+    dataForm.value.floorName = selectedFloor.floorName
+  }
+}
+
+const elderUp = (e) => {
+  dataForm.value.elderName = e.elderName
+  dataForm.value.elderId = e.id
+  dataForm.value.elderSex = e.elderSex === 1 ? '男' : '女'
+  dataForm.value.bedName = e.bedName || ''
+  dataForm.value.checkInTime = e.checkInTime
+  dataForm.value.contractNumber = e.contractNumber
+  dataForm.value.elderAge = e.elderAge
+}
+
+// ========== 感知觉与沟通评估表 表单序列化方法 ==========
+
+// 危险物品登记不需要计算总分,保留计算属性占位
+const totalScore = computed(() => {
+  return 0
+})
+
+
+/** 将表单数据序列化为 JSON 对象 */
+const serializeFormData = () => {
+  return {
+    // 基本信息
+    assessor: form.assessor || '',
+    assessDate: form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : '',
+
+    // 31天清洁记录
+    records: form.records || []
+  }
+}
+
+/** 将 JSON 对象反序列化为表单数据 */
+const deserializeFormData = (formData: Record<string, any>) => {
+  if (!formData) return
+
+  // 基本信息
+  form.assessor = formData.assessor || ''
+  form.assessDate = formData.assessDate ? dayjs(formData.assessDate).toDate() : ''
+
+  // 31天清洁记录
+  if (formData.records && formData.records.length > 0) {
+    form.records = formData.records
+  } else {
+    form.records = generate31DaysRecords()
+  }
+}
+
+/** 重置日常清洁消毒记录表表单数据 */
+const resetPerceptionForm = () => {
+  form.assessor = ''
+  form.assessDate = ''
+
+  // 重置31天清洁记录
+  form.records = generate31DaysRecords()
+}
+
+/** 打开弹窗 */
+const open = async (tenantId, id?: any, detail: boolean = false) => {
+  resetForm()
+  dialogVisible.value = true
+  dataForm.value.id = id || undefined
+  dataForm.value.tenantId = tenantId
+  isDetail.value = detail
+  try {
+    buildList.value = await getBuildList({tenantIds: tenantId})
+  }catch (e) {}
+
+  if (id) {
+    title.value = "编辑-日常清洁消毒记录"
+    // 加载登记数据
+    await loadDangerousGoodsData(id)
+  } else {
+    title.value = "新增-日常清洁消毒记录"
+
+  }
+}
+
+/** 加载登记数据 */
+const loadDangerousGoodsData = async (id: number) => {
+  try {
+    const res = await cleaningRecordGetById(id)
+    if (res) {
+      // 填充长者基本信息
+      dataForm.value.elderName = res.elderName || ''
+      dataForm.value.elderId = res.elderId || ''
+      dataForm.value.elderSex = res.elderSex || ''
+      dataForm.value.bedName = res.bedName || ''
+      dataForm.value.checkInTime = res.checkInTime || ''
+      dataForm.value.contractNumber = res.fileNumber || ''
+      dataForm.value.elderAge = res.elderAge || ''
+      await selectElderRef.value.upData(res.elderName, res.elderId)
+      // 解析 assessData
+      if (res.assessData) {
+        const formData = JSON.parse(res.assessData)
+        deserializeFormData(formData)
+      }
+    }
+  } catch (error) {
+    message.error('加载日常清洁消毒记录数据失败')
+  }
+}
+
+
+
+// 生成31天的记录
+const generate31DaysRecords = () => {
+  return Array.from({ length: 31 }, () => ({
+    // 日用品
+    cup: '',              // 口杯
+    towel: '',            // 毛巾
+    bathTowel: '',        // 浴巾
+    basin: '',            // 脸盆足盆
+    vomitContainer: '',   // 吐泻物容器
+    spittoon: '',         // 痰盂(杯)
+    // 清洁用具
+    rag: '',              // 抹布
+    broom: '',            // 扫把
+    mop: '',              // 拖把
+    cleaningContainer: '', // 清洁盛器
+    toiletBrush: '',      // 马桶刷
+    // 便器
+    bedPan: '',           // 便盆
+    commode: '',          // 坐便椅
+    urinal: '',           // 尿壶
+    // 签名和备注
+    signature: '',        // 执行人签名
+    remark: ''            // 备注
+  }))
+}
+
+const form = reactive({
+  // 基本信息
+  assessor: '',
+  assessDate: '',
+
+  // 31天清洁记录
+  records: generate31DaysRecords()
+})
+
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  if (formLoading.value) {
+    return
+  }
+  formLoading.value = true
+  // 提交请求
+    try {
+      const assessData = serializeFormData()
+      const tempParams = {
+        ...dataForm.value,
+        assessData: JSON.stringify(assessData),
+        assessor: form.assessor,
+        assessDate: form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : ''
+      }
+
+    if (dataForm.value.id) {
+      const res = await cleaningRecordUpdate(tempParams)
+      if (res) {
+        message.success(t('common.updateSuccess'))
+        dialogVisible.value = false
+        // 发送操作成功的事件
+        emit('success')
+      }
+    } else {
+      const res = await cleaningRecordCreate(tempParams)
+      if (res) {
+        message.success(t('common.createSuccess'))
+        dialogVisible.value = false
+        // 发送操作成功的事件
+        emit('success')
+      }
+    }
+  } finally {
+    setTimeout(() => {
+      formLoading.value = false
+    }, 500)
+  }
+}
+
+
+
+/** 重置表单 */
+const resetForm = () => {
+  dataForm.value = {
+    id: undefined,
+    idCard: '',
+    buildId: '',
+    floorId: '',
+    floorName: '',
+    contractNumber: '', //档案号
+    elderName: '',//长者姓名
+    bedName: '', //床位号
+    elderAge: '', //年龄
+    elderSex: '', //性别
+    checkInTime: '', //入院日期
+    elderId: '',
+    tenantId: undefined
+  }
+  formRef.value?.resetFields()
+
+  // 重置感知觉与沟通评估表表单
+  resetPerceptionForm()
+}
+
+// 关闭表单
+const handleClosed = () => {
+  dialogVisible.value = false
+  resetForm()
+}
+
+
+
+</script>
+
+<style scoped lang="scss">
+.mmse-form {
+  margin: 0 auto;
+  background: #fff;
+
+  .form-title {
+    text-align: center;
+    font-size: 24px;
+    font-weight: bold;
+    margin-bottom: 20px;
+  }
+
+
+
+  .info-row {
+    display: flex;
+    gap: 40px;
+    width: 100%;
+    flex-direction: row;
+    align-items: center;
+    margin-bottom: 10px;
+
+    .info-item {
+      display: flex;
+      align-items: center;
+      gap: 8px;
+
+      .label {
+        width: 82px;
+        text-align: right;
+        margin-right: 4px;
+        white-space: nowrap;
+      }
+    }
+  }
+
+
+  .form-body {
+    border: 1px solid #333;
+    padding: 15px;
+
+    .cleaning-table-wrapper {
+      overflow-x: auto;
+      margin-bottom: 20px;
+
+      .cleaning-table {
+        min-width: 1400px;
+        border-collapse: collapse;
+        border: 1px solid #333;
+
+        th, td {
+          border: 1px solid #333;
+          padding: 4px 2px;
+          text-align: center;
+          vertical-align: middle;
+        }
+
+        th {
+          background: #f5f7fa;
+          font-weight: bold;
+          font-size: 12px;
+        }
+
+        .col-date {
+          width: 50px;
+          min-width: 50px;
+        }
+
+        .col-category {
+          background: #e8f4f8;
+          font-size: 12px;
+        }
+
+        .col-item {
+          width: 55px;
+          min-width: 55px;
+          font-size: 11px;
+        }
+
+        .col-freq {
+          font-size: 10px;
+          color: #666;
+          font-weight: normal;
+        }
+
+        .col-sign {
+          width: 80px;
+          min-width: 80px;
+        }
+
+        .col-remark {
+          width: 100px;
+          min-width: 100px;
+        }
+
+        .day-cell {
+          font-weight: bold;
+          background: #f5f7fa;
+        }
+
+        .freq-row {
+          th {
+            background: #fffbe6;
+          }
+        }
+
+        tbody {
+          tr {
+            height: 36px;
+          }
+
+          td {
+            .native-select {
+              width: 100%;
+              height: 24px;
+              padding: 0 16px 0 2px;
+              font-size: 11px;
+              border: 1px solid #dcdfe6;
+              border-radius: 3px;
+              background-color: #fff;
+              text-align: center;
+              cursor: pointer;
+              appearance: none;
+              background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
+              background-repeat: no-repeat;
+              background-position: right 2px center;
+              background-size: 12px;
+
+              &:focus {
+                border-color: #409eff;
+                outline: none;
+              }
+
+              option {
+                font-size: 12px;
+              }
+            }
+
+            .check-value {
+              font-size: 11px;
+              display: inline-block;
+              min-width: 20px;
+            }
+          }
+        }
+      }
+    }
+
+    .dangerous-goods-table {
+      margin-bottom: 20px;
+
+      .goods-table {
+        width: 100%;
+        border-collapse: collapse;
+        border: 1px solid #333;
+
+        th, td {
+          border: 1px solid #333;
+          padding: 10px 8px;
+          text-align: center;
+          vertical-align: middle;
+        }
+
+        th {
+          background: #f5f7fa;
+          font-weight: bold;
+          font-size: 14px;
+        }
+
+        .col-no {
+          width: 50px;
+        }
+
+        .col-bed {
+          width: 80px;
+        }
+
+        .col-name {
+          width: 80px;
+        }
+
+        .col-goods-title {
+          background: #f5f7fa;
+          font-weight: bold;
+        }
+
+        .col-goods {
+          width: 100px;
+        }
+
+        .col-storage {
+          width: 120px;
+        }
+
+        .col-sign {
+          width: 120px;
+        }
+
+        .col-remark {
+          width: 150px;
+        }
+
+        tbody {
+          td {
+            .el-input {
+              width: 100%;
+            }
+
+            .el-textarea {
+              width: 100%;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  .section {
+    margin-bottom: 20px;
+
+    &:last-child {
+      margin-bottom: 0;
+    }
+
+    .section-title {
+      font-weight: bold;
+      margin-bottom: 10px;
+    }
+  }
+
+  .form-item {
+    display: flex;
+    align-items: center;
+    margin-bottom: 12px;
+    flex-wrap: wrap;
+    gap: 8px;
+
+    .item-number {
+      font-weight: bold;
+      min-width: 25px;
+    }
+
+    .item-label {
+      white-space: nowrap;
+      min-width: fit-content;
+    }
+
+  }
+
+  .other-input {
+    width: 200px;
+    margin-left: 10px;
+  }
+
+  // 调整 Element Plus 组件样式
+  :deep(.el-input__inner) {
+    height: 28px;
+    line-height: 28px;
+    border-top: none;
+    border-left: none;
+    border-right: none;
+    border-radius: 0;
+    padding: 0 4px;
+
+    &:focus {
+      border-color: #409eff;
+    }
+  }
+
+
+  :deep(.el-checkbox__label),
+  :deep(.el-radio__label) {
+    padding-left: 4px;
+  }
+}
+.row{
+  margin-bottom: 12px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  text{
+    text-align: right;
+    margin-right: 4px;
+    width: 82px;
+  }
+}
+
+// 感知觉与沟通评估表 特有样式
+.total-score-section {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  margin-bottom: 20px;
+
+  .total-score {
+    display: flex;
+    align-items: baseline;
+    gap: 4px;
+
+    .score-label {
+      font-size: 16px;
+      font-weight: bold;
+    }
+
+    .score-value {
+      font-size: 28px;
+      font-weight: bold;
+      color: #409eff;
+    }
+
+    .score-max {
+      font-size: 14px;
+      color: #909399;
+    }
+  }
+
+  .risk-level {
+    font-size: 16px;
+    font-weight: bold;
+    padding: 8px 16px;
+    border-radius: 4px;
+
+    &.risk-none {
+      color: #67c23a;
+      background: #f0f9eb;
+    }
+
+    &.risk-low {
+      color: #e6a23c;
+      background: #fdf6ec;
+    }
+
+    &.risk-medium {
+      color: #f56c6c;
+      background: #fef0f0;
+    }
+
+    &.risk-high {
+      color: #f56c6c;
+      background: #fef0f0;
+      border: 1px solid #f56c6c;
+    }
+  }
+}
+
+.assessment-table {
+  width: 100%;
+  border-collapse: collapse;
+  margin-bottom: 20px;
+
+  table {
+    width: 100%;
+    border: 1px solid #333;
+
+    th, td {
+      border: 1px solid #333;
+      padding: 12px;
+      text-align: left;
+    }
+
+    th {
+      background: #f5f7fa;
+      font-weight: bold;
+      text-align: center;
+    }
+
+    .criteria-col {
+      width: 60%;
+    }
+
+    .score-col {
+      width: 15%;
+      text-align: center;
+    }
+
+    .select-col {
+      width: 25%;
+      text-align: center;
+    }
+
+    .criteria {
+      text-align: left;
+    }
+
+    .score {
+      text-align: center;
+      font-weight: bold;
+    }
+
+    .select {
+      text-align: center;
+
+      :deep(.el-radio) {
+        margin-right: 0;
+      }
+    }
+  }
+}
+
+.remark-section {
+  margin: 15px 0;
+  padding: 12px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .remark-label {
+    font-weight: bold;
+    color: #606266;
+  }
+
+  .remark-text {
+    color: #606266;
+  }
+}
+
+.risk-judgment-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .risk-judgment-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .risk-options {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20px;
+
+    :deep(.el-radio) {
+      margin-right: 0;
+    }
+  }
+}
+
+.preventive-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .preventive-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .preventive-options {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 15px;
+
+    :deep(.el-checkbox) {
+      margin-right: 20px;
+      margin-bottom: 8px;
+    }
+
+    .other-input {
+      width: 200px;
+      margin-left: 10px;
+    }
+  }
+}
+
+.signature-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .signature-row {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    gap: 20px;
+  }
+
+  .signature-item {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+
+    &.date-item {
+      :deep(.el-date-picker) {
+        width: 150px;
+      }
+    }
+  }
+
+  .signature-label {
+    font-weight: bold;
+    white-space: nowrap;
+  }
+
+  .signature-input {
+    width: 150px;
+  }
+
+  .date-picker {
+    width: 150px;
+  }
+}
+
+.note-section {
+  margin-top: 20px;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .note-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .note-content {
+    font-size: 13px;
+    line-height: 1.8;
+    color: #606266;
+
+    p {
+      margin: 5px 0;
+    }
+
+    .indent {
+      margin-left: 20px;
+    }
+  }
+}
+</style>

+ 390 - 0
src/views/elderly/nursing/records/dustman/index.vue

@@ -0,0 +1,390 @@
+<template>
+  <ContentWrap>
+    <!-- 工单记录 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="110px"
+    >
+      <el-form-item label="长者姓名">
+        <el-input
+          v-model="queryParams.elderName"
+          placeholder="长者姓名"
+          class="!w-240px"
+          clearable
+        />
+      </el-form-item>
+
+      <el-form-item label="楼栋">
+        <el-select v-model="queryParams.buidId" placeholder="选择楼栋" style="width: 180px" @change="handleBuildChange">
+          <el-option v-for="(item,index) in buildList" :key="index" :label="item.buildName" :value="item.id" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="楼层">
+        <el-select  v-model="queryParams.floorId" placeholder="选择楼层" style="width: 180px" >
+          <el-option v-for="(item,index) in floorList" :key="index" :label="item.floorName" :value="item.id" />
+        </el-select>
+      </el-form-item>
+
+
+      <el-form-item label="登记月份">
+        <el-date-picker
+          size="default"
+          ref="selectRef"
+          class="!w-240px"
+          v-model="queryParams.discoveryTime"
+          type="monthrange"
+          :clearable="true"
+          :editable="false"
+          placeholder="选择月份"
+          value-format="YYYY-MM-DD"
+          format="YYYY-MM-DD"
+          date-format="YYYY-MM-DD"
+        />
+      </el-form-item>
+
+      <el-form-item>
+        <el-button @click="handleQuery" style="margin-left: 2vw"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <div class="mb-10px">
+
+      <ButtonAdd @click="openForm(undefined)"  />
+      <el-button @click="inputH" type="success"><Icon icon="fa:cloud-upload" :size="16" class="mr-1"/>导入</el-button>
+      <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">
+        <template #default="scope">
+          {{
+            scope.$index + (queryParams.pageNo * queryParams.pageSize - queryParams.pageSize) + 1
+          }}
+        </template>
+      </el-table-column>
+
+
+      <el-table-column prop="elderName" header-align="center" align="center" label="长者姓名" min-width="120" show-overflow-tooltip/>
+      <el-table-column prop="elderSex" header-align="center" align="center" label="性别" min-width="90" show-overflow-tooltip/>
+      <el-table-column prop="elderAge" header-align="center" align="center" label="年龄" min-width="90" show-overflow-tooltip/>
+      <el-table-column prop="serviceItem" header-align="center" align="center" label="服务项目" min-width="200" show-overflow-tooltip/>
+      <el-table-column prop="serviceName" header-align="center" align="center" label="服务人员姓名" min-width="160" show-overflow-tooltip/>
+      <el-table-column prop="orderTime" header-align="center" align="center" label="订单时间" min-width="180" show-overflow-tooltip>
+        <template #default="scope">
+          {{(formatToDateTime(scope.row.orderTime))}}
+        </template>
+      </el-table-column>
+      <el-table-column prop="comeTime" header-align="center" align="center" label="上门时间" min-width="180" show-overflow-tooltip>
+        <template #default="scope">
+          {{formatToDateTime(scope.row.serviceBeginTime)}}
+        </template>
+      </el-table-column>
+      <el-table-column prop="elderAddress" header-align="center" align="center" label="地址" min-width="220" show-overflow-tooltip/>
+      <el-table-column prop="isExpire" header-align="center" align="center" label="是否过期" min-width="120" show-overflow-tooltip/>
+      <el-table-column prop="orderStatus" header-align="center" align="center" label="订单状态" min-width="160" show-overflow-tooltip/>
+
+      <el-table-column label="操作" align="center" width="200" fixed="right">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openFormEdit(scope.row, scope.row.id)"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="warning"
+            @click="openFormDetail(scope.row.id)"
+          >
+            详情
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="openClose(scope.row)"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </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"
+  />
+
+
+  <Import
+    ref="importRef"
+    @success="getList"
+    :config="{
+      title: '导入',
+      downloadUrl: 'elderly-service-order/get-import-template',
+      excelTempName: '居家工单-【导入】模板',
+      importUrl: '/elderly-service-order/import',
+      failExportUrl: '',
+    }"
+  />
+
+</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 {
+  careRecordsPage, elderlyServiceOrderDelete, elderlyServiceOrderPage,
+} from "@/api/member/appointment";
+import download from "@/utils/download";
+import { useUserStore } from '@/store/modules/user'
+import {formatToDate, formatToDateTime, getCurrentMonthRange} from "@/utils/dateUtil";
+import * as UserApi from "@/api/system/user";
+import Import from "@/components/ImportFile/index.vue";
+import {ref} from "vue";
+import {getBuildList} from "@/api/system/badManage";
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+const userStore = useUserStore()
+const loading = ref(true) // 列表的加载中
+const detailRef = ref()
+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,
+  elderName: '',
+  elderPhone: '',
+  discoveryTime: ["2025-12-01",formatToDate()],
+  tenantIds: userStore.orgTenantId[0]
+})
+const queryFormRef = ref() // 搜索的表单
+
+const inputH = () => {
+  importRef.value.open(queryParams.tenantIds[0])
+}
+// 打开导出弹窗
+const handleImportCard = async () => {
+  try {
+    const queryParams = reactive({
+      pageNo: 1,
+      pageSize: 1000,
+      tenantIds: userStore.orgTenantId,
+    })
+    const data = await UserApi.exportElderlyServiceOrder(queryParams)
+    download.excel(data, '工单报表数据.xls')
+  }catch (e) {
+
+  }
+
+
+  // exportConfig.value = {
+  //   title: "批量导出",
+  //   batchMin: 1,
+  //   batchMax: 999,
+  //   countMin: 1,
+  //   countMax: 500,
+  //   defaultBatch: 1,
+  //   defaultCount: 500,
+  //   description: [
+  //     '1. 请输入需要导出的数量',
+  //     '2. 一次导不完的话,输入批次 2 再次导出,以此类推。',
+  //     '3. 建议单次导出数量不超过500,以免影响系统性能',
+  //     '4. 导出需要较长时间,请耐心等待。'
+  //   ]
+  // }
+  // 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 (_) {}
+
+}
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    //let queryP = {...queryParams,discoveryTime:queryParams.discoveryTime?[queryParams.discoveryTime[0]+" 00:00:00",queryParams.discoveryTime[1]+" 23:59:59"]:null}
+    const data = await elderlyServiceOrderPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = async () => {
+  if (!queryFormRef.value) return
+  const valid = await queryFormRef.value.validate()
+  if (!valid) return
+  queryParams.pageNo = 1
+  await getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryParams.elderName = ''
+  queryParams.tenantId = userStore.orgTenantId[0]
+  queryParams.discoveryTime= ["2025-12-01",formatToDate()]
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (id?: number) => {
+  // if(queryParams.tenantIds.length == 0 || queryParams.tenantIds.length > 1){
+  //   message.error('新增只能选择一个机构')
+  //   return
+  // }
+  formRef.value.open(queryParams.tenantIds, id,false)
+}
+
+const editRef = ref()
+const openFormEdit = (row: any = {}, id?: number) => {
+  formRef.value.open(row.tenantId, id,false)
+}
+
+
+const openFormDetail = (id?: number) => {
+  formRef.value.open(undefined,id,true)
+}
+
+
+
+
+
+const openClose = async (item) => {
+  try {
+    console.log("任务ID",item)
+    const res = await message.confirm('确定要删除吗?', '提示')
+    if (res == 'confirm') {
+      // 发起
+      try {
+        const res = await elderlyServiceOrderDelete(item.id)
+        if (res){
+          message.success(t('common.updateSuccess'))
+        }
+      }catch(err) {}
+    }
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 取消按钮操作 */
+const cancelDelete = async (id: number) => {
+  try {
+    // 取消的二次确认
+    await message.cancelConfirm()
+    // 发起取消
+    // await elderlyBakDel(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+
+const buildList = ref([])
+const floorList = ref([])
+
+const route = useRoute()
+/** 初始化 **/
+onMounted(async () => {
+  if(route.query && route.query.elderName){
+    queryParams.elderName = route.query.elderName as string
+  }
+  getList()
+  try {
+    buildList.value = await getBuildList({tenantIds: queryParams.tenantId})
+  }catch (e) {}
+})
+
+// 表头格式
+const tableHeaderColor = ({ rowIndex }: any) => {
+  if (rowIndex === 0) {
+    return {
+      backgroundColor: '#f8f8f9',
+      color: '#666666',
+      fontWeight: 'bold'
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss"></style>

+ 1122 - 0
src/views/elderly/nursing/records/facility-equipment/AddForm.vue

@@ -0,0 +1,1122 @@
+<template>
+  <el-drawer
+    v-model="dialogVisible"
+    :title="title"
+    resizable
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    :destroy-on-close="true"
+    size="88%"
+    :before-close="handleClosed"
+  >
+
+    <div class="mmse-form">
+      <!-- 设施设备 -->
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" class="row">
+          <text>楼栋</text>
+          <el-select :disabled="isDetail" v-model="dataForm.buildId" placeholder="选择楼栋" style="width: 100%" @change="handleBuildChange">
+            <el-option  v-for="(item,index) in buildList" :key="index" :label="item.buildName" :value="item.id" />
+          </el-select>
+
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" class="row">
+          <text>楼层</text>
+            <el-select :disabled="isDetail" v-model="dataForm.floorId" placeholder="选择楼层" style="width: 100%" @change="handleFloorChange">
+              <el-option v-for="(item,index) in floorList" :key="index" :label="item.floorName" :value="item.id" />
+            </el-select>
+
+        </el-col>
+      </el-row>
+
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>登记人</text>
+          <el-input :disabled="isDetail" v-model="form.assessor"  />
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>登记月份</text>
+          <el-date-picker :disabled="isDetail" v-model="form.assessDate" type="month" style="width: 100%;"/>
+        </el-col>
+      </el-row>
+
+      <!-- 表单内容区域 -->
+      <div class="form-body">
+        <!-- 设施设备检查表 -->
+        <div class="facility-table-wrapper">
+          <table class="facility-table">
+            <thead>
+              <tr>
+                <th class="col-category">类别</th>
+                <th class="col-item">检查项目</th>
+                <th v-for="day in 31" :key="day" class="col-day">{{ day }}</th>
+              </tr>
+            </thead>
+            <tbody>
+              <!-- 房间设施设备 -->
+              <tr>
+                <td rowspan="7" class="category-cell">房间<br/>设施<br/>设备</td>
+                <td class="item-cell">门</td>
+                <td v-for="day in 31" :key="'door-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.door[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.door[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <tr>
+                <td class="item-cell">床头柜</td>
+                <td v-for="day in 31" :key="'bedside-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.bedside[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.bedside[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <tr>
+                <td class="item-cell">衣柜</td>
+                <td v-for="day in 31" :key="'wardrobe-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.wardrobe[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.wardrobe[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <tr>
+                <td class="item-cell">床</td>
+                <td v-for="day in 31" :key="'bed-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.bed[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.bed[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <tr>
+                <td class="item-cell">凳子</td>
+                <td v-for="day in 31" :key="'stool-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.stool[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.stool[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <tr>
+                <td class="item-cell">电视</td>
+                <td v-for="day in 31" :key="'tv-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.tv[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.tv[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <tr>
+                <td class="item-cell">空调</td>
+                <td v-for="day in 31" :key="'ac-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.ac[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.ac[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <!-- 紧急呼叫装置 -->
+              <tr>
+                <td rowspan="2" class="category-cell">紧急<br/>呼叫<br/>装置</td>
+                <td class="item-cell">床头平安钟</td>
+                <td v-for="day in 31" :key="'bedBell-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.bedBell[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.bedBell[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <tr>
+                <td class="item-cell">洗手间平安钟</td>
+                <td v-for="day in 31" :key="'toiletBell-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.toiletBell[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.toiletBell[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <!-- 卫生间设施设备 -->
+              <tr>
+                <td rowspan="8" class="category-cell">卫生<br/>间设<br/>施设<br/>备</td>
+                <td class="item-cell">盥洗池</td>
+                <td v-for="day in 31" :key="'sink-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.sink[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.sink[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <tr>
+                <td class="item-cell">马桶</td>
+                <td v-for="day in 31" :key="'toilet-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.toilet[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.toilet[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <tr>
+                <td class="item-cell">花洒</td>
+                <td v-for="day in 31" :key="'shower-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.shower[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.shower[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <tr>
+                <td class="item-cell">灯</td>
+                <td v-for="day in 31" :key="'light-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.light[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.light[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <tr>
+                <td class="item-cell">浴霸</td>
+                <td v-for="day in 31" :key="'bathHeater-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.bathHeater[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.bathHeater[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <tr>
+                <td class="item-cell">扶手</td>
+                <td v-for="day in 31" :key="'handrail-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.handrail[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.handrail[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <tr>
+                <td class="item-cell">放物架</td>
+                <td v-for="day in 31" :key="'shelf-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.shelf[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.shelf[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <tr>
+                <td class="item-cell">镜子</td>
+                <td v-for="day in 31" :key="'mirror-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.mirror[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.mirror[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <!-- 辅助器材 -->
+              <tr>
+                <td rowspan="4" class="category-cell">辅助<br/>器材</td>
+                <td class="item-cell">轮椅</td>
+                <td v-for="day in 31" :key="'wheelchair-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.wheelchair[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.wheelchair[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <tr>
+                <td class="item-cell">拐杖</td>
+                <td v-for="day in 31" :key="'crutch-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.crutch[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.crutch[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <tr>
+                <td class="item-cell">助行器</td>
+                <td v-for="day in 31" :key="'walker-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.walker[day-1]" class="native-select">
+                    <option value="">-</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.walker[day-1] || '-' }}</span>
+                </td>
+              </tr>
+              <tr>
+                <td class="item-cell">坐便椅</td>
+                <td v-for="day in 31" :key="'commode-'+day">
+                  <select v-if="!isDetail" v-model="form.checkItems.commode[day-1]" class="native-select">
+                    <option value="">--</option>
+                    <option value="正常">正常</option>
+                    <option value="损坏">损坏</option>
+                  </select>
+                  <span v-else class="check-value">{{ form.checkItems.commode[day-1] || '-' }}</span>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+
+        <!-- 检查情况说明 -->
+        <div class="check-info-section">
+          <div class="check-info-row">
+            <span class="label">检查情况说明:</span>
+            <el-input v-if="!isDetail" v-model="form.checkDescription" type="textarea" :rows="3" placeholder="填写检查情况说明" style="flex: 1;" />
+            <span v-else>{{ form.checkDescription }}</span>
+          </div>
+          <div class="check-info-row">
+            <span class="label">检查人签名:</span>
+            <el-input v-if="!isDetail" v-model="form.checkerSignature" placeholder="签名" style="width: 200px;" />
+            <span v-else>{{ form.checkerSignature }}</span>
+          </div>
+        </div>
+
+        <!-- 备注说明 -->
+        <div class="note-section">
+          <div class="note-title">备注说明</div>
+          <div class="note-content">
+            <p>检查设施设备及器材完好则在相应栏选择"正常",如检查有损坏则在相应栏选择"损坏",并立即上报维修员维修,最后在备注栏填写上报及维修结果。</p>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div>前端提交的数据,后端可以参照这个格式:
+      {
+      "buildId": 190,
+      "floorId": 644,
+      "floorName": "2层",
+      "elderName": "0318",
+      "bedName": "测试楼-2层-201-10",
+      "tenantId": 195,
+      "buildName": "测试楼",
+      "assessData": " ",
+      "assessor": "啊啊啊",
+      "assessDate": "2026-03-27",
+      "orgType": 1
+      }
+    </div>
+
+
+
+    <template #footer>
+      <el-button @click="handleClosed">关闭</el-button>
+      <el-button style="margin-left: 22px;margin-right: 30px" v-loading="formLoading" type="primary" v-show="!isDetail" @click="submitForm">确定</el-button>
+      <el-button v-if="isDetail" type="success" @click="handleExport">打印</el-button>
+    </template>
+
+  </el-drawer>
+</template>
+
+<script lang="ts" setup>
+import { computed, ref } from 'vue'
+
+import dayjs from 'dayjs'
+
+import { facilityEquipmentCreate, facilityEquipmentGetById, facilityEquipmentUpdate } from "@/api/social-work";
+import {getBuildList} from "@/api/system/badManage";
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+const title = ref('')
+const dialogVisible = ref(false) // 弹窗
+const formRef = ref() // 表单 Ref
+const selectElderRef = ref() // 表单 Ref
+const isDetail = ref(false) // 是否详情打开
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+let dataForm = ref({
+  // 表单字段
+  id: undefined,
+  idCard: '',
+  buildId: '',
+  floorId: '',
+  floorName: '',
+  contractNumber: '', //档案号
+  elderName: '',//长者姓名
+  bedName: '', //床位号
+  elderAge: '', //年龄
+  elderSex: '', //性别
+  checkInTime: '', //入院日期
+  elderId: '',
+  tenantId: undefined
+})
+
+
+const buildList = ref([])
+const floorList = ref([])
+const handleBuildChange = (buildId: any) => {
+  const selectedBuild = buildList.value.find((item: any) => item.id === buildId)
+  if (selectedBuild) {
+    dataForm.value.buildName = selectedBuild.buildName
+    floorList.value = selectedBuild.floorList || []
+    // 清空楼层选择
+    dataForm.value.floorId = ''
+    dataForm.value.floorName = ''
+  }
+}
+const handleFloorChange = (floorId: any) => {
+  const selectedFloor = floorList.value.find((item: any) => item.id === floorId)
+  if (selectedFloor) {
+    dataForm.value.floorName = selectedFloor.floorName
+  }
+}
+
+const elderUp = (e) => {
+  dataForm.value.elderName = e.elderName
+  dataForm.value.elderId = e.id
+  dataForm.value.elderSex = e.elderSex === 1 ? '男' : '女'
+  dataForm.value.bedName = e.bedName || ''
+  dataForm.value.checkInTime = e.checkInTime
+  dataForm.value.contractNumber = e.contractNumber
+  dataForm.value.elderAge = e.elderAge
+}
+
+// ========== 感知觉与沟通评估表 表单序列化方法 ==========
+
+// 危险物品登记不需要计算总分,保留计算属性占位
+const totalScore = computed(() => {
+  return 0
+})
+
+
+/** 将表单数据序列化为 JSON 对象 */
+const serializeFormData = () => {
+  return {
+    // 基本信息
+    assessor: form.assessor || '',
+    assessDate: form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : '',
+
+    // 设施设备检查项
+    checkItems: form.checkItems,
+
+    // 检查情况说明
+    checkDescription: form.checkDescription || '',
+    checkerSignature: form.checkerSignature || ''
+  }
+}
+
+/** 将 JSON 对象反序列化为表单数据 */
+const deserializeFormData = (formData: Record<string, any>) => {
+  if (!formData) return
+
+  // 基本信息
+  form.assessor = formData.assessor || ''
+  form.assessDate = formData.assessDate ? dayjs(formData.assessDate).toDate() : ''
+
+  // 设施设备检查项
+  if (formData.checkItems) {
+    Object.keys(form.checkItems).forEach(key => {
+      if (formData.checkItems[key]) {
+        form.checkItems[key] = formData.checkItems[key]
+      }
+    })
+  }
+
+  // 检查情况说明
+  form.checkDescription = formData.checkDescription || ''
+  form.checkerSignature = formData.checkerSignature || ''
+}
+
+/** 重置设施设备检查表表单数据 */
+const resetPerceptionForm = () => {
+  form.assessor = ''
+  form.assessDate = ''
+
+  // 重置所有检查项为31天空数组
+  Object.keys(form.checkItems).forEach(key => {
+    form.checkItems[key] = generate31Days()
+  })
+
+  // 重置检查情况说明
+  form.checkDescription = ''
+  form.checkerSignature = ''
+}
+
+/** 打开弹窗 */
+const open = async (tenantId, id?: any, detail: boolean = false) => {
+  resetForm()
+  dialogVisible.value = true
+  dataForm.value.id = id || undefined
+  dataForm.value.tenantId = tenantId
+  isDetail.value = detail
+  try {
+    buildList.value = await getBuildList({tenantIds: tenantId})
+  }catch (e) {}
+
+  if (id) {
+    title.value = "编辑-设施设备检查"
+    // 加载登记数据
+    await loadDangerousGoodsData(id)
+  } else {
+    title.value = "新增-设施设备检查"
+
+  }
+}
+
+/** 加载登记数据 */
+const loadDangerousGoodsData = async (id: number) => {
+  try {
+    const res = await facilityEquipmentGetById(id)
+    if (res) {
+      // 填充长者基本信息
+      dataForm.value.elderName = res.elderName || ''
+      dataForm.value.elderId = res.elderId || ''
+      dataForm.value.elderSex = res.elderSex || ''
+      dataForm.value.bedName = res.bedName || ''
+      dataForm.value.checkInTime = res.checkInTime || ''
+      dataForm.value.contractNumber = res.fileNumber || ''
+      dataForm.value.elderAge = res.elderAge || ''
+      await selectElderRef.value.upData(res.elderName, res.elderId)
+      // 解析 assessData
+      if (res.assessData) {
+        const formData = JSON.parse(res.assessData)
+        deserializeFormData(formData)
+      }
+    }
+  } catch (error) {
+    message.error('加载设施设备检查数据失败')
+  }
+}
+
+
+
+// 生成31天的空数组
+const generate31Days = () => new Array(31).fill('')
+
+const form = reactive({
+  // 基本信息
+  assessor: '',
+  assessDate: '',
+
+  // 设施设备检查项(31天)
+  checkItems: {
+    // 房间设施设备
+    door: generate31Days(),        // 门
+    bedside: generate31Days(),     // 床头柜
+    wardrobe: generate31Days(),    // 衣柜
+    bed: generate31Days(),         // 床
+    stool: generate31Days(),       // 凳子
+    tv: generate31Days(),          // 电视
+    ac: generate31Days(),          // 空调
+    // 紧急呼叫装置
+    bedBell: generate31Days(),     // 床头平安钟
+    toiletBell: generate31Days(),  // 洗手间平安钟
+    // 卫生间设施设备
+    sink: generate31Days(),        // 盥洗池
+    toilet: generate31Days(),      // 马桶
+    shower: generate31Days(),      // 花洒
+    light: generate31Days(),       // 灯
+    bathHeater: generate31Days(),  // 浴霸
+    handrail: generate31Days(),    // 扶手
+    shelf: generate31Days(),       // 放物架
+    mirror: generate31Days(),      // 镜子
+    // 辅助器材
+    wheelchair: generate31Days(),  // 轮椅
+    crutch: generate31Days(),      // 拐杖
+    walker: generate31Days(),      // 助行器
+    commode: generate31Days()      // 坐便椅
+  },
+
+  // 检查情况说明
+  checkDescription: '',
+  // 检查人签名
+  checkerSignature: ''
+})
+
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  if (formLoading.value) {
+    return
+  }
+  formLoading.value = true
+  // 提交请求
+    try {
+      const assessData = serializeFormData()
+      const tempParams = {
+        ...dataForm.value,
+        assessData: JSON.stringify(assessData),
+        assessor: form.assessor,
+        assessDate: form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : ''
+      }
+
+    if (dataForm.value.id) {
+      const res = await facilityEquipmentUpdate(tempParams)
+      if (res) {
+        message.success(t('common.updateSuccess'))
+        dialogVisible.value = false
+        // 发送操作成功的事件
+        emit('success')
+      }
+    } else {
+      const res = await facilityEquipmentCreate(tempParams)
+      if (res) {
+        message.success(t('common.createSuccess'))
+        dialogVisible.value = false
+        // 发送操作成功的事件
+        emit('success')
+      }
+    }
+  } finally {
+    setTimeout(() => {
+      formLoading.value = false
+    }, 500)
+  }
+}
+
+
+
+/** 重置表单 */
+const resetForm = () => {
+  dataForm.value = {
+    id: undefined,
+    idCard: '',
+    buildId: '',
+    floorId: '',
+    floorName: '',
+    contractNumber: '', //档案号
+    elderName: '',//长者姓名
+    bedName: '', //床位号
+    elderAge: '', //年龄
+    elderSex: '', //性别
+    checkInTime: '', //入院日期
+    elderId: '',
+    tenantId: undefined
+  }
+  formRef.value?.resetFields()
+
+  // 重置感知觉与沟通评估表表单
+  resetPerceptionForm()
+}
+
+// 关闭表单
+const handleClosed = () => {
+  dialogVisible.value = false
+  resetForm()
+}
+
+
+
+</script>
+
+<style scoped lang="scss">
+.mmse-form {
+  margin: 0 auto;
+  background: #fff;
+
+  .form-title {
+    text-align: center;
+    font-size: 24px;
+    font-weight: bold;
+    margin-bottom: 20px;
+  }
+
+
+
+  .info-row {
+    display: flex;
+    gap: 40px;
+    width: 100%;
+    flex-direction: row;
+    align-items: center;
+    margin-bottom: 10px;
+
+    .info-item {
+      display: flex;
+      align-items: center;
+      gap: 8px;
+
+      .label {
+        width: 82px;
+        text-align: right;
+        margin-right: 4px;
+        white-space: nowrap;
+      }
+    }
+  }
+
+
+  .form-body {
+    border: 1px solid #333;
+    padding: 15px;
+
+    .facility-table-wrapper {
+      overflow-x: auto;
+      margin-bottom: 20px;
+
+      .facility-table {
+        min-width: 1400px;
+        border-collapse: collapse;
+        border: 1px solid #333;
+
+        th, td {
+          border: 1px solid #333;
+          padding: 4px 2px;
+          text-align: center;
+          vertical-align: middle;
+        }
+
+        th {
+          background: #f5f7fa;
+          font-weight: bold;
+          font-size: 12px;
+        }
+
+        .col-category {
+          width: 80px;
+          min-width: 80px;
+          background: #f5f7fa;
+          font-weight: bold;
+          font-size: 12px;
+        }
+
+        .col-item {
+          width: 100px;
+          min-width: 100px;
+          background: #f5f7fa;
+          font-weight: bold;
+          font-size: 12px;
+        }
+
+        .col-day {
+          width: 55px;
+          font-size: 11px;
+          min-width: 55px;
+        }
+
+        .category-cell {
+          background: #f5f7fa;
+          font-weight: bold;
+          font-size: 12px;
+          line-height: 1.4;
+        }
+
+        .item-cell {
+          font-size: 12px;
+          text-align: left;
+          padding-left: 8px;
+        }
+
+        tbody {
+          td {
+            .native-select {
+              width: 100%;
+              height: 24px;
+              padding: 0 16px 0 2px;
+              font-size: 11px;
+              border: 1px solid #dcdfe6;
+              border-radius: 3px;
+              background-color: #fff;
+              text-align: center;
+              cursor: pointer;
+              appearance: none;
+              background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
+              background-repeat: no-repeat;
+              background-position: right 2px center;
+              background-size: 12px;
+
+              &:focus {
+                border-color: #409eff;
+                outline: none;
+              }
+
+              option {
+                font-size: 12px;
+              }
+            }
+
+            .check-value {
+              font-size: 12px;
+              display: inline-block;
+              min-width: 20px;
+            }
+          }
+        }
+      }
+    }
+
+    .check-info-section {
+      margin-bottom: 20px;
+
+      .check-info-row {
+        display: flex;
+        align-items: flex-start;
+        margin-bottom: 15px;
+
+        .label {
+          font-weight: bold;
+          white-space: nowrap;
+          margin-right: 10px;
+          min-width: 100px;
+        }
+      }
+    }
+  }
+
+  .section {
+    margin-bottom: 20px;
+
+    &:last-child {
+      margin-bottom: 0;
+    }
+
+    .section-title {
+      font-weight: bold;
+      margin-bottom: 10px;
+    }
+  }
+
+  .form-item {
+    display: flex;
+    align-items: center;
+    margin-bottom: 12px;
+    flex-wrap: wrap;
+    gap: 8px;
+
+    .item-number {
+      font-weight: bold;
+      min-width: 25px;
+    }
+
+    .item-label {
+      white-space: nowrap;
+      min-width: fit-content;
+    }
+
+  }
+
+  .other-input {
+    width: 200px;
+    margin-left: 10px;
+  }
+
+  // 调整 Element Plus 组件样式
+  :deep(.el-input__inner) {
+    height: 28px;
+    line-height: 28px;
+    border-top: none;
+    border-left: none;
+    border-right: none;
+    border-radius: 0;
+    padding: 0 4px;
+
+    &:focus {
+      border-color: #409eff;
+    }
+  }
+
+
+  :deep(.el-checkbox__label),
+  :deep(.el-radio__label) {
+    padding-left: 4px;
+  }
+}
+.row{
+  margin-bottom: 12px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  text{
+    text-align: right;
+    margin-right: 4px;
+    width: 82px;
+  }
+}
+
+// 感知觉与沟通评估表 特有样式
+.total-score-section {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  margin-bottom: 20px;
+
+  .total-score {
+    display: flex;
+    align-items: baseline;
+    gap: 4px;
+
+    .score-label {
+      font-size: 16px;
+      font-weight: bold;
+    }
+
+    .score-value {
+      font-size: 28px;
+      font-weight: bold;
+      color: #409eff;
+    }
+
+    .score-max {
+      font-size: 14px;
+      color: #909399;
+    }
+  }
+
+  .risk-level {
+    font-size: 16px;
+    font-weight: bold;
+    padding: 8px 16px;
+    border-radius: 4px;
+
+    &.risk-none {
+      color: #67c23a;
+      background: #f0f9eb;
+    }
+
+    &.risk-low {
+      color: #e6a23c;
+      background: #fdf6ec;
+    }
+
+    &.risk-medium {
+      color: #f56c6c;
+      background: #fef0f0;
+    }
+
+    &.risk-high {
+      color: #f56c6c;
+      background: #fef0f0;
+      border: 1px solid #f56c6c;
+    }
+  }
+}
+
+.assessment-table {
+  width: 100%;
+  border-collapse: collapse;
+  margin-bottom: 20px;
+
+  table {
+    width: 100%;
+    border: 1px solid #333;
+
+    th, td {
+      border: 1px solid #333;
+      padding: 12px;
+      text-align: left;
+    }
+
+    th {
+      background: #f5f7fa;
+      font-weight: bold;
+      text-align: center;
+    }
+
+    .criteria-col {
+      width: 60%;
+    }
+
+    .score-col {
+      width: 15%;
+      text-align: center;
+    }
+
+    .select-col {
+      width: 25%;
+      text-align: center;
+    }
+
+    .criteria {
+      text-align: left;
+    }
+
+    .score {
+      text-align: center;
+      font-weight: bold;
+    }
+
+    .select {
+      text-align: center;
+
+      :deep(.el-radio) {
+        margin-right: 0;
+      }
+    }
+  }
+}
+
+.remark-section {
+  margin: 15px 0;
+  padding: 12px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .remark-label {
+    font-weight: bold;
+    color: #606266;
+  }
+
+  .remark-text {
+    color: #606266;
+  }
+}
+
+.risk-judgment-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .risk-judgment-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .risk-options {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20px;
+
+    :deep(.el-radio) {
+      margin-right: 0;
+    }
+  }
+}
+
+.preventive-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .preventive-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .preventive-options {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 15px;
+
+    :deep(.el-checkbox) {
+      margin-right: 20px;
+      margin-bottom: 8px;
+    }
+
+    .other-input {
+      width: 200px;
+      margin-left: 10px;
+    }
+  }
+}
+
+.signature-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .signature-row {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    gap: 20px;
+  }
+
+  .signature-item {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+
+    &.date-item {
+      :deep(.el-date-picker) {
+        width: 150px;
+      }
+    }
+  }
+
+  .signature-label {
+    font-weight: bold;
+    white-space: nowrap;
+  }
+
+  .signature-input {
+    width: 150px;
+  }
+
+  .date-picker {
+    width: 150px;
+  }
+}
+
+.note-section {
+  margin-top: 20px;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .note-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .note-content {
+    font-size: 13px;
+    line-height: 1.8;
+    color: #606266;
+
+    p {
+      margin: 5px 0;
+    }
+
+    .indent {
+      margin-left: 20px;
+    }
+  }
+}
+</style>

+ 390 - 0
src/views/elderly/nursing/records/facility-equipment/index.vue

@@ -0,0 +1,390 @@
+<template>
+  <ContentWrap>
+    <!-- 工单记录 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="110px"
+    >
+      <el-form-item label="长者姓名">
+        <el-input
+          v-model="queryParams.elderName"
+          placeholder="长者姓名"
+          class="!w-240px"
+          clearable
+        />
+      </el-form-item>
+
+      <el-form-item label="楼栋">
+        <el-select v-model="queryParams.buidId" placeholder="选择楼栋" style="width: 180px" @change="handleBuildChange">
+          <el-option v-for="(item,index) in buildList" :key="index" :label="item.buildName" :value="item.id" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="楼层">
+        <el-select  v-model="queryParams.floorId" placeholder="选择楼层" style="width: 180px" >
+          <el-option v-for="(item,index) in floorList" :key="index" :label="item.floorName" :value="item.id" />
+        </el-select>
+      </el-form-item>
+
+
+      <el-form-item label="登记月份">
+        <el-date-picker
+          size="default"
+          ref="selectRef"
+          class="!w-240px"
+          v-model="queryParams.discoveryTime"
+          type="monthrange"
+          :clearable="true"
+          :editable="false"
+          placeholder="选择月份"
+          value-format="YYYY-MM-DD"
+          format="YYYY-MM-DD"
+          date-format="YYYY-MM-DD"
+        />
+      </el-form-item>
+
+      <el-form-item>
+        <el-button @click="handleQuery" style="margin-left: 2vw"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <div class="mb-10px">
+
+      <ButtonAdd @click="openForm(undefined)"  />
+      <el-button @click="inputH" type="success"><Icon icon="fa:cloud-upload" :size="16" class="mr-1"/>导入</el-button>
+      <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">
+        <template #default="scope">
+          {{
+            scope.$index + (queryParams.pageNo * queryParams.pageSize - queryParams.pageSize) + 1
+          }}
+        </template>
+      </el-table-column>
+
+
+      <el-table-column prop="elderName" header-align="center" align="center" label="长者姓名" min-width="120" show-overflow-tooltip/>
+      <el-table-column prop="elderSex" header-align="center" align="center" label="性别" min-width="90" show-overflow-tooltip/>
+      <el-table-column prop="elderAge" header-align="center" align="center" label="年龄" min-width="90" show-overflow-tooltip/>
+      <el-table-column prop="serviceItem" header-align="center" align="center" label="服务项目" min-width="200" show-overflow-tooltip/>
+      <el-table-column prop="serviceName" header-align="center" align="center" label="服务人员姓名" min-width="160" show-overflow-tooltip/>
+      <el-table-column prop="orderTime" header-align="center" align="center" label="订单时间" min-width="180" show-overflow-tooltip>
+        <template #default="scope">
+          {{(formatToDateTime(scope.row.orderTime))}}
+        </template>
+      </el-table-column>
+      <el-table-column prop="comeTime" header-align="center" align="center" label="上门时间" min-width="180" show-overflow-tooltip>
+        <template #default="scope">
+          {{formatToDateTime(scope.row.serviceBeginTime)}}
+        </template>
+      </el-table-column>
+      <el-table-column prop="elderAddress" header-align="center" align="center" label="地址" min-width="220" show-overflow-tooltip/>
+      <el-table-column prop="isExpire" header-align="center" align="center" label="是否过期" min-width="120" show-overflow-tooltip/>
+      <el-table-column prop="orderStatus" header-align="center" align="center" label="订单状态" min-width="160" show-overflow-tooltip/>
+
+      <el-table-column label="操作" align="center" width="200" fixed="right">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openFormEdit(scope.row, scope.row.id)"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="warning"
+            @click="openFormDetail(scope.row.id)"
+          >
+            详情
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="openClose(scope.row)"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </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"
+  />
+
+
+  <Import
+    ref="importRef"
+    @success="getList"
+    :config="{
+      title: '导入',
+      downloadUrl: 'elderly-service-order/get-import-template',
+      excelTempName: '居家工单-【导入】模板',
+      importUrl: '/elderly-service-order/import',
+      failExportUrl: '',
+    }"
+  />
+
+</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 {
+  careRecordsPage, elderlyServiceOrderDelete, elderlyServiceOrderPage,
+} from "@/api/member/appointment";
+import download from "@/utils/download";
+import { useUserStore } from '@/store/modules/user'
+import {formatToDate, formatToDateTime, getCurrentMonthRange} from "@/utils/dateUtil";
+import * as UserApi from "@/api/system/user";
+import Import from "@/components/ImportFile/index.vue";
+import {ref} from "vue";
+import {getBuildList} from "@/api/system/badManage";
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+const userStore = useUserStore()
+const loading = ref(true) // 列表的加载中
+const detailRef = ref()
+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,
+  elderName: '',
+  elderPhone: '',
+  discoveryTime: ["2025-12-01",formatToDate()],
+  tenantIds: userStore.orgTenantId[0]
+})
+const queryFormRef = ref() // 搜索的表单
+
+const inputH = () => {
+  importRef.value.open(queryParams.tenantIds[0])
+}
+// 打开导出弹窗
+const handleImportCard = async () => {
+  try {
+    const queryParams = reactive({
+      pageNo: 1,
+      pageSize: 1000,
+      tenantIds: userStore.orgTenantId,
+    })
+    const data = await UserApi.exportElderlyServiceOrder(queryParams)
+    download.excel(data, '工单报表数据.xls')
+  }catch (e) {
+
+  }
+
+
+  // exportConfig.value = {
+  //   title: "批量导出",
+  //   batchMin: 1,
+  //   batchMax: 999,
+  //   countMin: 1,
+  //   countMax: 500,
+  //   defaultBatch: 1,
+  //   defaultCount: 500,
+  //   description: [
+  //     '1. 请输入需要导出的数量',
+  //     '2. 一次导不完的话,输入批次 2 再次导出,以此类推。',
+  //     '3. 建议单次导出数量不超过500,以免影响系统性能',
+  //     '4. 导出需要较长时间,请耐心等待。'
+  //   ]
+  // }
+  // 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 (_) {}
+
+}
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    //let queryP = {...queryParams,discoveryTime:queryParams.discoveryTime?[queryParams.discoveryTime[0]+" 00:00:00",queryParams.discoveryTime[1]+" 23:59:59"]:null}
+    const data = await elderlyServiceOrderPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = async () => {
+  if (!queryFormRef.value) return
+  const valid = await queryFormRef.value.validate()
+  if (!valid) return
+  queryParams.pageNo = 1
+  await getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryParams.elderName = ''
+  queryParams.tenantId = userStore.orgTenantId[0]
+  queryParams.discoveryTime= ["2025-12-01",formatToDate()]
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (id?: number) => {
+  // if(queryParams.tenantIds.length == 0 || queryParams.tenantIds.length > 1){
+  //   message.error('新增只能选择一个机构')
+  //   return
+  // }
+  formRef.value.open(queryParams.tenantIds, id,false)
+}
+
+const editRef = ref()
+const openFormEdit = (row: any = {}, id?: number) => {
+  formRef.value.open(row.tenantId, id,false)
+}
+
+
+const openFormDetail = (id?: number) => {
+  formRef.value.open(undefined,id,true)
+}
+
+
+
+
+
+const openClose = async (item) => {
+  try {
+    console.log("任务ID",item)
+    const res = await message.confirm('确定要删除吗?', '提示')
+    if (res == 'confirm') {
+      // 发起
+      try {
+        const res = await elderlyServiceOrderDelete(item.id)
+        if (res){
+          message.success(t('common.updateSuccess'))
+        }
+      }catch(err) {}
+    }
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 取消按钮操作 */
+const cancelDelete = async (id: number) => {
+  try {
+    // 取消的二次确认
+    await message.cancelConfirm()
+    // 发起取消
+    // await elderlyBakDel(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+
+const buildList = ref([])
+const floorList = ref([])
+
+const route = useRoute()
+/** 初始化 **/
+onMounted(async () => {
+  if(route.query && route.query.elderName){
+    queryParams.elderName = route.query.elderName as string
+  }
+  getList()
+  try {
+    buildList.value = await getBuildList({tenantIds: queryParams.tenantId})
+  }catch (e) {}
+})
+
+// 表头格式
+const tableHeaderColor = ({ rowIndex }: any) => {
+  if (rowIndex === 0) {
+    return {
+      backgroundColor: '#f8f8f9',
+      color: '#666666',
+      fontWeight: 'bold'
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss"></style>

+ 958 - 0
src/views/elderly/nursing/records/paper-diaper-receive/AddForm.vue

@@ -0,0 +1,958 @@
+<template>
+  <el-drawer
+    v-model="dialogVisible"
+    :title="title"
+    resizable
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    :destroy-on-close="true"
+    size="70%"
+    :before-close="handleClosed"
+  >
+
+    <div class="mmse-form">
+      <!-- 纸尿裤领用 -->
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>长者姓名</text>
+          <search-the-elderly ref="selectElderRef" :disabled="isDetail" @update_elder="elderUp" v-model="dataForm.elderName" :tId="dataForm.tenantId"/>
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>档案号</text>
+          <el-input v-if="!isDetail" v-model="dataForm.contractNumber" disabled />
+          <el-text v-else disabled="">{{dataForm.contractNumber}}</el-text>
+        </el-col>
+      </el-row>
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>入院日期</text>
+          <el-input v-if="!isDetail" :model-value="dayjs(dataForm.checkInTime).format('YYYY-MM-DD')=='Invalid Date'?'':dayjs(dataForm.checkInTime).format('YYYY-MM-DD')" disabled />
+          <el-text v-else disabled="">{{dayjs(dataForm.checkInTime).format('YYYY-MM-DD')}}</el-text>
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>床位号</text>
+          <el-input v-if="!isDetail" v-model="dataForm.bedName" disabled />
+          <el-text v-else disabled="">{{dataForm.bedName}}</el-text>
+        </el-col>
+      </el-row>
+
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" class="row">
+          <text>楼栋</text>
+          <el-select :disabled="isDetail" v-model="dataForm.buildId" placeholder="选择楼栋" style="width: 100%" @change="handleBuildChange">
+            <el-option  v-for="(item,index) in buildList" :key="index" :label="item.buildName" :value="item.id" />
+          </el-select>
+
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" class="row">
+          <text>楼层</text>
+            <el-select :disabled="isDetail" v-model="dataForm.floorId" placeholder="选择楼层" style="width: 100%" @change="handleFloorChange">
+              <el-option v-for="(item,index) in floorList" :key="index" :label="item.floorName" :value="item.id" />
+            </el-select>
+
+        </el-col>
+      </el-row>
+
+      <el-row :gutter="40">
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>登记人</text>
+          <el-input :disabled="isDetail" v-model="form.assessor"  />
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
+          <text>登记日期</text>
+          <el-date-picker :disabled="isDetail" v-model="form.assessDate" type="date" style="width: 100%;"/>
+        </el-col>
+      </el-row>
+
+      <!-- 表单内容区域 -->
+      <div class="form-body">
+        <!-- 纸尿裤领用登记表 -->
+        <div class="diaper-table-wrapper">
+          <table class="diaper-table">
+            <thead>
+              <tr>
+                <th class="col-monthly">包月<br/>(元)</th>
+                <th class="col-product">互爱纸尿裤<br/>m码/包<br/>28元</th>
+                <th class="col-product">纸尿裤<br/>L码/包<br/>29.8元</th>
+                <th class="col-product">纸尿裤<br/>XL码/包<br/>32元</th>
+                <th class="col-product">互爱尿片<br/>均码/包<br/>38元</th>
+                <th class="col-product">拉拉裤<br/>/包<br/>48元</th>
+                <th class="col-product">护理垫<br/>/包<br/>17.55元</th>
+                <th class="col-sign">护理员<br/>签名</th>
+                <th class="col-total">合计<br/>(元)</th>
+              </tr>
+            </thead>
+            <tbody>
+              <tr>
+                <!-- 包月价格 -->
+                <td>
+                  <el-input v-if="!isDetail" v-model.number="form.monthlyPrice" type="number" placeholder="价格" @change="calculateTotal" />
+                  <span v-else>{{ form.monthlyPrice }}</span>
+                </td>
+                <!-- 互爱纸尿裤m码数量 -->
+                <td>
+                  <el-input v-if="!isDetail" v-model.number="form.diaperMCount" type="number" placeholder="数量" @change="calculateTotal" />
+                  <span v-else>{{ form.diaperMCount }}</span>
+                </td>
+                <!-- 纸尿裤L码数量 -->
+                <td>
+                  <el-input v-if="!isDetail" v-model.number="form.diaperLCount" type="number" placeholder="数量" @change="calculateTotal" />
+                  <span v-else>{{ form.diaperLCount }}</span>
+                </td>
+                <!-- 纸尿裤XL码数量 -->
+                <td>
+                  <el-input v-if="!isDetail" v-model.number="form.diaperXLCount" type="number" placeholder="数量" @change="calculateTotal" />
+                  <span v-else>{{ form.diaperXLCount }}</span>
+                </td>
+                <!-- 互爱尿片均码数量 -->
+                <td>
+                  <el-input v-if="!isDetail" v-model.number="form.diaperPadCount" type="number" placeholder="数量" @change="calculateTotal" />
+                  <span v-else>{{ form.diaperPadCount }}</span>
+                </td>
+                <!-- 拉拉裤数量 -->
+                <td>
+                  <el-input v-if="!isDetail" v-model.number="form.pullUpCount" type="number" placeholder="数量" @change="calculateTotal" />
+                  <span v-else>{{ form.pullUpCount }}</span>
+                </td>
+                <!-- 护理垫数量 -->
+                <td>
+                  <el-input v-if="!isDetail" v-model.number="form.carePadCount" type="number" placeholder="数量" @change="calculateTotal" />
+                  <span v-else>{{ form.carePadCount }}</span>
+                </td>
+                <!-- 护理员签名 -->
+                <td>
+                  <el-input v-if="!isDetail" v-model="form.nurseSignature" placeholder="签名" />
+                  <span v-else>{{ form.nurseSignature }}</span>
+                </td>
+                <!-- 合计 -->
+                <td class="total-cell">
+                  <span class="total-amount">{{ form.totalAmount }}</span>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+
+        <!-- 备注说明 -->
+        <div class="note-section">
+          <div class="note-title">备注说明</div>
+          <div class="note-content">
+            <p>1. 包月费用直接输入价格,其他产品输入数量,系统自动计算合计金额。</p>
+            <p>2. 产品价格:互爱纸尿裤m码28元/包,L码29.8元/包,XL码32元/包,互爱尿片38元/包,拉拉裤48元/包,护理垫17.55元/包。</p>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div>前端提交的数据,后端可以参照这个格式:
+      {
+      "buildId": 190,
+      "floorId": 644,
+      "floorName": "2层",
+      "contractNumber": "111",
+      "elderName": "0318",
+      "bedName": "测试楼-2层-201-10",
+      "elderAge": 86,
+      "elderSex": "男",
+      "elderId": 18697,
+      "tenantId": 195,
+      "buildName": "测试楼",
+      "assessData": " ",
+      "assessor": "啊啊啊",
+      "assessDate": "2026-03-27",
+      "orgType": 1
+      }
+    </div>
+
+
+
+    <template #footer>
+      <el-button @click="handleClosed">关闭</el-button>
+      <el-button style="margin-left: 22px;margin-right: 30px" v-loading="formLoading" type="primary" v-show="!isDetail" @click="submitForm">确定</el-button>
+      <el-button v-if="isDetail" type="success" @click="handleExport">打印</el-button>
+    </template>
+
+  </el-drawer>
+</template>
+
+<script lang="ts" setup>
+import { computed, ref } from 'vue'
+
+import dayjs from 'dayjs'
+
+import { diaperReceiveCreate, diaperReceiveGetById, diaperReceiveUpdate } from "@/api/social-work";
+import {getBuildList} from "@/api/system/badManage";
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+const title = ref('')
+const dialogVisible = ref(false) // 弹窗
+const formRef = ref() // 表单 Ref
+const selectElderRef = ref() // 表单 Ref
+const isDetail = ref(false) // 是否详情打开
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+let dataForm = ref({
+  // 表单字段
+  id: undefined,
+  idCard: '',
+  buildId: '',
+  floorId: '',
+  floorName: '',
+  contractNumber: '', //档案号
+  elderName: '',//长者姓名
+  bedName: '', //床位号
+  elderAge: '', //年龄
+  elderSex: '', //性别
+  checkInTime: '', //入院日期
+  elderId: '',
+  tenantId: undefined
+})
+
+
+const buildList = ref([])
+const floorList = ref([])
+const handleBuildChange = (buildId: any) => {
+  const selectedBuild = buildList.value.find((item: any) => item.id === buildId)
+  if (selectedBuild) {
+    dataForm.value.buildName = selectedBuild.buildName
+    floorList.value = selectedBuild.floorList || []
+    // 清空楼层选择
+    dataForm.value.floorId = ''
+    dataForm.value.floorName = ''
+  }
+}
+const handleFloorChange = (floorId: any) => {
+  const selectedFloor = floorList.value.find((item: any) => item.id === floorId)
+  if (selectedFloor) {
+    dataForm.value.floorName = selectedFloor.floorName
+  }
+}
+
+const elderUp = (e) => {
+  dataForm.value.elderName = e.elderName
+  dataForm.value.elderId = e.id
+  dataForm.value.elderSex = e.elderSex === 1 ? '男' : '女'
+  dataForm.value.bedName = e.bedName || ''
+  dataForm.value.checkInTime = e.checkInTime
+  dataForm.value.contractNumber = e.contractNumber
+  dataForm.value.elderAge = e.elderAge
+}
+
+// ========== 感知觉与沟通评估表 表单序列化方法 ==========
+
+// 纸尿裤领用合计金额
+const totalScore = computed(() => {
+  return form.totalAmount
+})
+
+
+/** 将表单数据序列化为 JSON 对象 */
+const serializeFormData = () => {
+  return {
+    // 基本信息
+    assessor: form.assessor || '',
+    assessDate: form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : '',
+
+    // 纸尿裤领用登记
+    monthlyPrice: form.monthlyPrice || 0,
+    diaperMCount: form.diaperMCount || 0,
+    diaperLCount: form.diaperLCount || 0,
+    diaperXLCount: form.diaperXLCount || 0,
+    diaperPadCount: form.diaperPadCount || 0,
+    pullUpCount: form.pullUpCount || 0,
+    carePadCount: form.carePadCount || 0,
+    nurseSignature: form.nurseSignature || '',
+    totalAmount: form.totalAmount || 0
+  }
+}
+
+/** 将 JSON 对象反序列化为表单数据 */
+const deserializeFormData = (formData: Record<string, any>) => {
+  if (!formData) return
+
+  // 基本信息
+  form.assessor = formData.assessor || ''
+  form.assessDate = formData.assessDate ? dayjs(formData.assessDate).toDate() : ''
+
+  // 纸尿裤领用登记
+  form.monthlyPrice = formData.monthlyPrice || 0
+  form.diaperMCount = formData.diaperMCount || 0
+  form.diaperLCount = formData.diaperLCount || 0
+  form.diaperXLCount = formData.diaperXLCount || 0
+  form.diaperPadCount = formData.diaperPadCount || 0
+  form.pullUpCount = formData.pullUpCount || 0
+  form.carePadCount = formData.carePadCount || 0
+  form.nurseSignature = formData.nurseSignature || ''
+  form.totalAmount = formData.totalAmount || 0
+}
+
+/** 重置纸尿裤领用登记表单数据 */
+const resetPerceptionForm = () => {
+  form.assessor = ''
+  form.assessDate = ''
+
+  // 纸尿裤领用登记
+  form.monthlyPrice = 0
+  form.diaperMCount = 0
+  form.diaperLCount = 0
+  form.diaperXLCount = 0
+  form.diaperPadCount = 0
+  form.pullUpCount = 0
+  form.carePadCount = 0
+  form.nurseSignature = ''
+  form.totalAmount = 0
+}
+
+/** 打开弹窗 */
+const open = async (tenantId, id?: any, detail: boolean = false) => {
+  resetForm()
+  dialogVisible.value = true
+  dataForm.value.id = id || undefined
+  dataForm.value.tenantId = tenantId
+  isDetail.value = detail
+  try {
+    buildList.value = await getBuildList({tenantIds: tenantId})
+  }catch (e) {}
+
+  if (id) {
+    title.value = "编辑-纸尿裤领用登记"
+    // 加载登记数据
+    await loadDangerousGoodsData(id)
+  } else {
+    title.value = "新增-纸尿裤领用登记"
+
+  }
+}
+
+/** 加载登记数据 */
+const loadDangerousGoodsData = async (id: number) => {
+  try {
+    const res = await diaperReceiveGetById(id)
+    if (res) {
+      // 填充长者基本信息
+      dataForm.value.elderName = res.elderName || ''
+      dataForm.value.elderId = res.elderId || ''
+      dataForm.value.elderSex = res.elderSex || ''
+      dataForm.value.bedName = res.bedName || ''
+      dataForm.value.checkInTime = res.checkInTime || ''
+      dataForm.value.contractNumber = res.fileNumber || ''
+      dataForm.value.elderAge = res.elderAge || ''
+      await selectElderRef.value.upData(res.elderName, res.elderId)
+      // 解析 assessData
+      if (res.assessData) {
+        const formData = JSON.parse(res.assessData)
+        deserializeFormData(formData)
+      }
+    }
+  } catch (error) {
+    message.error('加载纸尿裤领用登记数据失败')
+  }
+}
+
+
+
+const form = reactive({
+  // 基本信息
+  assessor: '',
+  assessDate: '',
+
+  // 纸尿裤领用登记
+  monthlyPrice: 0,        // 包月价格
+  diaperMCount: 0,        // 互爱纸尿裤m码数量
+  diaperLCount: 0,        // 纸尿裤L码数量
+  diaperXLCount: 0,       // 纸尿裤XL码数量
+  diaperPadCount: 0,      // 互爱尿片数量
+  pullUpCount: 0,         // 拉拉裤数量
+  carePadCount: 0,        // 护理垫数量
+  nurseSignature: '',     // 护理员签名
+  totalAmount: 0          // 合计金额
+})
+
+// 计算合计金额
+const calculateTotal = () => {
+  const monthly = Number(form.monthlyPrice) || 0
+  const diaperM = (Number(form.diaperMCount) || 0) * 28
+  const diaperL = (Number(form.diaperLCount) || 0) * 29.8
+  const diaperXL = (Number(form.diaperXLCount) || 0) * 32
+  const diaperPad = (Number(form.diaperPadCount) || 0) * 38
+  const pullUp = (Number(form.pullUpCount) || 0) * 48
+  const carePad = (Number(form.carePadCount) || 0) * 17.55
+
+  form.totalAmount = Math.round((monthly + diaperM + diaperL + diaperXL + diaperPad + pullUp + carePad) * 100) / 100
+}
+
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  if (formLoading.value) {
+    return
+  }
+  formLoading.value = true
+  // 提交请求
+    try {
+      const assessData = serializeFormData()
+      const tempParams = {
+        ...dataForm.value,
+        assessData: JSON.stringify(assessData),
+        assessor: form.assessor,
+        assessDate: form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : ''
+      }
+
+    if (dataForm.value.id) {
+      const res = await diaperReceiveUpdate(tempParams)
+      if (res) {
+        message.success(t('common.updateSuccess'))
+        dialogVisible.value = false
+        // 发送操作成功的事件
+        emit('success')
+      }
+    } else {
+      const res = await diaperReceiveCreate(tempParams)
+      if (res) {
+        message.success(t('common.createSuccess'))
+        dialogVisible.value = false
+        // 发送操作成功的事件
+        emit('success')
+      }
+    }
+  } finally {
+    setTimeout(() => {
+      formLoading.value = false
+    }, 500)
+  }
+}
+
+
+
+/** 重置表单 */
+const resetForm = () => {
+  dataForm.value = {
+    id: undefined,
+    idCard: '',
+    buildId: '',
+    floorId: '',
+    floorName: '',
+    contractNumber: '', //档案号
+    elderName: '',//长者姓名
+    bedName: '', //床位号
+    elderAge: '', //年龄
+    elderSex: '', //性别
+    checkInTime: '', //入院日期
+    elderId: '',
+    tenantId: undefined
+  }
+  formRef.value?.resetFields()
+
+  // 重置感知觉与沟通评估表表单
+  resetPerceptionForm()
+}
+
+// 关闭表单
+const handleClosed = () => {
+  dialogVisible.value = false
+  resetForm()
+}
+
+
+
+</script>
+
+<style scoped lang="scss">
+.mmse-form {
+  max-width: 1200px;
+  margin: 0 auto;
+  background: #fff;
+
+  .form-title {
+    text-align: center;
+    font-size: 24px;
+    font-weight: bold;
+    margin-bottom: 20px;
+  }
+
+
+
+  .info-row {
+    display: flex;
+    gap: 40px;
+    width: 100%;
+    flex-direction: row;
+    align-items: center;
+    margin-bottom: 10px;
+
+    .info-item {
+      display: flex;
+      align-items: center;
+      gap: 8px;
+
+      .label {
+        width: 82px;
+        text-align: right;
+        margin-right: 4px;
+        white-space: nowrap;
+      }
+    }
+  }
+
+
+  .form-body {
+    border: 1px solid #333;
+    padding: 15px;
+
+    .diaper-table-wrapper {
+      margin-bottom: 20px;
+
+      .diaper-table {
+        width: 100%;
+        border-collapse: collapse;
+        border: 1px solid #333;
+
+        th, td {
+          border: 1px solid #333;
+          padding: 10px 8px;
+          text-align: center;
+          vertical-align: middle;
+        }
+
+        th {
+          background: #f5f7fa;
+          font-weight: bold;
+          font-size: 12px;
+        }
+
+        .col-monthly {
+          width: 80px;
+          background: #e8f4f8;
+        }
+
+        .col-product {
+          width: 100px;
+          font-size: 11px;
+        }
+
+        .col-sign {
+          width: 100px;
+        }
+
+        .col-total {
+          width: 100px;
+          background: #fffbe6;
+        }
+
+        tbody {
+          tr {
+            height: 60px;
+          }
+
+          td {
+            .total-cell {
+              background: #f5f7fa;
+            }
+
+            .total-amount {
+              font-weight: bold;
+              font-size: 14px;
+              color: #f56c6c;
+            }
+          }
+        }
+      }
+    }
+
+    .dangerous-goods-table {
+      margin-bottom: 20px;
+
+      .goods-table {
+        width: 100%;
+        border-collapse: collapse;
+        border: 1px solid #333;
+
+        th, td {
+          border: 1px solid #333;
+          padding: 10px 8px;
+          text-align: center;
+          vertical-align: middle;
+        }
+
+        th {
+          background: #f5f7fa;
+          font-weight: bold;
+          font-size: 14px;
+        }
+
+        .col-no {
+          width: 50px;
+        }
+
+        .col-bed {
+          width: 80px;
+        }
+
+        .col-name {
+          width: 80px;
+        }
+
+        .col-goods-title {
+          background: #f5f7fa;
+          font-weight: bold;
+        }
+
+        .col-goods {
+          width: 100px;
+        }
+
+        .col-storage {
+          width: 120px;
+        }
+
+        .col-sign {
+          width: 120px;
+        }
+
+        .col-remark {
+          width: 150px;
+        }
+
+        tbody {
+          td {
+            .el-input {
+              width: 100%;
+            }
+
+            .el-textarea {
+              width: 100%;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  .section {
+    margin-bottom: 20px;
+
+    &:last-child {
+      margin-bottom: 0;
+    }
+
+    .section-title {
+      font-weight: bold;
+      margin-bottom: 10px;
+    }
+  }
+
+  .form-item {
+    display: flex;
+    align-items: center;
+    margin-bottom: 12px;
+    flex-wrap: wrap;
+    gap: 8px;
+
+    .item-number {
+      font-weight: bold;
+      min-width: 25px;
+    }
+
+    .item-label {
+      white-space: nowrap;
+      min-width: fit-content;
+    }
+
+  }
+
+  .other-input {
+    width: 200px;
+    margin-left: 10px;
+  }
+
+  // 调整 Element Plus 组件样式
+  :deep(.el-input__inner) {
+    height: 28px;
+    line-height: 28px;
+    border-top: none;
+    border-left: none;
+    border-right: none;
+    border-radius: 0;
+    padding: 0 4px;
+
+    &:focus {
+      border-color: #409eff;
+    }
+  }
+
+
+  :deep(.el-checkbox__label),
+  :deep(.el-radio__label) {
+    padding-left: 4px;
+  }
+}
+.row{
+  margin-bottom: 12px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  text{
+    text-align: right;
+    margin-right: 4px;
+    width: 82px;
+  }
+}
+
+// 感知觉与沟通评估表 特有样式
+.total-score-section {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  margin-bottom: 20px;
+
+  .total-score {
+    display: flex;
+    align-items: baseline;
+    gap: 4px;
+
+    .score-label {
+      font-size: 16px;
+      font-weight: bold;
+    }
+
+    .score-value {
+      font-size: 28px;
+      font-weight: bold;
+      color: #409eff;
+    }
+
+    .score-max {
+      font-size: 14px;
+      color: #909399;
+    }
+  }
+
+  .risk-level {
+    font-size: 16px;
+    font-weight: bold;
+    padding: 8px 16px;
+    border-radius: 4px;
+
+    &.risk-none {
+      color: #67c23a;
+      background: #f0f9eb;
+    }
+
+    &.risk-low {
+      color: #e6a23c;
+      background: #fdf6ec;
+    }
+
+    &.risk-medium {
+      color: #f56c6c;
+      background: #fef0f0;
+    }
+
+    &.risk-high {
+      color: #f56c6c;
+      background: #fef0f0;
+      border: 1px solid #f56c6c;
+    }
+  }
+}
+
+.assessment-table {
+  width: 100%;
+  border-collapse: collapse;
+  margin-bottom: 20px;
+
+  table {
+    width: 100%;
+    border: 1px solid #333;
+
+    th, td {
+      border: 1px solid #333;
+      padding: 12px;
+      text-align: left;
+    }
+
+    th {
+      background: #f5f7fa;
+      font-weight: bold;
+      text-align: center;
+    }
+
+    .criteria-col {
+      width: 60%;
+    }
+
+    .score-col {
+      width: 15%;
+      text-align: center;
+    }
+
+    .select-col {
+      width: 25%;
+      text-align: center;
+    }
+
+    .criteria {
+      text-align: left;
+    }
+
+    .score {
+      text-align: center;
+      font-weight: bold;
+    }
+
+    .select {
+      text-align: center;
+
+      :deep(.el-radio) {
+        margin-right: 0;
+      }
+    }
+  }
+}
+
+.remark-section {
+  margin: 15px 0;
+  padding: 12px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .remark-label {
+    font-weight: bold;
+    color: #606266;
+  }
+
+  .remark-text {
+    color: #606266;
+  }
+}
+
+.risk-judgment-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .risk-judgment-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .risk-options {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20px;
+
+    :deep(.el-radio) {
+      margin-right: 0;
+    }
+  }
+}
+
+.preventive-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .preventive-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .preventive-options {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 15px;
+
+    :deep(.el-checkbox) {
+      margin-right: 20px;
+      margin-bottom: 8px;
+    }
+
+    .other-input {
+      width: 200px;
+      margin-left: 10px;
+    }
+  }
+}
+
+.signature-section {
+  margin: 20px 0;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .signature-row {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    gap: 20px;
+  }
+
+  .signature-item {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+
+    &.date-item {
+      :deep(.el-date-picker) {
+        width: 150px;
+      }
+    }
+  }
+
+  .signature-label {
+    font-weight: bold;
+    white-space: nowrap;
+  }
+
+  .signature-input {
+    width: 150px;
+  }
+
+  .date-picker {
+    width: 150px;
+  }
+}
+
+.note-section {
+  margin-top: 20px;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+
+  .note-title {
+    font-weight: bold;
+    font-size: 16px;
+    margin-bottom: 12px;
+    color: #303133;
+  }
+
+  .note-content {
+    font-size: 13px;
+    line-height: 1.8;
+    color: #606266;
+
+    p {
+      margin: 5px 0;
+    }
+
+    .indent {
+      margin-left: 20px;
+    }
+  }
+}
+</style>

+ 390 - 0
src/views/elderly/nursing/records/paper-diaper-receive/index.vue

@@ -0,0 +1,390 @@
+<template>
+  <ContentWrap>
+    <!-- 工单记录 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="110px"
+    >
+      <el-form-item label="长者姓名">
+        <el-input
+          v-model="queryParams.elderName"
+          placeholder="长者姓名"
+          class="!w-240px"
+          clearable
+        />
+      </el-form-item>
+
+      <el-form-item label="楼栋">
+        <el-select v-model="queryParams.buidId" placeholder="选择楼栋" style="width: 180px" @change="handleBuildChange">
+          <el-option v-for="(item,index) in buildList" :key="index" :label="item.buildName" :value="item.id" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="楼层">
+        <el-select  v-model="queryParams.floorId" placeholder="选择楼层" style="width: 180px" >
+          <el-option v-for="(item,index) in floorList" :key="index" :label="item.floorName" :value="item.id" />
+        </el-select>
+      </el-form-item>
+
+
+      <el-form-item label="登记日期">
+        <el-date-picker
+          size="default"
+          ref="selectRef"
+          class="!w-240px"
+          v-model="queryParams.discoveryTime"
+          type="daterange"
+          :clearable="true"
+          :editable="false"
+          placeholder="选择工单日期"
+          value-format="YYYY-MM-DD"
+          format="YYYY-MM-DD"
+          date-format="YYYY-MM-DD"
+        />
+      </el-form-item>
+
+      <el-form-item>
+        <el-button @click="handleQuery" style="margin-left: 2vw"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <div class="mb-10px">
+
+      <ButtonAdd @click="openForm(undefined)"  />
+      <el-button @click="inputH" type="success"><Icon icon="fa:cloud-upload" :size="16" class="mr-1"/>导入</el-button>
+      <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">
+        <template #default="scope">
+          {{
+            scope.$index + (queryParams.pageNo * queryParams.pageSize - queryParams.pageSize) + 1
+          }}
+        </template>
+      </el-table-column>
+
+
+      <el-table-column prop="elderName" header-align="center" align="center" label="长者姓名" min-width="120" show-overflow-tooltip/>
+      <el-table-column prop="elderSex" header-align="center" align="center" label="性别" min-width="90" show-overflow-tooltip/>
+      <el-table-column prop="elderAge" header-align="center" align="center" label="年龄" min-width="90" show-overflow-tooltip/>
+      <el-table-column prop="serviceItem" header-align="center" align="center" label="服务项目" min-width="200" show-overflow-tooltip/>
+      <el-table-column prop="serviceName" header-align="center" align="center" label="服务人员姓名" min-width="160" show-overflow-tooltip/>
+      <el-table-column prop="orderTime" header-align="center" align="center" label="订单时间" min-width="180" show-overflow-tooltip>
+        <template #default="scope">
+          {{(formatToDateTime(scope.row.orderTime))}}
+        </template>
+      </el-table-column>
+      <el-table-column prop="comeTime" header-align="center" align="center" label="上门时间" min-width="180" show-overflow-tooltip>
+        <template #default="scope">
+          {{formatToDateTime(scope.row.serviceBeginTime)}}
+        </template>
+      </el-table-column>
+      <el-table-column prop="elderAddress" header-align="center" align="center" label="地址" min-width="220" show-overflow-tooltip/>
+      <el-table-column prop="isExpire" header-align="center" align="center" label="是否过期" min-width="120" show-overflow-tooltip/>
+      <el-table-column prop="orderStatus" header-align="center" align="center" label="订单状态" min-width="160" show-overflow-tooltip/>
+
+      <el-table-column label="操作" align="center" width="200" fixed="right">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openFormEdit(scope.row, scope.row.id)"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="warning"
+            @click="openFormDetail(scope.row.id)"
+          >
+            详情
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="openClose(scope.row)"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </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"
+  />
+
+
+  <Import
+    ref="importRef"
+    @success="getList"
+    :config="{
+      title: '导入',
+      downloadUrl: 'elderly-service-order/get-import-template',
+      excelTempName: '居家工单-【导入】模板',
+      importUrl: '/elderly-service-order/import',
+      failExportUrl: '',
+    }"
+  />
+
+</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 {
+  careRecordsPage, elderlyServiceOrderDelete, elderlyServiceOrderPage,
+} from "@/api/member/appointment";
+import download from "@/utils/download";
+import { useUserStore } from '@/store/modules/user'
+import {formatToDate, formatToDateTime, getCurrentMonthRange} from "@/utils/dateUtil";
+import * as UserApi from "@/api/system/user";
+import Import from "@/components/ImportFile/index.vue";
+import {ref} from "vue";
+import {getBuildList} from "@/api/system/badManage";
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+const userStore = useUserStore()
+const loading = ref(true) // 列表的加载中
+const detailRef = ref()
+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,
+  elderName: '',
+  elderPhone: '',
+  discoveryTime: ["2025-12-01",formatToDate()],
+  tenantIds: userStore.orgTenantId[0]
+})
+const queryFormRef = ref() // 搜索的表单
+
+const inputH = () => {
+  importRef.value.open(queryParams.tenantIds[0])
+}
+// 打开导出弹窗
+const handleImportCard = async () => {
+  try {
+    const queryParams = reactive({
+      pageNo: 1,
+      pageSize: 1000,
+      tenantIds: userStore.orgTenantId,
+    })
+    const data = await UserApi.exportElderlyServiceOrder(queryParams)
+    download.excel(data, '工单报表数据.xls')
+  }catch (e) {
+
+  }
+
+
+  // exportConfig.value = {
+  //   title: "批量导出",
+  //   batchMin: 1,
+  //   batchMax: 999,
+  //   countMin: 1,
+  //   countMax: 500,
+  //   defaultBatch: 1,
+  //   defaultCount: 500,
+  //   description: [
+  //     '1. 请输入需要导出的数量',
+  //     '2. 一次导不完的话,输入批次 2 再次导出,以此类推。',
+  //     '3. 建议单次导出数量不超过500,以免影响系统性能',
+  //     '4. 导出需要较长时间,请耐心等待。'
+  //   ]
+  // }
+  // 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 (_) {}
+
+}
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    //let queryP = {...queryParams,discoveryTime:queryParams.discoveryTime?[queryParams.discoveryTime[0]+" 00:00:00",queryParams.discoveryTime[1]+" 23:59:59"]:null}
+    const data = await elderlyServiceOrderPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = async () => {
+  if (!queryFormRef.value) return
+  const valid = await queryFormRef.value.validate()
+  if (!valid) return
+  queryParams.pageNo = 1
+  await getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryParams.elderName = ''
+  queryParams.tenantId = userStore.orgTenantId[0]
+  queryParams.discoveryTime= ["2025-12-01",formatToDate()]
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (id?: number) => {
+  // if(queryParams.tenantIds.length == 0 || queryParams.tenantIds.length > 1){
+  //   message.error('新增只能选择一个机构')
+  //   return
+  // }
+  formRef.value.open(queryParams.tenantIds, id,false)
+}
+
+const editRef = ref()
+const openFormEdit = (row: any = {}, id?: number) => {
+  formRef.value.open(row.tenantId, id,false)
+}
+
+
+const openFormDetail = (id?: number) => {
+  formRef.value.open(undefined,id,true)
+}
+
+
+
+
+
+const openClose = async (item) => {
+  try {
+    console.log("任务ID",item)
+    const res = await message.confirm('确定要删除吗?', '提示')
+    if (res == 'confirm') {
+      // 发起
+      try {
+        const res = await elderlyServiceOrderDelete(item.id)
+        if (res){
+          message.success(t('common.updateSuccess'))
+        }
+      }catch(err) {}
+    }
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 取消按钮操作 */
+const cancelDelete = async (id: number) => {
+  try {
+    // 取消的二次确认
+    await message.cancelConfirm()
+    // 发起取消
+    // await elderlyBakDel(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+
+const buildList = ref([])
+const floorList = ref([])
+
+const route = useRoute()
+/** 初始化 **/
+onMounted(async () => {
+  if(route.query && route.query.elderName){
+    queryParams.elderName = route.query.elderName as string
+  }
+  getList()
+  try {
+    buildList.value = await getBuildList({tenantIds: queryParams.tenantId})
+  }catch (e) {}
+})
+
+// 表头格式
+const tableHeaderColor = ({ rowIndex }: any) => {
+  if (rowIndex === 0) {
+    return {
+      backgroundColor: '#f8f8f9',
+      color: '#666666',
+      fontWeight: 'bold'
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss"></style>