Quellcode durchsuchen

电子合同接口对接

chenjun vor 1 Monat
Ursprung
Commit
77f6468f39

+ 113 - 19
src/api/elderly/contracts/index.ts

@@ -8,6 +8,13 @@ export const riskDisclosure_findPage = (query) => {
   })
 }
 
+// 获取列表
+export const riskDisclosure_findPage2 = (elderId) => {
+  return request.get({
+    url: `/elderly/extra/riskDisclosure/getListByElderId?elderId=${elderId}`
+  })
+}
+
 // 新增附件
 export const extra_riskDisclosure_create = (data) => {
   return request.post({
@@ -380,12 +387,14 @@ export const guardianPartyB_update = (data) => {
 }
 export const guardianPartyB_getById = (id: number | string) => {
   return request.get({
-    url: `/elderly/extra/partyBGuardianCertificate/getDetail/${id}`
+    url: `/elderly/extra/partyBGuardianCertificate/getDetail`,
+    params: { id }
   })
 }
 export const guardianPartyB_delete = (id: number | string) => {
   return request.delete({
-    url: `/elderly/extra/partyBGuardianCertificate/delete/${id}`
+    url: `/elderly/extra/partyBGuardianCertificate/delete`,
+     params: { id }
   })
 }
 
@@ -410,101 +419,186 @@ export const registrationCertificateCivilAffairs_update = (data) => {
 }
 export const registrationCertificateCivilAffairs_getById = (id: number | string) => {
   return request.get({
-    url: `/elderly/extra/partyACertificate/getDetail?id=${id}`
+    url: `/elderly/extra/partyACertificate/getDetail`,
+    params: { id }
   })
 }
 export const registrationCertificateCivilAffairs_delete = (id: number | string) => {
   return request.delete({
-    url: `/elderly/extra/partyACertificate/delete/${id}`
+    url: `/elderly/extra/partyACertificate/delete`,
+    params: { id }
   })
 }
 
 // ========== 老年人能力综合评估结果 ==========
 export const comprehensiveAssessmentCapabilities_findPage = (query) => {
   return request.get({
-    url: `/elderly/extra/comprehensiveAssessmentCapabilities/findPage`,
+    url: `/elderly/extra/elderlyAbilityEvaluation/findPage`,
     params: query
   })
 }
 export const comprehensiveAssessmentCapabilities_create = (data) => {
   return request.post({
-    url: `/elderly/extra/comprehensiveAssessmentCapabilities/create`,
+    url: `/elderly/extra/elderlyAbilityEvaluation/create`,
     data
   })
 }
 export const comprehensiveAssessmentCapabilities_update = (data) => {
   return request.post({
-    url: `/elderly/extra/comprehensiveAssessmentCapabilities/update`,
+    url: `/elderly/extra/elderlyAbilityEvaluation/update`,
     data
   })
 }
 export const comprehensiveAssessmentCapabilities_getById = (id: number | string) => {
   return request.get({
-    url: `/elderly/extra/comprehensiveAssessmentCapabilities/getById/${id}`
+    url: `/elderly/extra/elderlyAbilityEvaluation/getDetail`,
+    params: { id }
   })
 }
 export const comprehensiveAssessmentCapabilities_delete = (id: number | string) => {
   return request.delete({
-    url: `/elderly/extra/comprehensiveAssessmentCapabilities/delete/${id}`
+    url: `/elderly/extra/elderlyAbilityEvaluation/delete`,
+    params: { id }
   })
 }
 
 // ========== 首次服务项目确认表 ==========
 export const firstServiceProjectConfirmation_findPage = (query) => {
   return request.get({
-    url: `/elderly/extra/firstServiceProjectConfirmation/findPage`,
+    url: `/elderly/extra/firstServiceConfirmation/findPage`,
     params: query
   })
 }
 export const firstServiceProjectConfirmation_create = (data) => {
   return request.post({
-    url: `/elderly/extra/firstServiceProjectConfirmation/create`,
+    url: `/elderly/extra/firstServiceConfirmation/create`,
     data
   })
 }
 export const firstServiceProjectConfirmation_update = (data) => {
   return request.post({
-    url: `/elderly/extra/firstServiceProjectConfirmation/update`,
+    url: `/elderly/extra/firstServiceConfirmation/update`,
     data
   })
 }
 export const firstServiceProjectConfirmation_getById = (id: number | string) => {
   return request.get({
-    url: `/elderly/extra/firstServiceProjectConfirmation/getById/${id}`
+    url: `/elderly/extra/firstServiceConfirmation/getDetail`,
+    params: { id }
   })
 }
 export const firstServiceProjectConfirmation_delete = (id: number | string) => {
   return request.delete({
-    url: `/elderly/extra/firstServiceProjectConfirmation/delete/${id}`
+    url: `/elderly/extra/firstServiceConfirmation/delete`,
+    params: { id }
   })
 }
 
 // ========== 变更事项确认表 ==========
 export const changeConfirmationForm_findPage = (query) => {
   return request.get({
-    url: `/elderly/extra/changeConfirmationForm/findPage`,
+    url: `/elderly/extra/changeConfirmation/findPage`,
     params: query
   })
 }
 export const changeConfirmationForm_create = (data) => {
   return request.post({
-    url: `/elderly/extra/changeConfirmationForm/create`,
+    url: `/elderly/extra/changeConfirmation/create`,
     data
   })
 }
 export const changeConfirmationForm_update = (data) => {
   return request.post({
-    url: `/elderly/extra/changeConfirmationForm/update`,
+    url: `/elderly/extra/changeConfirmation/update`,
     data
   })
 }
 export const changeConfirmationForm_getById = (id: number | string) => {
   return request.get({
-    url: `/elderly/extra/changeConfirmationForm/getById/${id}`
+    url: `/elderly/extra/changeConfirmation/getDetail`,
+    params: { id }
   })
 }
 export const changeConfirmationForm_delete = (id: number | string) => {
   return request.delete({
-    url: `/elderly/extra/changeConfirmationForm/delete/${id}`
+    url: `/elderly/extra/changeConfirmation/delete`,
+    params: { id }
+  })
+}
+
+// ========== 按长者ID查询列表 ==========
+export const checkInRegistration_getListByElderId = (elderId: number | string) => {
+  return request.get({
+    url: `/elderly/extra/checkInTab/getListByElderId?elderId=${elderId}`
+  })
+}
+export const elderSafetyCommitment_getListByElderId = (elderId: number | string) => {
+  return request.get({
+    url: `/elderly/extra/safetyCommitment/getListByElderId?elderId=${elderId}`
+  })
+}
+export const outingConfirmation_getListByElderId = (elderId: number | string) => {
+  return request.get({
+    url: `/elderly/extra/outingConfirmationForm/getListByElderId?elderId=${elderId}`
+  })
+}
+export const signatureProxyApplication_getListByElderId = (elderId: number | string) => {
+  return request.get({
+    url: `/elderly/extra/signatureProxyApplication/getListByElderId?elderId=${elderId}`
+  })
+}
+export const powerOfAttorney_getListByElderId = (elderId: number | string) => {
+  return request.get({
+    url: `/elderly/extra/powerOfAttorney/getListByElderId?elderId=${elderId}`
+  })
+}
+export const delegationAgentConfirmation_getListByElderId = (elderId: number | string) => {
+  return request.get({
+    url: `/elderly/extra/authorizedAgentConfirmation/getListByElderId?elderId=${elderId}`
+  })
+}
+export const serviceChargingStandards_getListByElderId = (elderId: number | string) => {
+  return request.get({
+    url: `/elderly/extra/orgServiceScopeFee/getListByElderId?elderId=${elderId}`
+  })
+}
+export const roomFacilitiesEquipment_getListByElderId = (elderId: number | string) => {
+  return request.get({
+    url: `/elderly/extra/roomFacilityList/getListByElderId?elderId=${elderId}`
+  })
+}
+export const explanationExaminationReport_getListByElderId = (elderId: number | string) => {
+  return request.get({
+    url: `/elderly/extra/physicalExamReport/getListByElderId?elderId=${elderId}`
+  })
+}
+export const partyBIdentificationDocument_getListByElderId = (elderId: number | string) => {
+  return request.get({
+    url: `/elderly/extra/partyBCertificate/getListByElderId?elderId=${elderId}`
+  })
+}
+export const guardianPartyB_getListByElderId = (elderId: number | string) => {
+  return request.get({
+    url: `/elderly/extra/partyBGuardianCertificate/getListByElderId?elderId=${elderId}`
+  })
+}
+export const registrationCertificateCivilAffairs_getListByElderId = (elderId: number | string) => {
+  return request.get({
+    url: `/elderly/extra/partyACertificate/getListByElderId?elderId=${elderId}`
+  })
+}
+export const comprehensiveAssessmentCapabilities_getListByElderId = (elderId: number | string) => {
+  return request.get({
+    url: `/elderly/extra/elderlyAbilityEvaluation/getListByElderId?elderId=${elderId}`
+  })
+}
+export const firstServiceProjectConfirmation_getListByElderId = (elderId: number | string) => {
+  return request.get({
+    url: `/elderly/extra/firstServiceConfirmation/getListByElderId?elderId=${elderId}`
+  })
+}
+export const changeConfirmationForm_getListByElderId = (elderId: number | string) => {
+  return request.get({
+    url: `/elderly/extra/changeConfirmation/getListByElderId?elderId=${elderId}`
   })
 }

+ 308 - 126
src/views/elderly/contracts/ContractManageForm.vue

@@ -1,6 +1,5 @@
 <script setup lang="ts">
 import { reactive, ref, computed, nextTick } from 'vue'
-import html2pdf from 'html2pdf.js'
 import ContractBody from './components/ContractBody.vue'
 import AttachmentPage from './components/AttachmentPage.vue'
 import AttachmentSelector from './components/AttachmentSelector.vue'
@@ -18,6 +17,43 @@ import ExplanationExaminationReportBody from './components/ExplanationExaminatio
 import DocumentAttachmentBody from './components/DocumentAttachmentBody.vue'
 import FirstServiceProjectConfirmationBody from './components/FirstServiceProjectConfirmationBody.vue'
 import ChangeConfirmationFormBody from './components/ChangeConfirmationFormBody.vue'
+import {
+  riskDisclosure_getById,
+  checkInRegistration_getById,
+  elderSafetyCommitment_getById,
+  outingConfirmation_getById,
+  signatureProxyApplication_getById,
+  powerOfAttorney_getById,
+  delegationAgentConfirmation_getById,
+  serviceChargingStandards_getById,
+  roomFacilitiesEquipment_getById,
+  explanationExaminationReport_getById,
+  partyBIdentificationDocument_getById,
+  guardianPartyB_getById,
+  registrationCertificateCivilAffairs_getById,
+  comprehensiveAssessmentCapabilities_getById,
+  firstServiceProjectConfirmation_getById,
+  changeConfirmationForm_getById
+} from '@/api/elderly/contracts'
+
+const attachmentDetailMap: Record<string, (id: number | string) => Promise<any>> = {
+  attach_1: riskDisclosure_getById,
+  attach_2: checkInRegistration_getById,
+  attach_4: elderSafetyCommitment_getById,
+  attach_5: outingConfirmation_getById,
+  attach_6: signatureProxyApplication_getById,
+  attach_7: powerOfAttorney_getById,
+  attach_8: delegationAgentConfirmation_getById,
+  attach_9: serviceChargingStandards_getById,
+  attach_10: roomFacilitiesEquipment_getById,
+  attach_11: explanationExaminationReport_getById,
+  attach_12: partyBIdentificationDocument_getById,
+  attach_13: guardianPartyB_getById,
+  attach_14: registrationCertificateCivilAffairs_getById,
+  attach_15: comprehensiveAssessmentCapabilities_getById,
+  attach_16: firstServiceProjectConfirmation_getById,
+  attach_17: changeConfirmationForm_getById
+}
 
 const message = useMessage()
 
@@ -50,27 +86,21 @@ const attachmentList = [
 ]
 
 const attachments = reactive<Record<string, any>>(
-  attachmentList.reduce((acc: any, item) => {
-    // 固定内容附件(3=入住须知)默认展示,不需要从列表选择
-    if (item.no === 3) {
-      acc[`attach_${item.no}`] = { title: item.title }
-    } else {
-      acc[`attach_${item.no}`] = null
-    }
-    return acc
-  }, {} as Record<string, any>)
+  attachmentList.reduce(
+    (acc: any, item) => {
+      // 固定内容附件(3=入住须知)默认展示,不需要从列表选择
+      if (item.no === 3) {
+        acc[`attach_${item.no}`] = { id: '', title: item.title }
+      } else {
+        acc[`attach_${item.no}`] = null
+      }
+      return acc
+    },
+    {} as Record<string, any>
+  )
 )
 
-const riskDisclosureForm = reactive<Record<string, any>>({
-  elderName: '',
-  companyName: '颐年医养',
-  assessor: '',
-  assessDate: '',
-  partyBSign: '',
-  partyBDate: '',
-  partyCSign: '',
-  partyCDate: ''
-})
+const riskDisclosureForm = reactive<Record<string, any>>({})
 
 const safetyCommitmentForm = reactive<Record<string, any>>({
   elderSign: '',
@@ -209,11 +239,20 @@ const checkInRegistrationForm = reactive<Record<string, any>>({
   checkInReason: '',
   pastHistory: {
     hasDisease: false,
-    diseases: [{ name: '', confirmTime: '' }, { name: '', confirmTime: '' }],
+    diseases: [
+      { name: '', confirmTime: '' },
+      { name: '', confirmTime: '' }
+    ],
     hasSurgery: false,
-    surgeries: [{ name: '', time: '' }, { name: '', time: '' }],
+    surgeries: [
+      { name: '', time: '' },
+      { name: '', time: '' }
+    ],
     hasTrauma: false,
-    traumas: [{ part: '', time: '' }, { part: '', time: '' }]
+    traumas: [
+      { part: '', time: '' },
+      { part: '', time: '' }
+    ]
   },
   currentDiseases: [
     { name: '', confirmTime: '', currentStatus: '' },
@@ -291,6 +330,22 @@ const handleContractDataChange = (data: any) => {
   contractSignatureData.value.partyCDate = data.partyCDate || ''
 }
 
+const handleAttachmentsLoad = (data: Record<string, any>) => {
+  console.log('收到', data)
+  if (!data) return
+  Object.keys(data).forEach((key) => {
+    if (attachments.hasOwnProperty(key)) {
+      console.log('AAAAAAA', data[key])
+      attachments[key] = data[key]
+      if (key == 'attach_1') {
+        Object.assign(riskDisclosureForm, data[key])
+      } else if (key == 'attach_2') {
+        Object.assign(checkInRegistrationForm, data[key])
+      }
+    }
+  })
+}
+
 const selectedAttachments = computed(() => {
   return attachmentList.filter((a) => {
     const data = attachments[`attach_${a.no}`]
@@ -314,10 +369,10 @@ const selectorVisible = ref<{
 })
 
 const type_c = ref(1)
-const open = (row?: any,type=1) => {
+const open = (row?: any, type = 1) => {
   recordRow.value = row || null
   type_c.value = type
-  isTextMode.value = type_c.value != 1;
+  isTextMode.value = type_c.value != 1
   formLoading.value = true
   isPrint.value = false
   attachmentList.forEach((it) => {
@@ -328,45 +383,7 @@ const open = (row?: any,type=1) => {
       attachments[`attach_${it.no}`] = null
     }
   })
-  riskDisclosureForm.elderName = ''
-  riskDisclosureForm.assessor = ''
-  riskDisclosureForm.assessDate = ''
-  riskDisclosureForm.partyBSign = ''
-  riskDisclosureForm.partyBDate = ''
-  riskDisclosureForm.partyCSign = ''
-  riskDisclosureForm.partyCDate = ''
-
-  // 重置长者安全承诺书表单
-  safetyCommitmentForm.elderSign = ''
-  safetyCommitmentForm.guardianSign = ''
-  safetyCommitmentForm.signDate = ''
-
-  // 重置长者外出情况确认书表单
-  outingConfirmationForm.elderName = ''
-  outingConfirmationForm.outingAbility = ''
-  outingConfirmationForm.elderSign = ''
-  outingConfirmationForm.guardianSign = ''
-  outingConfirmationForm.signDate = ''
-
-  // 重置入住登记表表单
-  Object.keys(checkInRegistrationForm).forEach((key) => {
-    const val = (checkInRegistrationForm as any)[key]
-    if (Array.isArray(val)) {
-      ;(checkInRegistrationForm as any)[key] = []
-    } else if (typeof val === 'object' && val !== null) {
-      ;(checkInRegistrationForm as any)[key] = JSON.parse(JSON.stringify(val))
-    } else {
-      ;(checkInRegistrationForm as any)[key] = ''
-    }
-  })
 
-  contractSignatureData.value.partyASign = ''
-  contractSignatureData.value.partyALegalSign = ''
-  contractSignatureData.value.partyADate = ''
-  contractSignatureData.value.partyBSign = ''
-  contractSignatureData.value.partyBDate = ''
-  contractSignatureData.value.partyCSign = ''
-  contractSignatureData.value.partyCDate = ''
   visible.value = true
   setTimeout(() => {
     formLoading.value = false
@@ -384,6 +401,9 @@ const emit = defineEmits(['refreshTree'])
 const handleSave = async () => {
   formLoading.value = true
   try {
+    if (contractBodyRef.value) {
+      await contractBodyRef.value.saveContract()
+    }
     message.success('保存成功')
     visible.value = false
     emit('refreshTree')
@@ -410,8 +430,6 @@ const handlePrint = async () => {
   }, 500)
 }
 
-
-
 const toggleTextMode = () => {
   isTextMode.value = !isTextMode.value
 }
@@ -436,46 +454,70 @@ const handleAttachmentDelete = (attach: any) => {
   message.success(`已删除:${attach.title}`)
 }
 
-const handleAttachmentSelect = (row: any) => {
+const handleAttachmentSelect = async (row: any) => {
   const key = selectorVisible.value.current
+  console.log('KEY值:', key, row, attachments)
   if (key) {
-    attachments[key] = row
-    // 附件 2:入住登记表,解析 assessData 到表单
-    if (key === 'attach_2' && row.assessData) {
+    const getDetail = attachmentDetailMap[key]
+    let fullData = row
+    if (getDetail && row.id) {
+      try {
+        const detail = await getDetail(row.id)
+        if (detail && detail.content) {
+          fullData = detail.content
+          const data = JSON.parse(fullData)
+          // 将id添加到数据中,方便后续操作
+          data.id = row.id
+          fullData = JSON.stringify(data)
+        }
+      } catch (error) {
+        console.error(`获取附件详情失败: ${key}`, error)
+      }
+    }
+    attachments[key] = fullData
+    if (key === 'attach_1' && fullData) {
+      try {
+        const data = JSON.parse(fullData)
+        if (data) {
+          Object.assign(riskDisclosureForm, data)
+        }
+      } catch (error) {
+        console.error('解析风险披露数据失败', error)
+      }
+    }
+    if (key === 'attach_2' && fullData) {
       try {
-        const data = JSON.parse(row.assessData)
-        if (data.checkInRegistration) {
-          Object.assign(checkInRegistrationForm, data.checkInRegistration)
-        } else {
+        const data = JSON.parse(fullData)
+        if (data) {
           Object.assign(checkInRegistrationForm, data)
         }
       } catch (error) {
         console.error('解析入住登记表数据失败', error)
       }
     }
-    // 附件 4:长者安全承诺书,解析 assessData 到表单
-    if (key === 'attach_4' && row.assessData) {
+    if (key === 'attach_4' && fullData) {
       try {
-        const data = JSON.parse(row.assessData)
-        if (data.safetyCommitment) {
-          Object.assign(safetyCommitmentForm, data.safetyCommitment)
+        const data = JSON.parse(fullData)
+        if (data) {
+          Object.assign(safetyCommitmentForm, data)
         }
       } catch (error) {
         console.error('解析长者安全承诺书数据失败', error)
       }
     }
-    // 附件 5:长者外出情况确认书,解析 assessData 到表单
-    if (key === 'attach_5' && row.assessData) {
+    if (key === 'attach_5' && fullData) {
       try {
-        const data = JSON.parse(row.assessData)
-        if (data.outingConfirmation) {
-          Object.assign(outingConfirmationForm, data.outingConfirmation)
+        const data = JSON.parse(fullData)
+        if (data) {
+          Object.assign(outingConfirmationForm, data)
         }
       } catch (error) {
         console.error('解析长者外出情况确认书数据失败', error)
       }
     }
-    message.success(`已选择:${row[activeTitleField(key)] || attachTitle(key)}`)
+    message.success(
+      `已选择:${fullData.elderName || row[activeTitleField(key)] || attachTitle(key)}`
+    )
   }
   selectorVisible.value.show = false
 }
@@ -497,6 +539,10 @@ const handleAttachmentSelectorClose = () => {
   selectorVisible.value.show = false
 }
 
+const handFormData = (data: any) => {
+  console.log('收到:', data)
+}
+
 const renderAttachmentContent = (key: string) => {
   const data = attachments[key]
   if (!data) return null
@@ -516,14 +562,32 @@ const renderAttachmentContent = (key: string) => {
       <div class="content-toolbar" v-if="!isPrint">
         <el-tag type="info" size="large">颐年集团养老服务合同</el-tag>
         <div class="toolbar-right">
-          <el-tooltip :content="isTextMode ? '切换为编辑模式(输入框)' : '切换为文本模式(打印预览)'" placement="top">
-            <el-button v-show="type_c==1" :type="isTextMode ? 'success' : 'default'" size="small" @click="toggleTextMode">
+          <el-tooltip
+            :content="isTextMode ? '切换为编辑模式(输入框)' : '切换为文本模式(打印预览)'"
+            placement="top"
+          >
+            <el-button
+              v-show="type_c == 1"
+              :type="isTextMode ? 'success' : 'default'"
+              size="small"
+              @click="toggleTextMode"
+            >
               {{ isTextMode ? '文本模式' : '编辑模式' }}
             </el-button>
           </el-tooltip>
-          <el-button v-show="type_c==1" type="primary" :loading="formLoading" size="small" @click="handleSave">保存</el-button>
+          <el-button
+            v-show="type_c == 1"
+            type="primary"
+            :loading="formLoading"
+            size="small"
+            @click="handleSave"
+            >保存</el-button
+          >
           <el-button size="small" @click="handleClose">关闭</el-button>
-          <el-tooltip placement="bottom" content="打印时目标打印机选择「Microsoft Print to PDF」;导出时目标打印机选择「另存为 PDF」">
+          <el-tooltip
+            placement="bottom"
+            content="打印时目标打印机选择「Microsoft Print to PDF」;导出时目标打印机选择「另存为 PDF」"
+          >
             <el-button type="success" size="small" @click="handlePrint">打印/导出</el-button>
           </el-tooltip>
         </div>
@@ -534,10 +598,19 @@ const renderAttachmentContent = (key: string) => {
         <div class="section-divider">
           <span>合同主体</span>
         </div>
-        <ContractBody ref="contractBodyRef" :record-row="recordRow" :is-text-mode="isTextMode" v-model="contractSignatureData" @update:data="handleContractDataChange" />
+        <ContractBody
+          ref="contractBodyRef"
+          :record-row="recordRow"
+          :is-text-mode="isTextMode"
+          v-model="contractSignatureData"
+          :attachment-ids="attachments"
+          @update:form-data="handFormData"
+          @update:data="handleContractDataChange"
+          @update:attachments="handleAttachmentsLoad"
+        />
 
         <!-- ============ 16个附件 ============ -->
-        <div class="section-divider" style="margin-top: 30px;">
+        <div class="section-divider" style="margin-top: 30px">
           <span>附件清单</span>
         </div>
 
@@ -570,57 +643,95 @@ const renderAttachmentContent = (key: string) => {
               />
             </div>
             <div v-else-if="attach.no === 4" class="attachment-content">
-              <ElderSafetyCommitmentBody v-model="safetyCommitmentForm" :is-text-mode="isTextMode" />
+              <ElderSafetyCommitmentBody
+                v-model="safetyCommitmentForm"
+                :is-text-mode="isTextMode"
+              />
             </div>
             <div v-else-if="attach.no === 5" class="attachment-content">
               <OutingConfirmationBody v-model="outingConfirmationForm" :is-text-mode="isTextMode" />
             </div>
             <div v-else-if="attach.no === 6" class="attachment-content">
-              <SignatureProxyApplicationBody v-model="signatureProxyForm" :is-text-mode="isTextMode" />
+              <SignatureProxyApplicationBody
+                v-model="signatureProxyForm"
+                :is-text-mode="isTextMode"
+              />
             </div>
             <div v-else-if="attach.no === 7" class="attachment-content">
               <PowerOfAttorneyBody v-model="powerOfAttorneyForm" :is-text-mode="isTextMode" />
             </div>
             <div v-else-if="attach.no === 8" class="attachment-content">
-              <DelegationAgentConfirmationBody v-model="delegationAgentForm" :is-text-mode="isTextMode" />
+              <DelegationAgentConfirmationBody
+                v-model="delegationAgentForm"
+                :is-text-mode="isTextMode"
+              />
             </div>
             <div v-else-if="attach.no === 9" class="attachment-content">
-              <ServiceChargingStandardsBody v-model="serviceChargingForm" :is-text-mode="isTextMode" />
+              <ServiceChargingStandardsBody
+                v-model="serviceChargingForm"
+                :is-text-mode="isTextMode"
+              />
             </div>
             <div v-else-if="attach.no === 10" class="attachment-content">
-              <RoomFacilitiesEquipmentBody v-model="roomFacilitiesForm" :is-text-mode="isTextMode" />
+              <RoomFacilitiesEquipmentBody
+                v-model="roomFacilitiesForm"
+                :is-text-mode="isTextMode"
+              />
             </div>
             <div v-else-if="attach.no === 11" class="attachment-content">
-              <ExplanationExaminationReportBody v-model="examinationReportForm" :is-text-mode="isTextMode" />
+              <ExplanationExaminationReportBody
+                v-model="examinationReportForm"
+                :is-text-mode="isTextMode"
+              />
             </div>
             <div v-else-if="attach.no === 12" class="attachment-content">
-              <DocumentAttachmentBody v-model="identificationPartyBForm" :is-text-mode="isTextMode" title="乙方有效证件" description="乙方:有效身份证件复印件(正反面复印)及户口本复印件(户主页和本人页)" />
+              <DocumentAttachmentBody
+                v-model="identificationPartyBForm"
+                :is-text-mode="isTextMode"
+                title="乙方有效证件"
+                description="乙方:有效身份证件复印件(正反面复印)及户口本复印件(户主页和本人页)"
+              />
             </div>
             <div v-else-if="attach.no === 13" class="attachment-content">
-              <DocumentAttachmentBody v-model="guardianPartyBForm" :is-text-mode="isTextMode" title="乙方监护人(丙方)身份证、户口本复印件" description="丙方:(系自然人的)有效身份证件复印件(正反面复印)及户口本复印件(户主页和本人页);(系单位的)的有效注册登登记材料复印件(加盖公章)、法定代表人/负责人及联系人的身份证件复印件(身份证件需正反面复印)" />
+              <DocumentAttachmentBody
+                v-model="guardianPartyBForm"
+                :is-text-mode="isTextMode"
+                title="乙方监护人(丙方)身份证、户口本复印件"
+                description="丙方:(系自然人的)有效身份证件复印件(正反面复印)及户口本复印件(户主页和本人页);(系单位的)的有效注册登登记材料复印件(加盖公章)、法定代表人/负责人及联系人的身份证件复印件(身份证件需正反面复印)"
+              />
             </div>
             <div v-else-if="attach.no === 14" class="attachment-content">
-              <DocumentAttachmentBody v-model="registrationCertificateForm" :is-text-mode="isTextMode" description="甲方登记证书及民政部门备案回执" />
+              <DocumentAttachmentBody
+                v-model="registrationCertificateForm"
+                :is-text-mode="isTextMode"
+                description="甲方登记证书及民政部门备案回执"
+              />
             </div>
             <div v-else-if="attach.no === 15" class="attachment-content">
-              <DocumentAttachmentBody v-model="comprehensiveAssessmentForm" :is-text-mode="isTextMode" title="老年人能力综合评估结果" />
+              <DocumentAttachmentBody
+                v-model="comprehensiveAssessmentForm"
+                :is-text-mode="isTextMode"
+                title="老年人能力综合评估结果"
+              />
             </div>
             <div v-else-if="attach.no === 16" class="attachment-content">
-              <FirstServiceProjectConfirmationBody v-model="firstServiceForm" :is-text-mode="isTextMode" />
+              <FirstServiceProjectConfirmationBody
+                v-model="firstServiceForm"
+                :is-text-mode="isTextMode"
+              />
             </div>
             <div v-else-if="attach.no === 17" class="attachment-content">
               <ChangeConfirmationFormBody v-model="changeConfirmForm" :is-text-mode="isTextMode" />
             </div>
-            <div v-else class="attachment-body">           
+            <div v-else class="attachment-body">
               <p><strong>日期:</strong>{{ data?.createTime || '-' }}</p>
-              <p style="color: #999; font-size: 13px;">
+              <p style="color: #999; font-size: 13px">
                 (此处为附件内容占位,实际各附件将由对应列表页提供完整内容排版)
               </p>
             </div>
           </template>
         </AttachmentPage>
       </div>
-
     </div>
   </el-drawer>
 
@@ -628,6 +739,7 @@ const renderAttachmentContent = (key: string) => {
     v-model:visible="selectorVisible.show"
     :title="selectorVisible.title"
     :current="selectorVisible.current"
+    :elder-id="recordRow?.elderId"
     :list="selectorVisible.list"
     @select="handleAttachmentSelect"
     @update:visible="handleAttachmentSelectorClose"
@@ -641,45 +753,112 @@ const renderAttachmentContent = (key: string) => {
 
       <!-- 已选的附件 -->
       <template v-if="selectedAttachments.length > 0">
-        <div
-          v-for="attach in selectedAttachments"
-          :key="attach.no"
-          class="print-attachment"
-        >
+        <div v-for="attach in selectedAttachments" :key="attach.no" class="print-attachment">
           <!-- 附件1:知情同意书,使用 RiskDisclosureBody -->
-          <RiskDisclosureBody v-if="attach.no === 1" v-model="riskDisclosureForm" :is-text-mode="true" />
+          <RiskDisclosureBody
+            v-if="attach.no === 1"
+            v-model="riskDisclosureForm"
+            :is-text-mode="true"
+          />
           <!-- 附件2:入住登记表,使用 CheckInRegistrationBody -->
-          <CheckInRegistrationBody v-else-if="attach.no === 2" v-model="checkInRegistrationForm" :is-text-mode="true" :elder-id="recordRow?.elderId" />
+          <CheckInRegistrationBody
+            v-else-if="attach.no === 2"
+            v-model="checkInRegistrationForm"
+            :is-text-mode="true"
+            :elder-id="recordRow?.elderId"
+          />
           <!-- 附件3:入住须知,使用 CheckInInformationBody -->
           <CheckInInformationBody v-else-if="attach.no === 3" :is-text-mode="true" />
           <!-- 附件4:长者安全承诺书,使用 ElderSafetyCommitmentBody -->
-          <ElderSafetyCommitmentBody v-else-if="attach.no === 4" v-model="safetyCommitmentForm" :is-text-mode="true" />
+          <ElderSafetyCommitmentBody
+            v-else-if="attach.no === 4"
+            v-model="safetyCommitmentForm"
+            :is-text-mode="true"
+          />
           <!-- 附件5:长者外出情况确认书,使用 OutingConfirmationBody -->
-          <OutingConfirmationBody v-else-if="attach.no === 5" v-model="outingConfirmationForm" :is-text-mode="true" />
+          <OutingConfirmationBody
+            v-else-if="attach.no === 5"
+            v-model="outingConfirmationForm"
+            :is-text-mode="true"
+          />
           <!-- 附件6:签名代理申请,使用 SignatureProxyApplicationBody -->
-          <SignatureProxyApplicationBody v-else-if="attach.no === 6" v-model="signatureProxyForm" :is-text-mode="true" />
+          <SignatureProxyApplicationBody
+            v-else-if="attach.no === 6"
+            v-model="signatureProxyForm"
+            :is-text-mode="true"
+          />
           <!-- 附件7:授权委托书,使用 PowerOfAttorneyBody -->
-          <PowerOfAttorneyBody v-else-if="attach.no === 7" v-model="powerOfAttorneyForm" :is-text-mode="true" />
+          <PowerOfAttorneyBody
+            v-else-if="attach.no === 7"
+            v-model="powerOfAttorneyForm"
+            :is-text-mode="true"
+          />
           <!-- 附件8:委托代理人确认表,使用 DelegationAgentConfirmationBody -->
-          <DelegationAgentConfirmationBody v-else-if="attach.no === 8" v-model="delegationAgentForm" :is-text-mode="true" />
+          <DelegationAgentConfirmationBody
+            v-else-if="attach.no === 8"
+            v-model="delegationAgentForm"
+            :is-text-mode="true"
+          />
           <!-- 附件9:机构服务范围及收费标准,使用 ServiceChargingStandardsBody -->
-          <ServiceChargingStandardsBody v-else-if="attach.no === 9" v-model="serviceChargingForm" :is-text-mode="true" />
+          <ServiceChargingStandardsBody
+            v-else-if="attach.no === 9"
+            v-model="serviceChargingForm"
+            :is-text-mode="true"
+          />
           <!-- 附件10:标准房间物品配备,使用 RoomFacilitiesEquipmentBody -->
-          <RoomFacilitiesEquipmentBody v-else-if="attach.no === 10" v-model="roomFacilitiesForm" :is-text-mode="true" />
+          <RoomFacilitiesEquipmentBody
+            v-else-if="attach.no === 10"
+            v-model="roomFacilitiesForm"
+            :is-text-mode="true"
+          />
           <!-- 附件11:体检报告项目说明,使用 ExplanationExaminationReportBody -->
-          <ExplanationExaminationReportBody v-else-if="attach.no === 11" v-model="examinationReportForm" :is-text-mode="true" />
+          <ExplanationExaminationReportBody
+            v-else-if="attach.no === 11"
+            v-model="examinationReportForm"
+            :is-text-mode="true"
+          />
           <!-- 附件12:乙方有效证件,使用 DocumentAttachmentBody -->
-          <DocumentAttachmentBody v-else-if="attach.no === 12" v-model="identificationPartyBForm" :is-text-mode="true" title="乙方有效证件" description="乙方:有效身份证件复印件(正反面复印)及户口本复印件(户主页和本人页)" />
+          <DocumentAttachmentBody
+            v-else-if="attach.no === 12"
+            v-model="identificationPartyBForm"
+            :is-text-mode="true"
+            title="乙方有效证件"
+            description="乙方:有效身份证件复印件(正反面复印)及户口本复印件(户主页和本人页)"
+          />
           <!-- 附件13:乙方监护人(丙方)身份证、户口本复印件,使用 DocumentAttachmentBody -->
-          <DocumentAttachmentBody v-else-if="attach.no === 13" v-model="guardianPartyBForm" :is-text-mode="true" title="乙方监护人(丙方)身份证、户口本复印件" description="丙方:(系自然人的)有效身份证件复印件(正反面复印)及户口本复印件(户主页和本人页);(系单位的)的有效注册登登记材料复印件(加盖公章)、法定代表人/负责人及联系人的身份证件复印件(身份证件需正反面复印)" />
+          <DocumentAttachmentBody
+            v-else-if="attach.no === 13"
+            v-model="guardianPartyBForm"
+            :is-text-mode="true"
+            title="乙方监护人(丙方)身份证、户口本复印件"
+            description="丙方:(系自然人的)有效身份证件复印件(正反面复印)及户口本复印件(户主页和本人页);(系单位的)的有效注册登登记材料复印件(加盖公章)、法定代表人/负责人及联系人的身份证件复印件(身份证件需正反面复印)"
+          />
           <!-- 附件14:甲方登记证书及民政部门备案回执,使用 DocumentAttachmentBody -->
-          <DocumentAttachmentBody v-else-if="attach.no === 14" v-model="registrationCertificateForm" :is-text-mode="true" description="甲方登记证书及民政部门备案回执" />
+          <DocumentAttachmentBody
+            v-else-if="attach.no === 14"
+            v-model="registrationCertificateForm"
+            :is-text-mode="true"
+            description="甲方登记证书及民政部门备案回执"
+          />
           <!-- 附件15:老年人能力综合评估结果,使用 DocumentAttachmentBody -->
-          <DocumentAttachmentBody v-else-if="attach.no === 15" v-model="comprehensiveAssessmentForm" :is-text-mode="true" title="老年人能力综合评估结果" />
+          <DocumentAttachmentBody
+            v-else-if="attach.no === 15"
+            v-model="comprehensiveAssessmentForm"
+            :is-text-mode="true"
+            title="老年人能力综合评估结果"
+          />
           <!-- 附件16:首次服务项目确认表,使用 FirstServiceProjectConfirmationBody -->
-          <FirstServiceProjectConfirmationBody v-else-if="attach.no === 16" v-model="firstServiceForm" :is-text-mode="true" />
+          <FirstServiceProjectConfirmationBody
+            v-else-if="attach.no === 16"
+            v-model="firstServiceForm"
+            :is-text-mode="true"
+          />
           <!-- 附件17:变更事项确认表,使用 ChangeConfirmationFormBody -->
-          <ChangeConfirmationFormBody v-else-if="attach.no === 17" v-model="changeConfirmForm" :is-text-mode="true" />
+          <ChangeConfirmationFormBody
+            v-else-if="attach.no === 17"
+            v-model="changeConfirmForm"
+            :is-text-mode="true"
+          />
 
           <!-- 其他附件:展示标题和信息 -->
           <div v-else class="a4-page">
@@ -689,7 +868,10 @@ const renderAttachmentContent = (key: string) => {
             <div class="print-attachment-info">
               <p><strong>名称:</strong>{{ renderAttachmentContent(`attach_${attach.no}`) }}</p>
               <p><strong>版本:</strong>{{ attachments[`attach_${attach.no}`]?.version || '-' }}</p>
-              <p><strong>日期:</strong>{{ attachments[`attach_${attach.no}`]?.createTime || '-' }}</p>
+              <p
+                ><strong>日期:</strong
+                >{{ attachments[`attach_${attach.no}`]?.createTime || '-' }}</p
+              >
             </div>
           </div>
         </div>

+ 5 - 8
src/views/elderly/contracts/change-confirmation-form/AddForm.vue

@@ -70,11 +70,7 @@
 
       <!-- 内容区域 -->
       <div class="form-body">
-        <ChangeConfirmationFormBody
-          ref="bodyRef"
-          v-model="changeForm"
-          :is-text-mode="isDetail"
-        />
+        <ChangeConfirmationFormBody ref="bodyRef" v-model="changeForm" :is-text-mode="isDetail" />
       </div>
     </div>
 
@@ -134,6 +130,7 @@ const elderUp = (e) => {
   dataForm.value.bedName = e.bedName || ''
   dataForm.value.checkInTime = e.checkInTime
   dataForm.value.contractNumber = e.contractNumber || e.fileNumber
+  changeForm.value.partyBName = e.elderName
 }
 
 const open = async (tenantId, id?: any, detail: boolean = false) => {
@@ -195,9 +192,9 @@ const submitForm = async () => {
       recorder: form.recorder,
       recordDate: form.recordDate ? dayjs(form.recordDate).format('YYYY-MM-DD') : '',
       content: content,
-      signYi: '',
-      signBing: '',
-      signDate: '',
+      signYi: bodyForm.partyBSign || '',
+      signBing: bodyForm.partyCSign || '',
+      signDate: bodyForm.signDate || '',
       tenantId: dataForm.value.tenantId
     }
 

+ 1 - 1
src/views/elderly/contracts/change-confirmation-form/index.vue

@@ -68,7 +68,7 @@
         show-overflow-tooltip
       />
       <el-table-column
-        prop="bedName"
+        prop="bedNumber"
         header-align="center"
         align="center"
         label="床位号"

+ 128 - 68
src/views/elderly/contracts/components/AttachmentSelector.vue

@@ -1,9 +1,26 @@
 <script setup lang="ts">
 import { ref, watch, computed, reactive } from 'vue'
-import { checkInRegistrationPage } from '@/api/social-work'
+import {
+  riskDisclosure_findPage2,
+  checkInRegistration_getListByElderId,
+  elderSafetyCommitment_getListByElderId,
+  outingConfirmation_getListByElderId,
+  signatureProxyApplication_getListByElderId,
+  powerOfAttorney_getListByElderId,
+  delegationAgentConfirmation_getListByElderId,
+  serviceChargingStandards_getListByElderId,
+  roomFacilitiesEquipment_getListByElderId,
+  explanationExaminationReport_getListByElderId,
+  partyBIdentificationDocument_getListByElderId,
+  guardianPartyB_getListByElderId,
+  registrationCertificateCivilAffairs_getListByElderId,
+  comprehensiveAssessmentCapabilities_getListByElderId,
+  firstServiceProjectConfirmation_getListByElderId,
+  changeConfirmationForm_getListByElderId
+} from '@/api/elderly/contracts'
 
 export interface SelectorConfig {
-  api?: (params: any) => Promise<any>
+  api?: (elderId: any) => Promise<any>
   columns?: Array<{
     prop?: string
     label: string
@@ -12,12 +29,6 @@ export interface SelectorConfig {
     align?: string
     formatter?: (row: any) => string
   }>
-  searchFields?: Array<{
-    prop: string
-    label: string
-    placeholder?: string
-    type?: 'input' | 'date'
-  }>
   titleField?: string
   dateField?: string
   versionField?: string
@@ -27,6 +38,7 @@ const props = defineProps<{
   visible?: boolean
   title?: string
   current?: string
+  elderId?: string | number
   list?: any[]
   config?: SelectorConfig
   extraParams?: Record<string, any>
@@ -41,29 +53,115 @@ const localVisible = ref(false)
 const selectedRow = ref<any>(null)
 const loading = ref(false)
 const dataList = ref<any[]>([])
-const queryParams = reactive<Record<string, any>>({})
 const pagination = reactive({
   pageNo: 1,
   pageSize: 10,
   total: 0
 })
 
-// 不同附件类型对应的默认配置
+const defaultColumns = [
+  // { prop: 'elderName', label: '长者姓名', width: 160 ,align: 'center'},
+  // { prop: 'bedNumber', label: '床位号', width: 150, align: 'center' },
+  { prop: 'recorder', label: '记录人',  align: 'center' },
+  { prop: 'recordDate', label: '记录日期', align: 'center' }
+]
+
 const defaultConfigMap: Record<string, SelectorConfig> = {
+  attach_1: {
+    api: riskDisclosure_findPage2,
+    columns: defaultColumns,
+    titleField: 'elderName',
+    dateField: 'recordDate'
+  },
   attach_2: {
-    api: checkInRegistrationPage,
-    columns: [
-      { prop: 'elderName', label: '长者姓名', minWidth: 120, align: 'center' },
-      { prop: 'assessor', label: '记录人', minWidth: 120, align: 'center' },
-      { prop: 'assessDate', label: '记录日期', width: 140, align: 'center' },
-      { prop: 'createTime', label: '创建时间', width: 160, align: 'center' }
-    ],
-    searchFields: [
-      { prop: 'elderName', label: '长者姓名', placeholder: '请输入长者姓名', type: 'input' }
-    ],
+    api: checkInRegistration_getListByElderId,
+    columns: defaultColumns,
+    titleField: 'elderName',
+    dateField: 'recordDate'
+  },
+  attach_4: {
+    api: elderSafetyCommitment_getListByElderId,
+    columns: defaultColumns,
+    titleField: 'elderName',
+    dateField: 'recordDate'
+  },
+  attach_5: {
+    api: outingConfirmation_getListByElderId,
+    columns: defaultColumns,
+    titleField: 'elderName',
+    dateField: 'recordDate'
+  },
+  attach_6: {
+    api: signatureProxyApplication_getListByElderId,
+    columns: defaultColumns,
+    titleField: 'elderName',
+    dateField: 'recordDate'
+  },
+  attach_7: {
+    api: powerOfAttorney_getListByElderId,
+    columns: defaultColumns,
+    titleField: 'elderName',
+    dateField: 'recordDate'
+  },
+  attach_8: {
+    api: delegationAgentConfirmation_getListByElderId,
+    columns: defaultColumns,
+    titleField: 'elderName',
+    dateField: 'recordDate'
+  },
+  attach_9: {
+    api: serviceChargingStandards_getListByElderId,
+    columns: defaultColumns,
+    titleField: 'elderName',
+    dateField: 'recordDate'
+  },
+  attach_10: {
+    api: roomFacilitiesEquipment_getListByElderId,
+    columns: defaultColumns,
+    titleField: 'elderName',
+    dateField: 'recordDate'
+  },
+  attach_11: {
+    api: explanationExaminationReport_getListByElderId,
+    columns: defaultColumns,
     titleField: 'elderName',
-    dateField: 'assessDate',
-    versionField: 'version'
+    dateField: 'recordDate'
+  },
+  attach_12: {
+    api: partyBIdentificationDocument_getListByElderId,
+    columns: defaultColumns,
+    titleField: 'elderName',
+    dateField: 'recordDate'
+  },
+  attach_13: {
+    api: guardianPartyB_getListByElderId,
+    columns: defaultColumns,
+    titleField: 'elderName',
+    dateField: 'recordDate'
+  },
+  attach_14: {
+    api: registrationCertificateCivilAffairs_getListByElderId,
+    columns: defaultColumns,
+    titleField: 'elderName',
+    dateField: 'recordDate'
+  },
+  attach_15: {
+    api: comprehensiveAssessmentCapabilities_getListByElderId,
+    columns: defaultColumns,
+    titleField: 'elderName',
+    dateField: 'recordDate'
+  },
+  attach_16: {
+    api: firstServiceProjectConfirmation_getListByElderId,
+    columns: defaultColumns,
+    titleField: 'elderName',
+    dateField: 'recordDate'
+  },
+  attach_17: {
+    api: changeConfirmationForm_getListByElderId,
+    columns: defaultColumns,
+    titleField: 'elderName',
+    dateField: 'recordDate'
   }
 }
 
@@ -74,11 +172,11 @@ const activeConfig = computed<SelectorConfig>(() => {
     ...defaults,
     ...custom,
     columns: custom.columns ?? defaults?.columns ?? [
-      { prop: 'title', label: '名称/说明', minWidth: 260 },
-      { prop: 'version', label: '版本', width: 100, align: 'center' },
-      { prop: 'createTime', label: '日期/创建时间', width: 160, align: 'center' }
+      // { prop: 'elderName', label: '长者姓名', minWidth: 160 },
+      // { prop: 'bedNumber', label: '床位号', width: 150, align: 'center' },
+      { prop: 'recorder', label: '记录人', align: 'center' },
+      { prop: 'recordDate', label: '记录日期', align: 'center' }
     ],
-    searchFields: custom.searchFields ?? defaults?.searchFields ?? [],
     titleField: custom.titleField ?? defaults?.titleField ?? 'title',
     dateField: custom.dateField ?? defaults?.dateField ?? 'createTime',
     versionField: custom.versionField ?? defaults?.versionField ?? 'version'
@@ -90,38 +188,17 @@ const displayList = computed(() => {
   return dataList.value
 })
 
-const resetQuery = () => {
-  activeConfig.value.searchFields?.forEach((field) => {
-    queryParams[field.prop] = ''
-  })
-  pagination.pageNo = 1
-}
-
 const fetchData = async () => {
   const api = activeConfig.value.api
-  if (!api) {
-    // 无接口时回退到默认模拟数据
-    dataList.value = [
-      { id: 1, title: '示例数据1 - 2026年1月版本', createTime: '2026-01-15', version: 'V1.0' },
-      { id: 2, title: '示例数据2 - 2026年3月版本', createTime: '2026-03-20', version: 'V1.1' },
-      { id: 3, title: '示例数据3 - 2026年5月版本', createTime: '2026-05-10', version: 'V2.0' }
-    ]
+  if (!api || !props.elderId) {
+    dataList.value = []
+    pagination.total = 0
     return
   }
 
   loading.value = true
   try {
-    const params: any = {
-      pageNo: pagination.pageNo,
-      pageSize: pagination.pageSize,
-      ...props.extraParams
-    }
-    activeConfig.value.searchFields?.forEach((field) => {
-      if (queryParams[field.prop]) {
-        params[field.prop] = queryParams[field.prop]
-      }
-    })
-    const res = await api(params)
+    const res = await api(props.elderId)
     if (res && res.list) {
       dataList.value = res.list
       pagination.total = res.total || 0
@@ -133,9 +210,6 @@ const fetchData = async () => {
       pagination.total = 0
     }
   } catch (error) {
-    dataList.value = [  { id: 1, title: '示例数据1 - 2026年1月版本', createTime: '2026-01-15', version: 'V1.0' },
-      { id: 2, title: '示例数据2 - 2026年3月版本', createTime: '2026-03-20', version: 'V1.1' },
-      { id: 3, title: '示例数据3 - 2026年5月版本', createTime: '2026-05-10', version: 'V2.0' }]
     pagination.total = 0
   } finally {
     loading.value = false
@@ -148,7 +222,6 @@ watch(
     localVisible.value = val || false
     if (val) {
       selectedRow.value = null
-      resetQuery()
       fetchData()
     }
   },
@@ -159,7 +232,6 @@ watch(
   () => props.current,
   () => {
     if (localVisible.value) {
-      resetQuery()
       fetchData()
     }
   }
@@ -180,11 +252,6 @@ const handleConfirm = () => {
   close()
 }
 
-const handleSearch = () => {
-  pagination.pageNo = 1
-  fetchData()
-}
-
 const handlePageChange = (page: number) => {
   pagination.pageNo = page
   fetchData()
@@ -214,7 +281,6 @@ const renderCell = (row: any, column: any) => {
       style="margin-bottom: 12px;"
     />
 
-
     <el-table
       v-loading="loading"
       :data="displayList"
@@ -259,12 +325,6 @@ const renderCell = (row: any, column: any) => {
 </template>
 
 <style scoped lang="scss">
-.selector-search {
-  padding: 0 0 12px;
-  border-bottom: 1px solid #ebeef5;
-  margin-bottom: 12px;
-}
-
 .selector-pagination {
   margin-top: 16px;
   display: flex;

+ 286 - 81
src/views/elderly/contracts/components/ChangeConfirmationFormBody.vue

@@ -4,6 +4,12 @@ import FieldItem from './FieldItem.vue'
 import SignatureItem from './SignatureItem.vue'
 import { getNursingLevelPage } from '@/api/elderly/nursing'
 
+interface OtherFeeItem {
+  name: string
+  amount: string
+  unit: string
+}
+
 interface FormData {
   partyBName?: string
   originalAbilityLevel?: string
@@ -15,29 +21,26 @@ interface FormData {
   newServices?: string[]
   totalFee?: string
   bedFee?: string
-  serviceFee?: string
+  nursingFee?: string
   mealFee?: string
-  otherFee1Name?: string
-  otherFee1Amount?: string
-  otherFee1Unit?: string
-  otherFee2Name?: string
-  otherFee2Amount?: string
-  otherFee2Unit?: string
+  serviceFee?: string
+  otherFees?: OtherFeeItem[]
   partyASign?: string
   partyBSign?: string
   partyCSign?: string
-  year?: string
-  month?: string
-  day?: string
+  signDate?: string
 }
 
-const props = withDefaults(defineProps<{
-  isTextMode?: boolean
-  modelValue?: FormData
-}>(), {
-  isTextMode: false,
-  modelValue: () => ({})
-})
+const props = withDefaults(
+  defineProps<{
+    isTextMode?: boolean
+    modelValue?: FormData
+  }>(),
+  {
+    isTextMode: false,
+    modelValue: () => ({})
+  }
+)
 
 const emit = defineEmits<{
   (e: 'update:modelValue', val: FormData): void
@@ -51,32 +54,49 @@ const form = reactive<FormData>({
   newAbilityLevel: '',
   newCareLevel: '',
   changedCareLevel: '',
-  newServices: ['', '', '', '', ''],
+  newServices: [],
   totalFee: '',
   bedFee: '',
-  serviceFee: '',
+  nursingFee: '',
   mealFee: '',
-  otherFee1Name: '',
-  otherFee1Amount: '',
-  otherFee1Unit: '',
-  otherFee2Name: '',
-  otherFee2Amount: '',
-  otherFee2Unit: '',
+  serviceFee: '',
+  otherFees: [],
   partyASign: '',
   partyBSign: '',
   partyCSign: '',
-  year: '',
-  month: '',
-  day: ''
+  signDate: ''
 })
 
-watch(() => props.modelValue, (val) => {
-  if (!val) return
-  Object.assign(form, JSON.parse(JSON.stringify(val)))
-  if (!form.newServices || form.newServices.length === 0) {
-    form.newServices = ['', '', '', '', '']
-  }
-}, { immediate: true, deep: true })
+watch(
+  () => props.modelValue,
+  (val) => {
+    if (!val) return
+    Object.assign(form, JSON.parse(JSON.stringify(val)))
+    if (!form.newServices) form.newServices = []
+    if (!form.otherFees) form.otherFees = []
+  },
+  { immediate: true, deep: true }
+)
+
+const addService = () => {
+  form.newServices!.push('')
+  updateForm()
+}
+
+const removeService = (idx: number) => {
+  form.newServices!.splice(idx, 1)
+  updateForm()
+}
+
+const addOtherFee = () => {
+  form.otherFees!.push({ name: '', amount: '', unit: '' })
+  updateForm()
+}
+
+const removeOtherFee = (idx: number) => {
+  form.otherFees!.splice(idx, 1)
+  updateForm()
+}
 
 const updateForm = () => {
   emit('update:modelValue', JSON.parse(JSON.stringify(form)))
@@ -86,7 +106,11 @@ const nurseLevelList = ref<{ id: number; nurseLevelName: string }[]>([])
 const fetchNurseLevels = async () => {
   try {
     const data = await getNursingLevelPage({ pageNum: 1, pageSize: 100 })
-    nurseLevelList.value = data.list
+    nurseLevelList.value.push({ id: 9999, nurseLevelName: '未变更' })
+    for (const datum of data.list) {
+      nurseLevelList.value.push(datum)
+    }
+
   } catch {
     // ignore
   }
@@ -95,7 +119,7 @@ onMounted(fetchNurseLevels)
 
 const getNurseLevelLabel = (val: string | number | undefined) => {
   if (val == null || val === '') return ''
-  const found = nurseLevelList.value.find(item => String(item.id) === String(val))
+  const found = nurseLevelList.value.find((item) => String(item.id) === String(val))
   return found ? found.nurseLevelName : String(val)
 }
 
@@ -109,16 +133,39 @@ defineExpose({ form })
     <div class="doc-content">
       <div class="row">
         <span>乙方:</span>
-        <FieldItem v-model="form.partyBName" :is-text-mode="isTextMode" width="200px" placeholder="" @update:model-value="updateForm" />
+        <FieldItem
+          v-model="form.partyBName"
+          :is-text-mode="isTextMode"
+          width="200px"
+          placeholder=""
+          @update:model-value="updateForm"
+        />
       </div>
 
       <div class="row">
         <span>乙方入住时经评估能力等级为</span>
-        <FieldItem v-model="form.originalAbilityLevel" :is-text-mode="isTextMode" width="120px" placeholder="" @update:model-value="updateForm" />
+        <FieldItem
+          v-model="form.originalAbilityLevel"
+          :is-text-mode="isTextMode"
+          width="120px"
+          placeholder=""
+          @update:model-value="updateForm"
+        />
         <span>,甲方提供的照料护理等级为</span>
         <template v-if="!isTextMode">
-          <el-select v-model="form.originalCareLevel" placeholder="请选择" clearable style="width: 140px" @change="updateForm">
-            <el-option v-for="item in nurseLevelList" :key="item.id" :label="item.nurseLevelName" :value="item.id" />
+          <el-select
+            v-model="form.originalCareLevel"
+            placeholder="请选择"
+            clearable
+            style="width: 140px"
+            @change="updateForm"
+          >
+            <el-option
+              v-for="item in nurseLevelList"
+              :key="item.id"
+              :label="item.nurseLevelName"
+              :value="item.id"
+            />
           </el-select>
         </template>
         <template v-else>
@@ -129,10 +176,25 @@ defineExpose({ form })
 
       <div class="row">
         <span>甲方于</span>
-        <FieldItem v-model="form.reAssessDate" :is-text-mode="isTextMode" type="date" width="140px" placeholder="" @update:model-value="updateForm" />
+        <FieldItem
+          v-model="form.reAssessDate"
+          :is-text-mode="isTextMode"
+          type="date"
+          width="140px"
+          placeholder=""
+          @update:model-value="updateForm"
+        />
         <span>对乙方重新进行了评估,重新评估的能力等级为</span>
-        <FieldItem v-model="form.newAbilityLevel" :is-text-mode="isTextMode" width="120px" placeholder="" @update:model-value="updateForm" />
-        <span>。根据乙方能力等级变化,需要对乙方的照料护理等级和相关的服务内容进行变更,经双方协商一致,同意变更下列事项,具体变更内容如下:</span>
+        <FieldItem
+          v-model="form.newAbilityLevel"
+          :is-text-mode="isTextMode"
+          width="120px"
+          placeholder=""
+          @update:model-value="updateForm"
+        />
+        <span
+          >。根据乙方能力等级变化,需要对乙方的照料护理等级和相关的服务内容进行变更,经双方协商一致,同意变更下列事项,具体变更内容如下:</span
+        >
       </div>
 
       <div class="section">
@@ -140,8 +202,19 @@ defineExpose({ form })
         <div class="row">
           <span>乙方变更后的照料护理等级为</span>
           <template v-if="!isTextMode">
-            <el-select v-model="form.changedCareLevel" placeholder="请选择" clearable style="width: 140px" @change="updateForm">
-              <el-option v-for="item in nurseLevelList" :key="item.id" :label="item.nurseLevelName" :value="item.id" />
+            <el-select
+              v-model="form.changedCareLevel"
+              placeholder="请选择"
+              clearable
+              style="width: 140px"
+              @change="updateForm"
+            >
+              <el-option
+                v-for="item in nurseLevelList"
+                :key="item.id"
+                :label="item.nurseLevelName"
+                :value="item.id"
+              />
             </el-select>
           </template>
           <template v-else>
@@ -153,9 +226,18 @@ defineExpose({ form })
 
       <div class="section">
         <div class="section-title">二、服务内容变更</div>
-        <div class="sub-title">1.甲方为乙方新增下列服务内容</div>
+        <div class="sub-title">1.甲方为乙方变更以下列服务内容:</div>
         <div v-if="!isTextMode" class="service-inputs">
-          <el-input v-for="(item, idx) in form.newServices" :key="idx" v-model="form.newServices![idx]" placeholder="请输入服务内容" style="width: 100%; margin-bottom: 8px;" @input="updateForm" />
+          <div v-for="(item, idx) in form.newServices" :key="idx" class="service-row">
+            <el-input
+              v-model="form.newServices![idx]"
+              placeholder="请输入服务内容"
+              style="flex: 1"
+              @input="updateForm"
+            />
+            <el-button type="danger" text @click="removeService(idx)">删除</el-button>
+          </div>
+          <el-button type="primary" plain @click="addService">+ 新增服务内容</el-button>
         </div>
         <div v-else class="service-lines">
           <div v-for="(item, idx) in form.newServices" :key="idx" class="service-line">
@@ -168,60 +250,153 @@ defineExpose({ form })
         <div class="section-title">三、费用变更</div>
         <div class="row">
           <span>养老服务总费用为</span>
-          <FieldItem v-model="form.totalFee" :is-text-mode="isTextMode" width="100px" placeholder="" @update:model-value="updateForm" />
-          <span>元/月,其中:(1)床位费:</span>
-          <FieldItem v-model="form.bedFee" :is-text-mode="isTextMode" width="100px" placeholder="" @update:model-value="updateForm" />
-          <span>元/月;(2)服务费:</span>
-          <FieldItem v-model="form.serviceFee" :is-text-mode="isTextMode" width="100px" placeholder="" @update:model-value="updateForm" />
-          <span>元/月;(3)膳食费:</span>
-          <FieldItem v-model="form.mealFee" :is-text-mode="isTextMode" width="100px" placeholder="" @update:model-value="updateForm" />
-          <span>元/月;(4)其他费用:</span>
-          <FieldItem v-model="form.otherFee1Name" :is-text-mode="isTextMode" width="100px" placeholder="" @update:model-value="updateForm" />
-          <span>费,</span>
-          <FieldItem v-model="form.otherFee1Amount" :is-text-mode="isTextMode" width="80px" placeholder="" @update:model-value="updateForm" />
-          <span>元/</span>
-          <FieldItem v-model="form.otherFee1Unit" :is-text-mode="isTextMode" width="80px" placeholder="单位" @update:model-value="updateForm" />
-          <span>(单位)。</span>
+          <FieldItem
+            v-model="form.totalFee"
+            :is-text-mode="isTextMode"
+            width="100px"
+            placeholder=""
+            @update:model-value="updateForm"
+          />
+          <span>元/月,其中:</span>
+        </div>
+        <div class="fee-list">
+          <div class="fee-item">
+            <span>(1)床位费:</span>
+            <FieldItem
+              v-model="form.bedFee"
+              :is-text-mode="isTextMode"
+              width="100px"
+              placeholder=""
+              @update:model-value="updateForm"
+            />
+            <span>元/月;</span>
+          </div>
+          <div class="fee-item">
+            <span>(2)护理费:</span>
+            <FieldItem
+              v-model="form.nursingFee"
+              :is-text-mode="isTextMode"
+              width="100px"
+              placeholder=""
+              @update:model-value="updateForm"
+            />
+            <span>元/月;</span>
+          </div>
+          <div class="fee-item">
+            <span>(3)膳食费:</span>
+            <FieldItem
+              v-model="form.mealFee"
+              :is-text-mode="isTextMode"
+              width="100px"
+              placeholder=""
+              @update:model-value="updateForm"
+            />
+            <span>元/月;</span>
+          </div>
+          <div class="fee-item">
+            <span>(4)服务费:</span>
+            <FieldItem
+              v-model="form.serviceFee"
+              :is-text-mode="isTextMode"
+              width="100px"
+              placeholder=""
+              @update:model-value="updateForm"
+            />
+            <span>元/月;</span>
+          </div>
+        </div>
+        <div v-if="!isTextMode" class="other-fee-section">
+          <div v-for="(item, idx) in form.otherFees" :key="idx" class="other-fee-item">
+            ({{ idx + 5 }})
+            <FieldItem
+              v-model="item.name"
+              :is-text-mode="isTextMode"
+              width="100px"
+              placeholder="费用名称"
+              @update:model-value="updateForm"
+            />
+            <span>费:</span>
+            <FieldItem
+              v-model="item.amount"
+              :is-text-mode="isTextMode"
+              width="80px"
+              placeholder="金额"
+              @update:model-value="updateForm"
+            />
+            <span>元/</span>
+            <FieldItem
+              v-model="item.unit"
+              :is-text-mode="isTextMode"
+              width="80px"
+              placeholder="单位"
+              @update:model-value="updateForm"
+            />
+            <span>(单位);</span>
+            <el-button type="danger" text @click="removeOtherFee(idx)">删除</el-button>
+          </div>
+          <el-button type="primary" plain @click="addOtherFee">+ 新增其他费用</el-button>
         </div>
-        <div class="row other-fee-row">
-          <FieldItem v-model="form.otherFee2Name" :is-text-mode="isTextMode" width="100px" placeholder="" @update:model-value="updateForm" />
-          <span>费,</span>
-          <FieldItem v-model="form.otherFee2Amount" :is-text-mode="isTextMode" width="80px" placeholder="" @update:model-value="updateForm" />
-          <span>元/</span>
-          <FieldItem v-model="form.otherFee2Unit" :is-text-mode="isTextMode" width="80px" placeholder="单位" @update:model-value="updateForm" />
-          <span>(单位)。</span>
+        <div v-else class="other-fee-section">
+          <div v-for="(item, idx) in form.otherFees" :key="idx" class="other-fee-item">
+            ({{ idx + 5 }})
+            <span>{{ item.name || '____' }}费:{{ item.amount || '____' }}元/{{ item.unit || '____' }}(单位)。</span>
+          </div>
         </div>
       </div>
 
-      <div class="confirm-text">
-        乙方、丙方同意并确认上述变更事项。
-      </div>
+      <div class="confirm-text"> 乙方、丙方同意并确认上述变更事项。 </div>
 
       <div class="sign-section">
         <div class="sign-row">
           <div class="sign-item">
             <span>甲方(盖章):</span>
-            <SignatureItem v-model="form.partyASign" :is-text-mode="isTextMode" width="180" height="70" placeholder="(盖章处)" title="甲方盖章" @update:model-value="updateForm" />
+            <SignatureItem
+              v-model="form.partyASign"
+              :is-text-mode="isTextMode"
+              width="180"
+              height="70"
+              placeholder="(盖章处)"
+              title="甲方盖章"
+              @update:model-value="updateForm"
+            />
           </div>
           <div class="sign-item">
             <span>乙方(签名或盖章):</span>
-            <SignatureItem v-model="form.partyBSign" :is-text-mode="isTextMode" width="180" height="70" placeholder="(签字处)" title="乙方签字" @update:model-value="updateForm" />
+            <SignatureItem
+              v-model="form.partyBSign"
+              :is-text-mode="isTextMode"
+              width="180"
+              height="70"
+              placeholder="(签字处)"
+              title="乙方签字"
+              @update:model-value="updateForm"
+            />
           </div>
         </div>
         <div class="sign-row single">
           <div class="sign-item">
             <span>丙方(签名或盖章):</span>
-            <SignatureItem v-model="form.partyCSign" :is-text-mode="isTextMode" width="180" height="70" placeholder="(签字处)" title="丙方签字" @update:model-value="updateForm" />
+            <SignatureItem
+              v-model="form.partyCSign"
+              :is-text-mode="isTextMode"
+              width="180"
+              height="70"
+              placeholder="(签字处)"
+              title="丙方签字"
+              @update:model-value="updateForm"
+            />
           </div>
         </div>
         <div class="date-row">
           <span>日期:</span>
-          <FieldItem v-model="form.year" :is-text-mode="isTextMode" width="60px" placeholder="" @update:model-value="updateForm" />
-          <span>年</span>
-          <FieldItem v-model="form.month" :is-text-mode="isTextMode" width="40px" placeholder="" @update:model-value="updateForm" />
-          <span>月</span>
-          <FieldItem v-model="form.day" :is-text-mode="isTextMode" width="40px" placeholder="" @update:model-value="updateForm" />
-          <span>日</span>
+          <FieldItem
+            v-model="form.signDate"
+            :is-text-mode="isTextMode"
+            type="date"
+            width="200px"
+            placeholder=""
+            @update:model-value="updateForm"
+          />
         </div>
       </div>
     </div>
@@ -291,6 +466,13 @@ defineExpose({ form })
 
   .service-inputs {
     padding-left: 8px;
+
+    .service-row {
+      display: flex;
+      align-items: center;
+      gap: 8px;
+      margin-bottom: 8px;
+    }
   }
 
   .service-lines {
@@ -309,6 +491,29 @@ defineExpose({ form })
     padding-left: 80px;
   }
 
+  .fee-list {
+    padding-left: 8px;
+
+    .fee-item {
+      margin-bottom: 8px;
+      display: flex;
+      align-items: center;
+      gap: 4px;
+    }
+  }
+
+  .other-fee-section {
+    padding-left: 8px;
+    margin-top: 8px;
+
+    .other-fee-item {
+      display: flex;
+      align-items: center;
+      gap: 4px;
+      margin-bottom: 8px;
+    }
+  }
+
   .confirm-text {
     margin-top: 20px;
     text-indent: 2em;

+ 137 - 3
src/views/elderly/contracts/components/ContractBody.vue

@@ -3,26 +3,82 @@ import { reactive, computed, ref, watch, onMounted } from 'vue'
 import { formatBackendDateTime } from '@/utils/formatTime'
 import { DICT_TYPE, getDictLabel } from '@/utils/dict'
 import { getTenantId } from '@/utils/auth'
-import {
-  getCheckInDetailByContractId
-} from '@/api/elderly/apply/check-in'
+import { getCheckInDetailByContractId } from '@/api/elderly/apply/check-in'
 import { getOverheadListByType } from '@/api/elderly/fee/overheadCharge'
 import FieldItem from './FieldItem.vue'
 import SignatureItem from './SignatureItem.vue'
 import { useUserStore } from '@/store/modules/user'
 import { getElderlyContractById } from '@/api/elderly/elder/contract'
 import { updateContractDate } from '@/api/elderly/fee/leave-settle'
+import {
+  riskDisclosure_getById,
+  checkInRegistration_getById,
+  elderSafetyCommitment_getById,
+  outingConfirmation_getById,
+  signatureProxyApplication_getById,
+  powerOfAttorney_getById,
+  delegationAgentConfirmation_getById,
+  serviceChargingStandards_getById,
+  roomFacilitiesEquipment_getById,
+  explanationExaminationReport_getById,
+  partyBIdentificationDocument_getById,
+  guardianPartyB_getById,
+  registrationCertificateCivilAffairs_getById,
+  comprehensiveAssessmentCapabilities_getById,
+  firstServiceProjectConfirmation_getById,
+  changeConfirmationForm_getById
+} from '@/api/elderly/contracts'
 const userStore = useUserStore()
+
+const attachmentConfig: Record<
+  string,
+  { idField: string; getDetail: (id: number | string) => Promise<any> }
+> = {
+  attach_1: { idField: 'riskDisclosureId', getDetail: riskDisclosure_getById },
+  attach_2: { idField: 'checkInTabId', getDetail: checkInRegistration_getById },
+  attach_4: { idField: 'safetyCommitmentId', getDetail: elderSafetyCommitment_getById },
+  attach_5: { idField: 'outingConfirmationFormId', getDetail: outingConfirmation_getById },
+  attach_6: {
+    idField: 'signatureProxyApplicationId',
+    getDetail: signatureProxyApplication_getById
+  },
+  attach_7: { idField: 'powerOfAttorneyId', getDetail: powerOfAttorney_getById },
+  attach_8: {
+    idField: 'authorizedAgentConfirmationId',
+    getDetail: delegationAgentConfirmation_getById
+  },
+  attach_9: { idField: 'orgServiceScopeFeeId', getDetail: serviceChargingStandards_getById },
+  attach_10: { idField: 'roomFacilityListId', getDetail: roomFacilitiesEquipment_getById },
+  attach_11: { idField: 'physicalExamReportId', getDetail: explanationExaminationReport_getById },
+  attach_12: { idField: 'partyBCertificateId', getDetail: partyBIdentificationDocument_getById },
+  attach_13: { idField: 'partyBGuardianCertificateId', getDetail: guardianPartyB_getById },
+  attach_14: {
+    idField: 'partyACertificateId',
+    getDetail: registrationCertificateCivilAffairs_getById
+  },
+  attach_15: {
+    idField: 'elderlyAbilityEvaluationId',
+    getDetail: comprehensiveAssessmentCapabilities_getById
+  },
+  attach_16: {
+    idField: 'firstServiceConfirmationId',
+    getDetail: firstServiceProjectConfirmation_getById
+  },
+  attach_17: { idField: 'changeConfirmationId', getDetail: changeConfirmationForm_getById }
+}
 const props = defineProps<{
   recordRow?: any
   isTextMode?: boolean
   signatureData?: any
   modelValue?: any
+  attachmentIds?: Record<string, any>
 }>()
 
 const emit = defineEmits<{
   (e: 'update:data', val: any): void
   (e: 'update:modelValue', val: any): void
+  (e: 'update:attachments', val: any): void
+  (e: 'update:formData', val: any): void
 }>()
 
 const loading = ref(false)
@@ -379,6 +435,40 @@ const fetchContractData = async (row: any) => {
         } catch (e) {
           console.error('解析合同信息失败', e)
         }
+        const attachmentsMap: Record<string, any> = {}
+        const detailPromises: Promise<any>[] = []
+        Object.keys(attachmentConfig).forEach((key) => {
+          const config = attachmentConfig[key]
+          console.log('config', config, key)
+          let id = undefined
+          try {
+             id = contractForm.attachments[key].id
+          }catch (e) {
+          }
+          console.log('id', id)
+          if (id) {
+            detailPromises.push(
+              config
+                .getDetail(id)
+                .then((detail) => {
+                  console.log('获取详情', detail)
+                  attachmentsMap[key] = JSON.parse(detail.content)
+
+                })
+                .catch((err) => {
+                  console.error(`获取附件详情失败: ${key}`, err)
+                  attachmentsMap[key] = { id }
+                })
+            )
+          } else {
+            attachmentsMap[key] = null
+          }
+        })
+        if (detailPromises.length > 0) {
+          await Promise.all(detailPromises)
+        }
+
+        emit('update:attachments', attachmentsMap)
         loading.value = false
       } else {
         console.log('保存')
@@ -553,6 +643,50 @@ const roomTypeOptions = computed(() => {
 
 const contractFormUpdate = ref({})
 
+const saveContract = async () => {
+  try {
+    console.log('历史:', contractForm.attachments)
+    if (!contractForm.attachments) {
+      contractForm.attachments = {}
+    }
+    const attachmentData: Record<string, any> = {}
+    if (props.attachmentIds) {
+      Object.keys(props.attachmentIds).forEach((key) => {
+        const row = props.attachmentIds![key]
+        console.log('保存1', key, row)
+        if (row) {
+          try {
+            const data = JSON.parse(row)
+            console.log('AAA', data)
+            if (data.id) {
+              console.log('AAA', data.id)
+              contractForm.attachments[key] = { id: data.id }
+              const config = attachmentConfig[key]
+              console.log('config', config)
+              contractFormUpdate.value[config.idField] = data.id
+              console.log('保存2', config, attachmentData)
+            }
+          } catch (e) {
+            console.log(e)
+          }
+        } else {
+        }
+      })
+    }
+    contractFormUpdate.value.contractInfo = JSON.stringify({
+      ...contractForm
+      // attachments: contractForm.attachments
+    })
+    const saveRes = await updateContractDate(contractFormUpdate.value)
+    return saveRes
+  } catch (error) {
+    console.error('保存合同失败', error)
+    throw error
+  }
+}
+
+defineExpose({ saveContract })
+
 onMounted(async () => {
   await loadBedTypes()
 })

+ 59 - 17
src/views/elderly/contracts/components/FirstServiceProjectConfirmationBody.vue

@@ -21,6 +21,7 @@ interface FormData {
   year?: string
   month?: string
   day?: string
+  signDate?: string
   basicServices?: Record<string, ServiceItem>
   lifeCare?: Record<string, any>
   elderlyNursing?: Record<string, any>
@@ -54,6 +55,7 @@ const form = reactive<FormData>({
   year: '',
   month: '',
   day: '',
+  signDate: '',
   basicServices: {
     consultation: defaultBasic(),
     mealService: defaultBasic(),
@@ -106,10 +108,63 @@ const form = reactive<FormData>({
 
 watch(() => props.modelValue, (val) => {
   if (!val) return
-  Object.assign(form, JSON.parse(JSON.stringify(val)))
+  const newVal = JSON.parse(JSON.stringify(val))
+  const mergedBasic = { ...form.basicServices }
+  const mergedLife = { ...form.lifeCare }
+  const mergedElderly = { ...form.elderlyNursing }
+  if (newVal.basicServices) {
+    Object.keys(newVal.basicServices).forEach(key => {
+      if (mergedBasic[key] && typeof mergedBasic[key] === 'object' && !Array.isArray(mergedBasic[key])) {
+        mergedBasic[key] = { ...mergedBasic[key], ...newVal.basicServices[key] }
+      } else {
+        mergedBasic[key] = newVal.basicServices[key]
+      }
+    })
+  }
+  if (newVal.lifeCare) {
+    Object.keys(newVal.lifeCare).forEach(key => {
+      if (mergedLife[key] && typeof mergedLife[key] === 'object' && !Array.isArray(mergedLife[key])) {
+        mergedLife[key] = { ...mergedLife[key], ...newVal.lifeCare[key] }
+      } else {
+        mergedLife[key] = newVal.lifeCare[key]
+      }
+    })
+  }
+  if (newVal.elderlyNursing) {
+    Object.keys(newVal.elderlyNursing).forEach(key => {
+      if (mergedElderly[key] && typeof mergedElderly[key] === 'object' && !Array.isArray(mergedElderly[key])) {
+        mergedElderly[key] = { ...mergedElderly[key], ...newVal.elderlyNursing[key] }
+      } else {
+        mergedElderly[key] = newVal.elderlyNursing[key]
+      }
+    })
+  }
+  Object.assign(form, newVal, {
+    basicServices: mergedBasic,
+    lifeCare: mergedLife,
+    elderlyNursing: mergedElderly
+  })
+  if (!form.signDate && form.year && form.month && form.day) {
+    form.signDate = `${form.year}年${form.month}月${form.day}日`
+  } else if (form.signDate) {
+    const m = form.signDate.match(/(\d{4})[年/\-.](\d{1,2})[月/\-.](\d{1,2})/)
+    if (m) {
+      form.year = m[1]
+      form.month = m[2]
+      form.day = m[3]
+    }
+  }
 }, { immediate: true, deep: true })
 
 const updateForm = () => {
+  if (form.signDate) {
+    const m = form.signDate.match(/(\d{4})[年/\-.](\d{1,2})[月/\-.](\d{1,2})/)
+    if (m) {
+      form.year = m[1]
+      form.month = m[2]
+      form.day = m[3]
+    }
+  }
   emit('update:modelValue', JSON.parse(JSON.stringify(form)))
 }
 
@@ -187,15 +242,6 @@ defineExpose({ form })
 <template>
   <div class="first-service-project">
     <div class="doc-title">首次服务项目确认表</div>
-    <div class="doc-date">
-      <span>时间:</span>
-      <FieldItem v-model="form.year" :is-text-mode="isTextMode" width="60px" placeholder="" @update:model-value="updateForm" />
-      <span>年</span>
-      <FieldItem v-model="form.month" :is-text-mode="isTextMode" width="40px" placeholder="" @update:model-value="updateForm" />
-      <span>月</span>
-      <FieldItem v-model="form.day" :is-text-mode="isTextMode" width="40px" placeholder="" @update:model-value="updateForm" />
-      <span>日</span>
-    </div>
 
     <!-- 基本信息 -->
     <table class="info-table">
@@ -206,7 +252,7 @@ defineExpose({ form })
           <td class="label">性别</td>
           <td><FieldItem v-model="form.gender" :is-text-mode="isTextMode" width="100%" placeholder="" @update:model-value="updateForm" /></td>
           <td class="label">房间号/床号</td>
-          <td><FieldItem v-model="form.roomNo" :is-text-mode="isTextMode" width="100%" placeholder="" @update:model-value="updateForm" />/<FieldItem v-model="form.bedNo" :is-text-mode="isTextMode" width="100%" placeholder="" @update:model-value="updateForm" /></td>
+          <td><FieldItem v-model="form.bedNo" :is-text-mode="isTextMode" width="100%" placeholder="" @update:model-value="updateForm" /></td>
         </tr>
         <tr>
           <td class="label">评估日期</td>
@@ -427,12 +473,8 @@ defineExpose({ form })
       </div>
     </div>
     <div class="date-row">
-      <FieldItem v-model="form.year" :is-text-mode="isTextMode" width="60px" placeholder="" @update:model-value="updateForm" />
-      <span>年</span>
-      <FieldItem v-model="form.month" :is-text-mode="isTextMode" width="40px" placeholder="" @update:model-value="updateForm" />
-      <span>月</span>
-      <FieldItem v-model="form.day" :is-text-mode="isTextMode" width="40px" placeholder="" @update:model-value="updateForm" />
-      <span>日</span>
+      日期:
+      <FieldItem v-model="form.signDate" :is-text-mode="isTextMode" type="date" width="220px" placeholder="" @update:model-value="updateForm" />
     </div>
 
     <!-- 备注 -->

+ 1 - 1
src/views/elderly/contracts/comprehensive-assessment-capabilities/index.vue

@@ -68,7 +68,7 @@
         show-overflow-tooltip
       />
       <el-table-column
-        prop="bedName"
+        prop="bedNumber"
         header-align="center"
         align="center"
         label="床位号"

+ 1 - 0
src/views/elderly/contracts/first-service-project-confirmation/AddForm.vue

@@ -130,6 +130,7 @@ const elderUp = (e) => {
   firstServiceForm.value.partyBName = e.elderName
   firstServiceForm.value.gender = e.elderSex === 1 ? '男' : e.elderSex === 2 ? '女' : ''
   firstServiceForm.value.bedNo = e.bedName || ''
+  firstServiceForm.value.careLevel = e.nurseLevelName || ''
 }
 
 const firstServiceForm = ref({

+ 1 - 1
src/views/elderly/contracts/first-service-project-confirmation/index.vue

@@ -68,7 +68,7 @@
         show-overflow-tooltip
       />
       <el-table-column
-        prop="bedName"
+        prop="bedNumber"
         header-align="center"
         align="center"
         label="床位号"

+ 1 - 1
src/views/elderly/contracts/guardian-party-b/index.vue

@@ -68,7 +68,7 @@
         show-overflow-tooltip
       />
       <el-table-column
-        prop="bedName"
+        prop="bedNumber"
         header-align="center"
         align="center"
         label="床位号"

+ 1 - 1
src/views/elderly/contracts/registration-certificate-civil-affairs-department/index.vue

@@ -68,7 +68,7 @@
         show-overflow-tooltip
       />
       <el-table-column
-        prop="bedName"
+        prop="bedNumber"
         header-align="center"
         align="center"
         label="床位号"

+ 26 - 7
src/views/elderly/elder/contract/Renewal.vue

@@ -679,12 +679,11 @@ const deathTime = computed(() => {
     dataForm.value.checkOutTime = data
     return data
   } else if (dataForm.value.checkInTime && dataForm.value.checkInDeadlineTime) {
-    const data =
-      dataForm.value.checkInDeadlineTime
-      // +
-      // '(' +
-      // dayjs(dataForm.value.checkInDeadlineTime).add(1, 'day').diff(dataForm.value.checkInTime, 'day') +
-      // '天)'
+    const data = dataForm.value.checkInDeadlineTime
+    // +
+    // '(' +
+    // dayjs(dataForm.value.checkInDeadlineTime).add(1, 'day').diff(dataForm.value.checkInTime, 'day') +
+    // '天)'
     dataForm.value.checkOutTime = data
     return data
   }
@@ -731,6 +730,24 @@ const expenseChargeTypeLabel = (item: any) =>
 
 /** 提交表单 */
 const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+
+function getStatus() {
+
+  // 1. 将字符串转为日期对象 (建议用 T00:00:00 强制作为当天 0 点解析,防止时区偏移)
+  const targetDate = new Date(`${dataForm.value.checkInTime}T00:00:00`)
+
+  // 2. 获取当前日期,并将当前时、分、秒、毫秒全部归零
+  const currentDate = new Date()
+  currentDate.setHours(0, 0, 0, 0)
+
+  // 3. 直接比较时间戳
+  if (targetDate.getTime() <= currentDate.getTime()) {
+    return 1 // 小于或等于当前日期
+  } else {
+    return 2 // 大于当前日期(未来的日期)
+  }
+}
+
 const submitForm = async () => {
   if (formLoading.value) {
     return
@@ -765,7 +782,8 @@ const submitForm = async () => {
         details: dataForm.value.details,
         specialCareNotes: dataForm.value.specialCareNotes,
         inStatusType: dataForm.value.inStatusType,
-        tenantId: dataForm.value.tenantId
+        tenantId: dataForm.value.tenantId,
+        status: getStatus()
       },
       totalAmount: formatRid(
         Number(formatDecimal(totalMonthFee.value)) +
@@ -783,6 +801,7 @@ const submitForm = async () => {
       inStatusType: dataForm.value.inStatusType,
       tenantId: dataForm.value.tenantId
     }
+    return
     // if (dataForm.value.inStatusType == '1') {
     //   data.monthlyExpenses.push(...arr)
     // }