Sfoglia il codice sorgente

Merge branch 'master' of http://47.107.245.0:3000/xiongxing/kyj-yanglao-web-new

xiongxing 3 settimane fa
parent
commit
5061046feb

+ 7 - 0
src/api/elderly/common/index.ts

@@ -14,3 +14,10 @@ export const cancelprocessInstance = (data) => {
     data
   })
 }
+
+// 获取家属签名列表(根据长者id)
+export const getFamilyMemberSign = (elderId: number | string) => {
+  return request.get({
+    url: `elderlyInfo/getFamilyMemberSign?elderId=${elderId}`
+  })
+}

+ 0 - 1046
src/views/elderly/apply/check-in/contract_remainder.txt

@@ -1,1046 +0,0 @@
-
-      <!-- ========== 附件二:入住登记表 ========== -->
-      <div class="a4-page">
-        <div class="page-header">
-          <span class="page-no">23</span>
-        </div>
-        <div class="page-content">
-          <h1 class="doc-title">附件二:入住登记表</h1>
-          <table class="info-table">
-            <tr>
-              <th>姓名</th>
-              <td>{{ contractForm.elderName || '' }}</td>
-              <th>性别</th>
-              <td>{{ contractForm.elderGender || '' }}</td>
-              <th>出生年月</th>
-              <td>{{ contractForm.elderBirth || '' }}</td>
-            </tr>
-            <tr>
-              <th>身份证号</th>
-              <td colspan="3">{{ contractForm.elderIdCard || '' }}</td>
-              <th>民族</th>
-              <td>{{ contractForm.elderNation || '' }}</td>
-            </tr>
-            <tr>
-              <th>籍贯</th>
-              <td>{{ contractForm.elderNative || '' }}</td>
-              <th>文化程度</th>
-              <td>{{ contractForm.elderEducation || '' }}</td>
-              <th>婚姻状况</th>
-              <td>{{ contractForm.elderMarital || '' }}</td>
-            </tr>
-            <tr>
-              <th>联系电话</th>
-              <td colspan="3">{{ contractForm.elderPhone || '' }}</td>
-              <th>医保类型</th>
-              <td>{{ contractForm.elderInsurance || '' }}</td>
-            </tr>
-            <tr>
-              <th>户籍地址</th>
-              <td colspan="5">{{ contractForm.elderAddress || '' }}</td>
-            </tr>
-            <tr>
-              <th>紧急联系人1</th>
-              <td>{{ contractForm.partyCName || '' }}</td>
-              <th>关系</th>
-              <td>{{ contractForm.partyCRelation || '' }}</td>
-              <th>电话</th>
-              <td>{{ contractForm.partyCPhone || '' }}</td>
-            </tr>
-            <tr>
-              <th>紧急联系人2</th>
-              <td>{{ contractForm.emergencyContact2Name || '' }}</td>
-              <th>关系</th>
-              <td>{{ contractForm.emergencyContact2Relation || '' }}</td>
-              <th>电话</th>
-              <td>{{ contractForm.emergencyContact2Phone || '' }}</td>
-            </tr>
-            <tr>
-              <th>护理等级</th>
-              <td colspan="5">{{ contractForm.nurseLevelName || '' }}</td>
-            </tr>
-            <tr>
-              <th>既往病史</th>
-              <td colspan="5">{{ contractForm.medicalHistory || '' }}</td>
-            </tr>
-            <tr>
-              <th>过敏史</th>
-              <td colspan="5">{{ contractForm.allergyHistory || '' }}</td>
-            </tr>
-            <tr>
-              <th>生活习惯</th>
-              <td colspan="5">{{ contractForm.livingHabit || '' }}</td>
-            </tr>
-            <tr>
-              <th>兴趣爱好</th>
-              <td colspan="5">{{ contractForm.hobby || '' }}</td>
-            </tr>
-          </table>
-          <div class="sign-block">
-            <p class="sign-line">长者(签字):
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.regSign1 || '____________________' }}</span>
-                <ESign v-show="!isPrint" v-model="contractForm.regSign1" />
-              </span>
-            </p>
-            <p class="sign-line">家属/监护人(签字):
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.regSign2 || '____________________' }}</span>
-                <ESign v-show="!isPrint" v-model="contractForm.regSign2" />
-              </span>
-            </p>
-            <p class="sign-line">登记日期:
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.regDate || '____年__月__日' }}</span>
-                <el-date-picker v-show="!isPrint" v-model="contractForm.regDate" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" size="small" style="width: 180px;" />
-              </span>
-            </p>
-          </div>
-        </div>
-      </div>
-
-      <!-- ========== 附件三:入住须知 ========== -->
-      <div class="a4-page">
-        <div class="page-header">
-          <span class="page-no">24</span>
-        </div>
-        <div class="page-content">
-          <h1 class="doc-title">附件三:入住须知</h1>
-          <h3 class="subsection-title">一、入住须知</h3>
-          <p class="content-text">1.长者入住前须提供二级甲等以上医院出具的近30日内的体检报告(体检项目按附件十执行)。</p>
-          <p class="content-text">2.入住时须提交长者及监护人身份证、户口本原件及复印件各一份。</p>
-          <p class="content-text">3.入住时须提交长者近期一寸免冠彩色照片3张。</p>
-          <p class="content-text">4.入住时须交纳押金及首月相关费用。</p>
-          <p class="content-text">5.长者自带的药品,须登记造册,由工作人员统一管理。</p>
-          <h3 class="subsection-title">二、管理制度</h3>
-          <p class="content-text">1.作息时间:夏季:6:00起床,21:00熄灯;冬季:6:30起床,20:30熄灯。</p>
-          <p class="content-text">2.用餐时间:早餐7:00-8:00,午餐11:30-12:30,晚餐17:30-18:30。</p>
-          <p class="content-text">3.会客时间:8:30-11:30,14:00-17:00(特殊情况除外)。</p>
-          <p class="content-text">4.外出须请假,经批准后方可外出,外出期间发生的一切责任自负。</p>
-          <p class="content-text">5.禁止携带易燃、易爆、有毒等危险品。</p>
-          <p class="content-text">6.贵重物品请自行妥善保管,丢失自负。</p>
-          <p class="content-text">7.爱护公共设施,损坏照价赔偿。</p>
-          <p class="content-text">8.长者之间应互相关心、互相帮助,团结友爱,不得发生争执、打架等事件。</p>
-          <h3 class="subsection-title">三、家属须知</h3>
-          <p class="content-text">1.家属应保持与机构的联系,电话、地址如有变更及时通知机构。</p>
-          <p class="content-text">2.家属探视应遵守机构的探视制度,不得影响其他长者正常生活。</p>
-          <p class="content-text">3.家属应积极配合机构的工作,对长者的身体状况、情绪变化及时沟通。</p>
-          <p class="content-text">4.长者生病或发生意外,家属接到通知后应及时赶到。</p>
-          <div class="sign-block">
-            <p class="sign-line">长者(签字):
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.noticeSign1 || '____________________' }}</span>
-                <ESign v-show="!isPrint" v-model="contractForm.noticeSign1" />
-              </span>
-            </p>
-            <p class="sign-line">家属/监护人(签字):
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.noticeSign2 || '____________________' }}</span>
-                <ESign v-show="!isPrint" v-model="contractForm.noticeSign2" />
-              </span>
-            </p>
-            <p class="sign-line">日期:
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.noticeDate || '____年__月__日' }}</span>
-                <el-date-picker v-show="!isPrint" v-model="contractForm.noticeDate" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" size="small" style="width: 180px;" />
-              </span>
-            </p>
-          </div>
-        </div>
-      </div>
-
-      <!-- ========== 附件四:长者安全承诺书 ========== -->
-      <div class="a4-page">
-        <div class="page-header">
-          <span class="page-no">25</span>
-        </div>
-        <div class="page-content">
-          <h1 class="doc-title">附件四:长者安全承诺书</h1>
-          <p class="content-text"><strong>本人自愿入住颐年集团养老服务机构,并承诺如下:</strong></p>
-          <p class="content-text">一、本人及家属已如实向机构告知本人的身体健康状况、过往病史、过敏史、用药情况等信息,如有隐瞒或不实陈述,由此引发的一切后果由本人及家属自行承担。</p>
-          <p class="content-text">二、本人承诺严格遵守机构的各项规章制度,服从工作人员的管理和服务安排。</p>
-          <p class="content-text">三、本人承诺不擅自离开机构,如需外出须办理请假手续。擅自外出期间发生的一切人身伤害、财产损失由本人及家属自行承担。</p>
-          <p class="content-text">四、本人承诺不携带易燃、易爆、有毒等危险品进入机构,不在房间内使用大功率电器。</p>
-          <p class="content-text">五、本人因年老体弱、行动不便等原因,存在发生摔倒、骨折、突发疾病等风险,本人及家属对此完全知晓并自愿承担相应风险。</p>
-          <p class="content-text">六、如本人发生意外情况,机构有权根据实际情况采取必要的救治措施(包括拨打120急救电话),由此产生的一切费用由本人及家属承担。</p>
-          <p class="content-text">七、本人及家属承诺按时缴纳各项费用,如逾期未缴,机构有权暂停服务或解除合同。</p>
-          <p class="content-text">八、本人及家属已认真阅读并理解本承诺书的全部内容,自愿签署本承诺书。</p>
-          <div class="sign-block">
-            <p class="sign-line">长者(签字):
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.safetySign1 || '____________________' }}</span>
-                <ESign v-show="!isPrint" v-model="contractForm.safetySign1" />
-              </span>
-            </p>
-            <p class="sign-line">家属/监护人(签字):
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.safetySign2 || '____________________' }}</span>
-                <ESign v-show="!isPrint" v-model="contractForm.safetySign2" />
-              </span>
-            </p>
-            <p class="sign-line">日期:
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.safetyDate || '____年__月__日' }}</span>
-                <el-date-picker v-show="!isPrint" v-model="contractForm.safetyDate" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" size="small" style="width: 180px;" />
-              </span>
-            </p>
-          </div>
-        </div>
-      </div>
-
-      <!-- ========== 附件五:长者外出情况确认书 ========== -->
-      <div class="a4-page">
-        <div class="page-header">
-          <span class="page-no">26</span>
-        </div>
-        <div class="page-content">
-          <h1 class="doc-title">附件五:长者外出情况确认书</h1>
-          <p class="content-text">为保障长者外出期间的人身安全,特制定本确认书,长者及家属在外出前须确认以下事项:</p>
-          <table class="info-table">
-            <tr>
-              <th>外出长者姓名</th>
-              <td>{{ contractForm.elderName || '' }}</td>
-              <th>外出日期</th>
-              <td>
-                <span v-if="isPrint">{{ contractForm.outDate || '____年__月__日' }}</span>
-                <el-date-picker v-show="!isPrint" v-model="contractForm.outDate" type="daterange" range-separator="至" start-placeholder="开始" end-placeholder="结束" value-format="YYYY-MM-DD" size="small" />
-              </td>
-            </tr>
-            <tr>
-              <th>外出原因</th>
-              <td colspan="3">{{ contractForm.outReason || '' }}</td>
-            </tr>
-            <tr>
-              <th>前往地点</th>
-              <td colspan="3">{{ contractForm.outLocation || '' }}</td>
-            </tr>
-            <tr>
-              <th>陪同人员</th>
-              <td>{{ contractForm.outCompanion || '' }}</td>
-              <th>联系电话</th>
-              <td>{{ contractForm.outPhone || '' }}</td>
-            </tr>
-            <tr>
-              <th>预计返回时间</th>
-              <td colspan="3">
-                <span v-if="isPrint">{{ contractForm.returnDate || '____年__月__日' }}</span>
-                <el-date-picker v-show="!isPrint" v-model="contractForm.returnDate" type="date" placeholder="返回日期" value-format="YYYY-MM-DD" size="small" />
-              </td>
-            </tr>
-            <tr>
-              <th>身体状况</th>
-              <td colspan="3">{{ contractForm.outHealthStatus || '' }}</td>
-            </tr>
-            <tr>
-              <th>随身物品</th>
-              <td colspan="3">{{ contractForm.outItems || '' }}</td>
-            </tr>
-          </table>
-          <p class="content-text"><strong>特别声明:</strong>长者外出期间,机构已尽到合理告知义务,外出期间发生的一切人身伤害、财产损失由长者本人及家属自行承担,与机构无关。</p>
-          <div class="sign-block">
-            <p class="sign-line">长者(签字):
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.outSign1 || '____________________' }}</span>
-                <ESign v-show="!isPrint" v-model="contractForm.outSign1" />
-              </span>
-            </p>
-            <p class="sign-line">家属/监护人(签字):
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.outSign2 || '____________________' }}</span>
-                <ESign v-show="!isPrint" v-model="contractForm.outSign2" />
-              </span>
-            </p>
-            <p class="sign-line">机构经办人(签字):
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.outSign3 || '____________________' }}</span>
-                <el-input v-show="!isPrint" v-model="contractForm.outSign3" placeholder="经办人签字" size="small" style="width: 200px;" />
-              </span>
-            </p>
-            <p class="sign-line">日期:
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.outConfirmDate || '____年__月__日' }}</span>
-                <el-date-picker v-show="!isPrint" v-model="contractForm.outConfirmDate" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" size="small" style="width: 180px;" />
-              </span>
-            </p>
-          </div>
-        </div>
-      </div>
-
-      <!-- ========== 附件六:签名代理申请 ========== -->
-      <div class="a4-page">
-        <div class="page-header">
-          <span class="page-no">27</span>
-        </div>
-        <div class="page-content">
-          <h1 class="doc-title">附件六:签名代理申请</h1>
-          <p class="content-text"><strong>申请人:</strong>{{ contractForm.elderName || '' }}</p>
-          <p class="content-text"><strong>申请事项:</strong>因本人年事已高/身体原因/书写困难,特申请由以下人员代为签署与养老服务相关的各项文件。</p>
-          <table class="info-table">
-            <tr>
-              <th>代理人姓名</th>
-              <td>{{ contractForm.agentName || '' }}</td>
-              <th>与申请人关系</th>
-              <td>{{ contractForm.agentRelation || '' }}</td>
-            </tr>
-            <tr>
-              <th>身份证号</th>
-              <td colspan="3">{{ contractForm.agentIdCard || '' }}</td>
-            </tr>
-            <tr>
-              <th>联系电话</th>
-              <td colspan="3">{{ contractForm.agentPhone || '' }}</td>
-            </tr>
-            <tr>
-              <th>联系地址</th>
-              <td colspan="3">{{ contractForm.agentAddress || '' }}</td>
-            </tr>
-            <tr>
-              <th>代理权限</th>
-              <td colspan="3">{{ contractForm.agentAuthority || '代为签署与养老服务相关的各项文件' }}</td>
-            </tr>
-            <tr>
-              <th>代理期限</th>
-              <td colspan="3">{{ contractForm.agentPeriod || '自本申请签署之日起至长者离院之日止' }}</td>
-            </tr>
-          </table>
-          <p class="content-text"><strong>特别说明:</strong></p>
-          <p class="content-text">1.代理人在代理权限内签署的文件,对申请人具有同等法律效力。</p>
-          <p class="content-text">2.申请人如需变更或撤销代理人,须书面通知机构。</p>
-          <p class="content-text">3.代理人签署的文件如涉及重大利益处分,机构有权要求申请人本人确认。</p>
-          <div class="sign-block">
-            <p class="sign-line">申请人(签字):
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.agentApplySign1 || '____________________' }}</span>
-                <ESign v-show="!isPrint" v-model="contractForm.agentApplySign1" />
-              </span>
-            </p>
-            <p class="sign-line">代理人(签字):
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.agentApplySign2 || '____________________' }}</span>
-                <ESign v-show="!isPrint" v-model="contractForm.agentApplySign2" />
-              </span>
-            </p>
-            <p class="sign-line">日期:
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.agentApplyDate || '____年__月__日' }}</span>
-                <el-date-picker v-show="!isPrint" v-model="contractForm.agentApplyDate" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" size="small" style="width: 180px;" />
-              </span>
-            </p>
-          </div>
-        </div>
-      </div>
-
-      <!-- ========== 附件七:委托代理人确认表 ========== -->
-      <div class="a4-page">
-        <div class="page-header">
-          <span class="page-no">28</span>
-        </div>
-        <div class="page-content">
-          <h1 class="doc-title">附件七:委托代理人确认表</h1>
-          <p class="content-text">机构根据长者及家属提交的委托代理申请,确认以下委托代理人:</p>
-          <table class="info-table">
-            <tr>
-              <th style="width:120px;">委托人(长者)</th>
-              <td>{{ contractForm.elderName || '' }}</td>
-              <th style="width:100px;">身份证号</th>
-              <td>{{ contractForm.elderIdCard || '' }}</td>
-            </tr>
-            <tr>
-              <th>委托代理人</th>
-              <td>{{ contractForm.partyCName || '' }}</td>
-              <th>与委托人关系</th>
-              <td>{{ contractForm.partyCRelation || '' }}</td>
-            </tr>
-            <tr>
-              <th>代理人身份证号</th>
-              <td colspan="3">{{ contractForm.partyCIdCard || '' }}</td>
-            </tr>
-            <tr>
-              <th>联系电话</th>
-              <td colspan="3">{{ contractForm.partyCPhone || '' }}</td>
-            </tr>
-            <tr>
-              <th>委托事项</th>
-              <td colspan="3">{{ contractForm.entrustItems || '代为办理长者入住、退住、费用缴纳、重大决策等事项' }}</td>
-            </tr>
-            <tr>
-              <th>委托期限</th>
-              <td colspan="3">{{ contractForm.entrustPeriod || '自本确认表签署之日起至长者离院之日止' }}</td>
-            </tr>
-            <tr>
-              <th>机构确认</th>
-              <td colspan="3">{{ contractForm.orgConfirm || '已收到上述委托代理申请,确认代理人资格。' }}</td>
-            </tr>
-          </table>
-          <div class="sign-block">
-            <p class="sign-line">委托人(签字):
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.entrustSign1 || '____________________' }}</span>
-                <ESign v-show="!isPrint" v-model="contractForm.entrustSign1" />
-              </span>
-            </p>
-            <p class="sign-line">委托代理人(签字):
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.entrustSign2 || '____________________' }}</span>
-                <ESign v-show="!isPrint" v-model="contractForm.entrustSign2" />
-              </span>
-            </p>
-            <p class="sign-line">机构经办人(签字):
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.entrustSign3 || '____________________' }}</span>
-                <el-input v-show="!isPrint" v-model="contractForm.entrustSign3" placeholder="经办人" size="small" style="width: 200px;" />
-              </span>
-            </p>
-            <p class="sign-line">机构盖章:
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.orgStamp || '____________________' }}</span>
-                <ESign v-show="!isPrint" v-model="contractForm.orgStamp" />
-              </span>
-            </p>
-            <p class="sign-line">日期:
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.entrustDate || '____年__月__日' }}</span>
-                <el-date-picker v-show="!isPrint" v-model="contractForm.entrustDate" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" size="small" style="width: 180px;" />
-              </span>
-            </p>
-          </div>
-        </div>
-      </div>
-
-      <!-- ========== 附件八:机构服务范围及收费标准 ========== -->
-      <div class="a4-page">
-        <div class="page-header">
-          <span class="page-no">29</span>
-        </div>
-        <div class="page-content">
-          <h1 class="doc-title">附件八:机构服务范围及收费标准</h1>
-          <h3 class="subsection-title">一、服务范围</h3>
-          <p class="content-text">1.提供日常生活照料服务:包括饮食、穿衣、如厕、沐浴、清洁卫生等。</p>
-          <p class="content-text">2.提供基本医疗保健服务:包括健康监测、慢病管理、用药指导等。</p>
-          <p class="content-text">3.提供文化娱乐服务:包括文娱活动、健身锻炼、兴趣小组等。</p>
-          <p class="content-text">4.提供心理支持服务:包括情感慰藉、心理疏导、精神关怀等。</p>
-          <p class="content-text">5.提供安全保障服务:包括24小时值班、安全巡视、紧急救援等。</p>
-          <h3 class="subsection-title">二、收费标准</h3>
-          <table class="info-table border-table">
-            <tr>
-              <th>项目</th>
-              <th>自理</th>
-              <th>半自理</th>
-              <th>不能自理</th>
-              <th>特护</th>
-            </tr>
-            <tr>
-              <td>床位费</td>
-              <td>{{ contractForm.feeBedSelf || '¥____' }}</td>
-              <td>{{ contractForm.feeBedHalf || '¥____' }}</td>
-              <td>{{ contractForm.feeBedNone || '¥____' }}</td>
-              <td>{{ contractForm.feeBedSpecial || '¥____' }}</td>
-            </tr>
-            <tr>
-              <td>护理费</td>
-              <td>{{ contractForm.feeNurseSelf || '¥____' }}</td>
-              <td>{{ contractForm.feeNurseHalf || '¥____' }}</td>
-              <td>{{ contractForm.feeNurseNone || '¥____' }}</td>
-              <td>{{ contractForm.feeNurseSpecial || '¥____' }}</td>
-            </tr>
-            <tr>
-              <td>膳食费</td>
-              <td>{{ contractForm.feeMealSelf || '¥____' }}</td>
-              <td>{{ contractForm.feeMealHalf || '¥____' }}</td>
-              <td>{{ contractForm.feeMealNone || '¥____' }}</td>
-              <td>{{ contractForm.feeMealSpecial || '¥____' }}</td>
-            </tr>
-            <tr>
-              <td>管理费</td>
-              <td>{{ contractForm.feeManageSelf || '¥____' }}</td>
-              <td>{{ contractForm.feeManageHalf || '¥____' }}</td>
-              <td>{{ contractForm.feeManageNone || '¥____' }}</td>
-              <td>{{ contractForm.feeManageSpecial || '¥____' }}</td>
-            </tr>
-            <tr>
-              <td>水电费</td>
-              <td>{{ contractForm.feeWaterSelf || '¥____' }}</td>
-              <td>{{ contractForm.feeWaterHalf || '¥____' }}</td>
-              <td>{{ contractForm.feeWaterNone || '¥____' }}</td>
-              <td>{{ contractForm.feeWaterSpecial || '¥____' }}</td>
-            </tr>
-            <tr>
-              <td>合计(月)</td>
-              <td>{{ contractForm.feeTotalSelf || '¥____' }}</td>
-              <td>{{ contractForm.feeTotalHalf || '¥____' }}</td>
-              <td>{{ contractForm.feeTotalNone || '¥____' }}</td>
-              <td>{{ contractForm.feeTotalSpecial || '¥____' }}</td>
-            </tr>
-          </table>
-          <p class="content-text"><strong>说明:</strong></p>
-          <p class="content-text">1.押金:入住时交纳,退住时无损坏全额退还。</p>
-          <p class="content-text">2.一次性费用:包括入住评估费、生活用品费等,入住时一次性交纳。</p>
-          <p class="content-text">3.以上收费标准仅供参考,具体以实际签订的服务合同为准。</p>
-          <p class="content-text">4.费用调整须提前30日以书面形式通知。</p>
-          <div class="sign-block">
-            <p class="sign-line">长者(签字):
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.feeSign1 || '____________________' }}</span>
-                <ESign v-show="!isPrint" v-model="contractForm.feeSign1" />
-              </span>
-            </p>
-            <p class="sign-line">家属/监护人(签字):
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.feeSign2 || '____________________' }}</span>
-                <ESign v-show="!isPrint" v-model="contractForm.feeSign2" />
-              </span>
-            </p>
-            <p class="sign-line">机构盖章:
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.feeOrgSign || '____________________' }}</span>
-                <ESign v-show="!isPrint" v-model="contractForm.feeOrgSign" />
-              </span>
-            </p>
-          </div>
-        </div>
-      </div>
-
-      <!-- ========== 附件九:房间设施设备清单 ========== -->
-      <div class="a4-page">
-        <div class="page-header">
-          <span class="page-no">30</span>
-        </div>
-        <div class="page-content">
-          <h1 class="doc-title">附件九:房间设施设备清单</h1>
-          <p class="content-text">长者:{{ contractForm.elderName || '' }},入住房间:{{ contractForm.roomNumber || '' }}</p>
-          <table class="info-table border-table">
-            <tr>
-              <th style="width:60px;">序号</th>
-              <th>物品名称</th>
-              <th style="width:80px;">数量</th>
-              <th style="width:80px;">单位</th>
-              <th>状态</th>
-              <th>备注</th>
-            </tr>
-            <tr><td>1</td><td>床</td><td>{{ contractForm.itemBed || '1' }}</td><td>张</td><td>{{ contractForm.itemBedStatus || '完好' }}</td><td>{{ contractForm.itemBedNote || '' }}</td></tr>
-            <tr><td>2</td><td>床垫</td><td>{{ contractForm.itemMattress || '1' }}</td><td>张</td><td>{{ contractForm.itemMattressStatus || '完好' }}</td><td>{{ contractForm.itemMattressNote || '' }}</td></tr>
-            <tr><td>3</td><td>床头柜</td><td>{{ contractForm.itemNightstand || '1' }}</td><td>个</td><td>{{ contractForm.itemNightstandStatus || '完好' }}</td><td>{{ contractForm.itemNightstandNote || '' }}</td></tr>
-            <tr><td>4</td><td>衣柜</td><td>{{ contractForm.itemWardrobe || '1' }}</td><td>个</td><td>{{ contractForm.itemWardrobeStatus || '完好' }}</td><td>{{ contractForm.itemWardrobeNote || '' }}</td></tr>
-            <tr><td>5</td><td>桌椅</td><td>{{ contractForm.itemTable || '1' }}</td><td>套</td><td>{{ contractForm.itemTableStatus || '完好' }}</td><td>{{ contractForm.itemTableNote || '' }}</td></tr>
-            <tr><td>6</td><td>空调</td><td>{{ contractForm.itemAircon || '1' }}</td><td>台</td><td>{{ contractForm.itemAirconStatus || '完好' }}</td><td>{{ contractForm.itemAirconNote || '' }}</td></tr>
-            <tr><td>7</td><td>电视机</td><td>{{ contractForm.itemTV || '1' }}</td><td>台</td><td>{{ contractForm.itemTVStatus || '完好' }}</td><td>{{ contractForm.itemTVNote || '' }}</td></tr>
-            <tr><td>8</td><td>呼叫器</td><td>{{ contractForm.itemCaller || '1' }}</td><td>个</td><td>{{ contractForm.itemCallerStatus || '完好' }}</td><td>{{ contractForm.itemCallerNote || '' }}</td></tr>
-            <tr><td>9</td><td>照明灯具</td><td>{{ contractForm.itemLamp || '2' }}</td><td>盏</td><td>{{ contractForm.itemLampStatus || '完好' }}</td><td>{{ contractForm.itemLampNote || '' }}</td></tr>
-            <tr><td>10</td><td>卫生间设施</td><td>{{ contractForm.itemBath || '1' }}</td><td>套</td><td>{{ contractForm.itemBathStatus || '完好' }}</td><td>{{ contractForm.itemBathNote || '' }}</td></tr>
-          </table>
-          <p class="content-text"><strong>备注说明:</strong></p>
-          <p class="content-text">1.以上设施设备由机构统一配置,长者应爱护使用,如有损坏照价赔偿。</p>
-          <p class="content-text">2.长者个人物品请自行妥善保管,机构不承担保管责任。</p>
-          <p class="content-text">3.设施设备如发生故障,请及时通知工作人员维修。</p>
-          <div class="sign-block">
-            <p class="sign-line">长者/家属(签字):
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.itemSign1 || '____________________' }}</span>
-                <ESign v-show="!isPrint" v-model="contractForm.itemSign1" />
-              </span>
-            </p>
-            <p class="sign-line">机构经办人(签字):
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.itemSign2 || '____________________' }}</span>
-                <el-input v-show="!isPrint" v-model="contractForm.itemSign2" placeholder="经办人" size="small" style="width: 200px;" />
-              </span>
-            </p>
-            <p class="sign-line">验收日期:
-              <span class="inline-edit-block">
-                <span v-if="isPrint">{{ contractForm.itemDate || '____年__月__日' }}</span>
-                <el-date-picker v-show="!isPrint" v-model="contractForm.itemDate" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" size="small" style="width: 180px;" />
-              </span>
-            </p>
-          </div>
-        </div>
-      </div>
-
-      <!-- ========== 附件十:体检报告项目说明 ========== -->
-      <div class="a4-page">
-        <div class="page-header">
-          <span class="page-no">31</span>
-        </div>
-        <div class="page-content">
-          <h1 class="doc-title">附件十:体检报告项目说明</h1>
-          <p class="content-text">(体检时间应在签订服务合同前30日以内,须由二级甲等以上医院出具)</p>
-          <table class="info-table border-table">
-            <tr>
-              <th style="width:60px;">序号</th>
-              <th>体检项目</th>
-              <th style="width:150px;">检查结果</th>
-              <th>备注</th>
-            </tr>
-            <tr><td>1</td><td>一般检查(身高、体重、血压、脉搏)</td><td>{{ contractForm.check1 || '' }}</td><td>{{ contractForm.checkNote1 || '' }}</td></tr>
-            <tr><td>2</td><td>血常规</td><td>{{ contractForm.check2 || '' }}</td><td>{{ contractForm.checkNote2 || '' }}</td></tr>
-            <tr><td>3</td><td>尿常规</td><td>{{ contractForm.check3 || '' }}</td><td>{{ contractForm.checkNote3 || '' }}</td></tr>
-            <tr><td>4</td><td>肝功能</td><td>{{ contractForm.check4 || '' }}</td><td>{{ contractForm.checkNote4 || '' }}</td></tr>
-            <tr><td>5</td><td>肾功能</td><td>{{ contractForm.check5 || '' }}</td><td>{{ contractForm.checkNote5 || '' }}</td></tr>
-            <tr><td>6</td><td>血脂</td><td>{{ contractForm.check6 || '' }}</td><td>{{ contractForm.checkNote6 || '' }}</td></tr>
-            <tr><td>7</td><td>血糖</td><td>{{ contractForm.check7 || '' }}</td><td>{{ contractForm.checkNote7 || '' }}</td></tr>
-            <tr><td>8</td><td>心电图</td><td>{{ contractForm.check8 || '' }}</td><td>{{ contractForm.checkNote8 || '' }}</td></tr>
-            <tr><td>9</td><td>胸部X光</td><td>{{ contractForm.check9 || '' }}</td><td>{{ contractForm.checkNote9 || '' }}</td></tr>
-            <tr><td>10</td><td>B超(腹部)</td><td>{{ contractForm.check10 || '' }}</td><td>{{ contractForm.checkNote10 || '' }}</td></tr>
-            <tr><td>11</td><td>精神健康状况评估</td><td>{{ contractForm.check11 || '' }}</td><td>{{ contractForm.checkNote11 || '' }}</td></tr>
-            <tr><td>12</td><td>传染性疾病检查</td><td>{{ contractForm.check12 || '' }}</td><td>{{ contractForm.checkNote12 || '' }}</td></tr>
-            <tr><td>13</td><td>既往病史陈述</td><td>{{ contractForm.check13 || '' }}</td><td>{{ contractForm.checkNote13 || '' }}</td></tr>
-            <tr><td>14</td><td>过敏史</td><td>{{ contractForm.check14 || '' }}</td><td>{{ contractForm.checkNote14 || '' }}</td></tr>
-            <tr><td>15</td><td>用药情况</td><td>{{ contractForm.check15 || '' }}</td><td>{{ contractForm.checkNote15 || '' }}</td></tr>
-          </table>
-          <p class="content-text"><strong>体检机构:</strong>{{ contractForm.checkOrg || '' }}</p>
-          <p class="content-text"><strong>体检日期:</strong>
-            <span class="inline-edit-block">
-              <span v-if="isPrint">{{ contractForm.checkDate || '____年__月__日' }}</span>
-              <el-date-picker v-show="!isPrint" v-model="contractForm.checkDate" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" size="small" style="width: 180px;" />
-            </span>
-          </p>
-          <p class="content-text"><strong>医生建议:</strong>{{ contractForm.checkAdvice || '' }}</p>
-          <p class="content-text"><strong>重要提示:</strong>体检报告是评估长者身体状况、确定护理等级的重要依据,长者及家属应如实提供。如发现重大健康问题,机构有权要求长者到医院进一步检查或拒绝入住。</p>
-        </div>
-      </div>
-
-      <!-- ========== 附件十一+十二:身份证复印件上传 ========== -->
-      <div class="a4-page">
-        <div class="page-header">
-          <span class="page-no">32</span>
-        </div>
-        <div class="page-content">
-          <h1 class="doc-title">附件十一:长者有效证件复印件</h1>
-          <div class="upload-block">
-            <p class="content-text">长者身份证正反面复印件(上传图片):</p>
-            <el-upload v-show="!isPrint"
-              v-model:file-list="contractForm.elderIdCardFiles"
-              action="#"
-              list-type="picture-card"
-              :auto-upload="false"
-              :limit="2"
-            >
-              <el-icon><Plus /></el-icon>
-            </el-upload>
-            <div v-if="isPrint && contractForm.elderIdCardFiles && contractForm.elderIdCardFiles.length > 0" class="print-images">
-              <img v-for="(f, i) in contractForm.elderIdCardFiles" :key="i" :src="f.url" style="max-width:300px; margin:10px;" />
-            </div>
-          </div>
-          <h1 class="doc-title" style="margin-top:30px;">附件十二:监护人身份证复印件</h1>
-          <div class="upload-block">
-            <p class="content-text">监护人身份证正反面复印件(上传图片):</p>
-            <el-upload v-show="!isPrint"
-              v-model:file-list="contractForm.guardianIdCardFiles"
-              action="#"
-              list-type="picture-card"
-              :auto-upload="false"
-              :limit="2"
-            >
-              <el-icon><Plus /></el-icon>
-            </el-upload>
-            <div v-if="isPrint && contractForm.guardianIdCardFiles && contractForm.guardianIdCardFiles.length > 0" class="print-images">
-              <img v-for="(f, i) in contractForm.guardianIdCardFiles" :key="i" :src="f.url" style="max-width:300px; margin:10px;" />
-            </div>
-          </div>
-        </div>
-      </div>
-
-      <!-- ========== 附件:体检报告上传 ========== -->
-      <div class="a4-page">
-        <div class="page-header">
-          <span class="page-no">33</span>
-        </div>
-        <div class="page-content">
-          <h1 class="doc-title">附件:体检报告及其他材料</h1>
-          <div class="upload-block">
-            <p class="content-text">体检报告(上传图片或PDF):</p>
-            <el-upload v-show="!isPrint"
-              v-model:file-list="contractForm.checkReportFiles"
-              action="#"
-              :auto-upload="false"
-              multiple
-            >
-              <el-button type="primary"><el-icon><Upload /></el-icon>&nbsp;点击上传</el-button>
-            </el-upload>
-          </div>
-          <div class="upload-block" style="margin-top:20px;">
-            <p class="content-text">其他证明材料(如病历、医保卡、户口本复印件等):</p>
-            <el-upload v-show="!isPrint"
-              v-model:file-list="contractForm.otherFiles"
-              action="#"
-              :auto-upload="false"
-              multiple
-            >
-              <el-button type="primary"><el-icon><Upload /></el-icon>&nbsp;点击上传</el-button>
-            </el-upload>
-          </div>
-          <p class="content-text" style="margin-top:40px; color:#666;"><em>本合同一式叁份,甲方执壹份,乙方执壹份,乙方监护人执壹份,自各方签字或盖章之日起生效。</em></p>
-        </div>
-      </div>
-
-    </div>
-  </el-drawer>
-</template>
-
-<script setup>
-import { ref, reactive, nextTick } from 'vue'
-import { ElMessage } from 'element-plus'
-import { Plus, Upload, Printer } from '@element-plus/icons-vue'
-import { getCheckInRecordId } from '@/api/elderly/apply/check-in'
-import ESign from './ESign.vue'
-
-const emit = defineEmits(['success'])
-
-const drawerVisible = ref(false)
-const loading = ref(false)
-const isPrint = ref(false)
-const currentRow = ref({})
-
-const defaultForm = {
-  // 机构信息
-  partyAName: '',
-  partyAAddr: '',
-  partyAPhone: '',
-  partyAEmail: '',
-  partyAFax: '',
-  // 长者信息
-  elderName: '',
-  elderGender: '',
-  elderBirth: '',
-  elderIdCard: '',
-  elderNation: '',
-  elderEducation: '',
-  elderMarital: '',
-  elderPhone: '',
-  elderInsurance: '',
-  elderAddress: '',
-  elderNative: '',
-  medicalHistory: '',
-  allergyHistory: '',
-  livingHabit: '',
-  hobby: '',
-  // 家属信息
-  partyCName: '',
-  partyCIdCard: '',
-  partyCRelation: '',
-  partyCPhone: '',
-  partyCAddress: '',
-  emergencyContact2Name: '',
-  emergencyContact2Relation: '',
-  emergencyContact2Phone: '',
-  // 合同信息
-  contractNumber: '',
-  startDate: '',
-  endDate: '',
-  nurseLevelName: '',
-  roomNumber: '',
-  // 费用
-  bedFee: '',
-  nurseFee: '',
-  mealFee: '',
-  manageFee: '',
-  waterFee: '',
-  deposit: '',
-  lifeSavingDeposit: '',
-  deathDeposit: '',
-  // 签名
-  partyASign: '',
-  partyALegalSign: '',
-  partyASignDate: '',
-  partyBSign: '',
-  partyBSignDate: '',
-  partyCSign: '',
-  partyCSignDate: '',
-  // 上传附件
-  elderIdCardFiles: [],
-  guardianIdCardFiles: [],
-  checkReportFiles: [],
-  otherFiles: []
-}
-
-const contractForm = reactive({ ...defaultForm })
-
-const open = async (row = {}) => {
-  currentRow.value = row
-  Object.assign(contractForm, { ...defaultForm })
-  drawerVisible.value = true
-  isPrint.value = false
-  // 自动填充接口数据
-  if (row && row.id) {
-    loading.value = true
-    try {
-      const res = await getCheckInRecordId(row.id, row.status)
-      if (res) {
-        nextTick(() => {
-          // 长者信息
-          contractForm.elderName = res.elderlyContractDO?.elderName || res.elderName || ''
-          contractForm.elderIdCard = res.elderlyContractDO?.idCard || res.idCard || ''
-          contractForm.elderGender = res.elderlyContractDO?.gender || res.gender || ''
-          contractForm.elderBirth = res.elderlyContractDO?.birthDate || res.birthDate || ''
-          contractForm.elderPhone = res.elderlyContractDO?.phone || res.phone || ''
-          contractForm.elderAddress = res.elderlyContractDO?.address || res.address || ''
-          contractForm.nurseLevelName = res.nurseLevelName || res.elderlyContractDO?.nurseLevelName || ''
-          contractForm.contractNumber = res.elderlyContractDO?.contractNumber || ''
-          contractForm.startDate = res.checkInTime || (res.elderlyContractDO?.beginTime ? res.elderlyContractDO.beginTime : '')
-          contractForm.endDate = res.checkInDeadlineTime || (res.elderlyContractDO?.expireTime ? res.elderlyContractDO.expireTime : '')
-          contractForm.roomNumber = res.roomNumber || res.elderlyContractDO?.roomNumber || ''
-          contractForm.medicalHistory = res.medicalHistory || ''
-          contractForm.allergyHistory = res.allergyHistory || ''
-          // 费用
-          const monthly = res.monthlyExpenses || []
-          const oneTime = res.oneTimeExpenses || []
-          const findAmount = (list, name) => {
-            const item = list.find(i => (i.itemCategoryName || '').includes(name))
-            return item ? item.actualAmount : ''
-          }
-          contractForm.bedFee = findAmount(monthly, '床位')
-          contractForm.nurseFee = findAmount(monthly, '护理')
-          contractForm.mealFee = findAmount(monthly, '膳食')
-          contractForm.manageFee = findAmount(monthly, '管理')
-          contractForm.waterFee = findAmount(monthly, '水电')
-          contractForm.deposit = findAmount(oneTime, '押金')
-          // 亲属
-          const relative = (res.relativesList && res.relativesList[0]) || {}
-          contractForm.partyCName = relative.name || ''
-          contractForm.partyCIdCard = relative.idCard || ''
-          contractForm.partyCRelation = relative.relation || ''
-          contractForm.partyCPhone = relative.phone || ''
-          contractForm.partyCAddress = relative.address || ''
-          const relative2 = (res.relativesList && res.relativesList[1]) || {}
-          contractForm.emergencyContact2Name = relative2.name || ''
-          contractForm.emergencyContact2Relation = relative2.relation || ''
-          contractForm.emergencyContact2Phone = relative2.phone || ''
-        })
-      }
-    } catch (e) {
-      console.error(e)
-    } finally {
-      loading.value = false
-    }
-  }
-}
-
-const handlePrint = () => {
-  isPrint.value = true
-  nextTick(() => {
-    window.print()
-    setTimeout(() => {
-      isPrint.value = false
-    }, 500)
-  })
-}
-
-const handleSubmit = () => {
-  ElMessage.success('合同信息保存成功')
-  emit('success', contractForm)
-  drawerVisible.value = false
-}
-
-defineExpose({ open })
-</script>
-
-<style>
-/* ========== 工具栏 ========== */
-.contract-toolbar {
-  position: sticky;
-  top: 0;
-  z-index: 100;
-  background: #fff;
-  padding: 15px 20px;
-  border-bottom: 1px solid #e4e7ed;
-  display: flex;
-  gap: 10px;
-  align-items: center;
-}
-.toolbar-title {
-  margin-left: auto;
-  color: #606266;
-  font-size: 14px;
-}
-
-/* ========== A4 页面容器 ========== */
-.a4-page {
-  width: 210mm;
-  min-height: 297mm;
-  padding: 20mm 18mm 18mm 18mm;
-  margin: 20px auto;
-  background: #fff;
-  box-shadow: 0 2px 12px rgba(0,0,0,0.1);
-  box-sizing: border-box;
-  position: relative;
-  font-family: "Microsoft YaHei", "SimSun", serif;
-  color: #000;
-  line-height: 1.8;
-  page-break-after: always;
-}
-.a4-page:last-child {
-  page-break-after: auto;
-}
-.page-header {
-  position: absolute;
-  top: 8mm;
-  right: 15mm;
-  font-size: 11pt;
-  color: #666;
-}
-.page-content {
-  min-height: 260mm;
-}
-
-/* ========== 文档标题 ========== */
-.doc-title {
-  font-size: 18pt;
-  font-weight: bold;
-  text-align: center;
-  margin-bottom: 30px;
-  letter-spacing: 2px;
-}
-.contract-number {
-  text-align: right;
-  font-size: 11pt;
-  color: #333;
-  margin-bottom: 20px;
-}
-
-/* ========== 段落标题 ========== */
-.section-title {
-  font-size: 14pt;
-  font-weight: bold;
-  margin-top: 20px;
-  margin-bottom: 10px;
-}
-.section-title.center {
-  text-align: center;
-}
-.subsection-title {
-  font-size: 12pt;
-  font-weight: bold;
-  margin-top: 15px;
-  margin-bottom: 8px;
-}
-
-/* ========== 正文 ========== */
-.content-text {
-  font-size: 11pt;
-  text-indent: 2em;
-  margin-bottom: 8px;
-  line-height: 1.9;
-  text-align: justify;
-}
-.content-text.no-indent {
-  text-indent: 0;
-}
-
-/* ========== 信息表格 ========== */
-.info-table {
-  width: 100%;
-  border-collapse: collapse;
-  margin: 15px 0;
-  font-size: 11pt;
-}
-.info-table th,
-.info-table td {
-  border: 1px solid #000;
-  padding: 6px 10px;
-  text-align: left;
-  vertical-align: middle;
-}
-.info-table th {
-  background: #f5f5f5;
-  font-weight: bold;
-  width: 100px;
-  text-align: center;
-}
-.info-table td .el-input,
-.info-table td .el-date-editor {
-  width: 100%;
-}
-
-/* ========== 行内编辑块 ========== */
-.inline-edit-block {
-  display: inline-block;
-  min-width: 80px;
-  border-bottom: 1px solid #999;
-  padding: 0 5px;
-}
-
-/* ========== 签名区域 ========== */
-.sign-page {
-  padding-top: 50mm;
-}
-.sign-block {
-  margin-top: 40px;
-  padding-left: 30mm;
-}
-.sign-line {
-  margin-bottom: 25px;
-  font-size: 11pt;
-  text-indent: 0;
-}
-.sign-area {
-  margin: 15px 0;
-}
-
-/* ========== 上传区域 ========== */
-.upload-block {
-  margin: 15px 0;
-  padding: 15px;
-  border: 1px dashed #ccc;
-  min-height: 150px;
-}
-
-/* ========== 打印样式 ========== */
-@media print {
-  @page {
-    size: A4;
-    margin: 0;
-  }
-  body {
-    background: #fff;
-    margin: 0;
-    padding: 0;
-  }
-  .contract-toolbar {
-    display: none !important;
-  }
-  .el-drawer__header,
-  .el-drawer__body > :not(.a4-container),
-  .el-dialog__header,
-  .el-dialog__footer {
-    display: none !important;
-  }
-  .el-drawer {
-    position: static !important;
-    width: 100% !important;
-    height: auto !important;
-  }
-  .el-drawer__body {
-    overflow: visible !important;
-  }
-  .a4-container {
-    padding: 0 !important;
-  }
-  .a4-page {
-    display: block !important;
-    margin: 0 !important;
-    box-shadow: none !important;
-    page-break-after: always;
-    page-break-inside: avoid;
-    width: 210mm;
-    min-height: 297mm;
-  }
-  .a4-page:last-child {
-    page-break-after: auto;
-  }
-  .el-input__wrapper,
-  .el-textarea__inner,
-  .el-select__wrapper,
-  .el-date-editor {
-    background: transparent !important;
-    box-shadow: none !important;
-    border: none !important;
-  }
-  .el-input__inner {
-    color: #000 !important;
-  }
-  /* 隐藏上传按钮占位 */
-  .el-upload,
-  .el-upload-list {
-    display: none !important;
-  }
-}
-</style>

BIN
src/views/elderly/apply/check-in/颐年集团养老服务合同-2026年6月终版docx.pdf


BIN
src/views/elderly/apply/check-in/颐年集团广州养老服务合同-校对启用版202606.pdf


+ 11 - 11
src/views/elderly/apply/nine-precautions/MMSE/AddForm.vue

@@ -51,17 +51,7 @@
 
         <!-- 表单内容区域 -->
         <div class="form-body">
-          <!-- 总分显示 -->
-          <div class="total-score-section">
-            <div class="total-score">
-              <span class="score-label">总分:</span>
-              <span class="score-value">{{ totalScore }}</span>
-              <span class="score-max">/ 30分</span>
-            </div>
-
-          </div>
-
-          <!-- 一、定向力 (10分) -->
+            <!-- 一、定向力 (10分) -->
           <div class="section">
             <div class="section-title">一、定向力(10分)</div>
 
@@ -300,6 +290,16 @@
             </div>
           </div>
 
+          <!-- 总分显示 -->
+          <div class="total-score-section">
+            <div class="total-score">
+              <span class="score-label">总分:</span>
+              <span class="score-value">{{ totalScore }}</span>
+              <span class="score-max">/ 30分</span>
+            </div>
+
+          </div>
+
           <!-- 风险程度判断 -->
           <div class="section risk-section">
             <div class="section-title">风险程度判断</div>

+ 2 - 2
src/views/elderly/apply/nine-precautions/anti-entertainment/AddForm.vue

@@ -50,9 +50,9 @@
                 <td class="col-factor" rowspan="4">身体健康状况基础疾病</td>
                 <td class="col-standard">
                   <el-radio-group v-model="form.assessment.scores[0]" :disabled="isDetail" @change="calculateTotal">
-                    <el-radio :label="2">两项疾病以上(>2项)=2分+不适合=5分</el-radio>
+                    <el-radio :label="7">两项疾病以上(>2项)=2分+不适合=5分</el-radio>
                     <el-radio :label="1">两项疾病以下(≤2项)=1分+适合=0分</el-radio>
-                    <el-radio :label="2">两项疾病以上(>2项)2分+身体适合0分=2分</el-radio>
+                    <el-radio :label="4">两项疾病以上(>2项)2分+身体适合0分=2分</el-radio>
                     <el-radio :label="6">两项疾病以下(≤2项)1分+身体不适合5分=6分</el-radio>
                   </el-radio-group>
                 </td>

+ 342 - 0
src/views/elderly/contracts/ContractManageForm.vue

@@ -0,0 +1,342 @@
+<script setup lang="ts">
+import { reactive, ref } from 'vue'
+import ContractBody from './components/ContractBody.vue'
+import AttachmentPage from './components/AttachmentPage.vue'
+import AttachmentSelector from './components/AttachmentSelector.vue'
+
+const message = useMessage()
+
+const visible = ref(false)
+const formLoading = ref(false)
+
+const isTextMode = ref(false)
+const isPrint = ref(false)
+const contractBodyRef = ref<any>(null)
+const recordRow = ref<any>(null)
+
+const attachmentList = [
+  { no: 1, title: '知情同意书' },
+  { no: 2, title: '入住登记表' },
+  { no: 3, title: '入住须知' },
+  { no: 4, title: '长者安全承诺书' },
+  { no: 5, title: '长者外出情况确认书' },
+  { no: 6, title: '签名代理申请' },
+  { no: 7, title: '授权委托书' },
+  { no: 8, title: '委托代理人确认表' },
+  { no: 9, title: '机构服务范围及收费标准' },
+  { no: 10, title: '房间设施设备清单' },
+  { no: 11, title: '体检报告项目说明' },
+  { no: 12, title: '乙方有效证件身份证、户口本复印件' },
+  { no: 13, title: '乙方监护人(丙方)身份证、户口本复印件' },
+  { no: 14, title: '甲方登记证书及民政部门备案回执' },
+  { no: 15, title: '老年人能力综合评估结果' },
+  { no: 16, title: '首次服务项目确认表' },
+  { no: 17, title: '变更事项确认表' }
+]
+
+const attachments = reactive<Record<string, any>>(
+  attachmentList.reduce((acc: any, item) => {
+    acc[`attach_${item.no}`] = null
+    return acc
+  }, {} as Record<string, any>)
+)
+
+const selectorVisible = ref<{
+  show: boolean
+  current: string
+  title: string
+  list: any[]
+}>({
+  show: false,
+  current: '',
+  title: '',
+  list: []
+})
+
+const open = (row?: any) => {
+  recordRow.value = row || null
+  formLoading.value = true
+  isTextMode.value = false
+  isPrint.value = false
+  attachmentList.forEach((it) => {
+    attachments[`attach_${it.no}`] = null
+  })
+  visible.value = true
+  setTimeout(() => {
+    formLoading.value = false
+  }, 100)
+}
+
+const close = () => {
+  visible.value = false
+}
+
+defineExpose({ open, close })
+
+const emit = defineEmits(['refreshTree'])
+
+const handleSave = async () => {
+  formLoading.value = true
+  try {
+    message.success('保存成功')
+    visible.value = false
+    emit('refreshTree')
+  } finally {
+    setTimeout(() => {
+      formLoading.value = false
+    }, 500)
+  }
+}
+
+const handleClose = () => {
+  visible.value = false
+}
+
+const handlePrint = async () => {
+  isPrint.value = true
+  isTextMode.value = true
+  await new Promise((resolve) => setTimeout(resolve, 200))
+  window.print()
+  setTimeout(() => {
+    isPrint.value = false
+    isTextMode.value = false
+  }, 500)
+}
+
+const handleExport = () => {
+  message.success('导出功能已触发(待接入实际接口)')
+}
+
+const toggleTextMode = () => {
+  isTextMode.value = !isTextMode.value
+}
+
+const openAttachmentSelector = (attach: any) => {
+  selectorVisible.value = {
+    show: true,
+    current: `attach_${attach.no}`,
+    title: attach.title,
+    list: []
+  }
+}
+
+const handleAttachmentSelect = (row: any) => {
+  const key = selectorVisible.value.current
+  if (key) {
+    attachments[key] = row
+    message.success(`已选择:${row.title}`)
+  }
+  selectorVisible.value.show = false
+}
+
+const handleAttachmentSelectorClose = () => {
+  selectorVisible.value.show = false
+}
+
+const renderAttachmentContent = (key: string) => {
+  const data = attachments[key]
+  if (!data) return null
+  return data.title || '已选择数据'
+}
+</script>
+
+<template>
+  <el-drawer
+    v-model="visible"
+    title="合同管理"
+    size="70vw"
+    direction="rtl"
+    class="contract-manage-drawer"
+  >
+    <div class="drawer-content">
+      <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 :type="isTextMode ? 'success' : 'default'" size="small" @click="toggleTextMode">
+              {{ isTextMode ? '文本模式' : '编辑模式' }}
+            </el-button>
+          </el-tooltip>
+          <el-button type="primary" :loading="formLoading" size="small" @click="handleSave">保存</el-button>
+          <el-button size="small" @click="handleClose">关闭</el-button>
+          <el-button type="success" size="small" @click="handlePrint">打印</el-button>
+          <el-button type="warning" size="small" @click="handleExport">导出</el-button>
+        </div>
+      </div>
+
+      <div class="content-body">
+        <!-- ============ 合同主体 ============ -->
+        <div class="section-divider">
+          <span>合同主体</span>
+        </div>
+        <ContractBody ref="contractBodyRef" :record-row="recordRow" :is-text-mode="isTextMode" />
+
+        <!-- ============ 16个附件 ============ -->
+        <div class="section-divider" style="margin-top: 30px;">
+          <span>附件清单</span>
+        </div>
+
+        <AttachmentPage
+          v-for="attach in attachmentList"
+          :key="attach.no"
+          :attachment-no="attach.no"
+          :title="attach.title"
+          :selected-data="attachments[`attach_${attach.no}`]"
+          :is-text-mode="isTextMode"
+          @select="openAttachmentSelector(attach)"
+        >
+          <template #default="{ data }">
+            <div class="attachment-body">
+              <p><strong>已选择:</strong>{{ renderAttachmentContent(`attach_${attach.no}`) }}</p>
+              <p><strong>版本:</strong>{{ data?.version || '-' }}</p>
+              <p><strong>日期:</strong>{{ data?.createTime || '-' }}</p>
+              <p style="color: #999; font-size: 13px;">
+                (此处为附件内容占位,实际各附件将由对应列表页提供完整内容排版)
+              </p>
+            </div>
+          </template>
+        </AttachmentPage>
+      </div>
+
+      <div class="content-footer" v-if="!isPrint">
+        <el-button type="primary" :loading="formLoading" @click="handleSave">保存</el-button>
+        <el-button @click="handleClose">关闭</el-button>
+        <el-button type="success" @click="handlePrint">打印</el-button>
+        <el-button type="warning" @click="handleExport">导出</el-button>
+      </div>
+    </div>
+  </el-drawer>
+
+  <AttachmentSelector
+    v-model:visible="selectorVisible.show"
+    :title="selectorVisible.title"
+    :list="selectorVisible.list"
+    @select="handleAttachmentSelect"
+    @update:visible="handleAttachmentSelectorClose"
+  />
+</template>
+
+<style lang="scss">
+.contract-manage-drawer {
+  .el-drawer__header {
+    margin-bottom: 0 !important;
+    padding: 14px 20px;
+  }
+
+  .el-drawer__body {
+    padding: 0 !important;
+    display: flex;
+    flex-direction: column;
+    height: 100%;
+    overflow: hidden;
+  }
+}
+
+@media print {
+  body * {
+    visibility: hidden;
+  }
+
+  .contract-manage-drawer,
+  .contract-manage-drawer .el-drawer__body {
+    visibility: visible;
+    position: static !important;
+    overflow: visible !important;
+  }
+
+  .contract-manage-drawer .content-toolbar,
+  .contract-manage-drawer .content-footer,
+  .contract-manage-drawer .el-drawer__header,
+  .contract-manage-drawer .content-body .section-divider {
+    display: none !important;
+  }
+
+  .contract-manage-drawer .content-body {
+    visibility: visible;
+    overflow: visible !important;
+  }
+
+  .contract-manage-drawer .content-body > * {
+    visibility: visible;
+  }
+
+  .contract-manage-drawer .drawer-content {
+    display: block;
+  }
+
+  @page {
+    size: A4;
+    margin: 0;
+  }
+}
+</style>
+
+<style scoped lang="scss">
+.drawer-content {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+  min-height: 0;
+}
+
+.content-toolbar {
+  flex-shrink: 0;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 10px 16px;
+  background: #f8f9fb;
+  border-bottom: 1px solid #e4e7ed;
+}
+
+.toolbar-right {
+  display: flex;
+  gap: 8px;
+}
+
+.section-divider {
+  width: 210mm;
+  margin: 0 auto 8px;
+  text-align: center;
+  padding: 8px 0;
+  font-size: 15px;
+  font-weight: bold;
+  color: #666;
+  border-top: 1px dashed #ccc;
+  position: relative;
+}
+
+.section-divider span {
+  display: inline-block;
+  padding: 4px 14px;
+  background: #fff;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+}
+
+.content-body {
+  flex: 1;
+  overflow-y: auto;
+  padding: 16px 0;
+  background: #f5f5f5;
+}
+
+.content-footer {
+  flex-shrink: 0;
+  display: flex;
+  justify-content: flex-end;
+  gap: 12px;
+  padding: 12px 20px;
+  border-top: 1px solid #ebeef5;
+  background: #fafafa;
+}
+
+.attachment-body {
+  padding: 10px 0;
+}
+
+.attachment-body p {
+  margin: 4px 0;
+  line-height: 1.8;
+}
+</style>

+ 114 - 0
src/views/elderly/contracts/components/AttachmentPage.vue

@@ -0,0 +1,114 @@
+<script setup lang="ts">
+import { computed } from 'vue'
+
+const props = defineProps<{
+  title: string
+  attachmentNo: string | number
+  selectedData?: any
+  isTextMode?: boolean
+}>()
+
+const emit = defineEmits<{
+  (e: 'select'): void
+}>()
+
+const hasData = computed(() => {
+  if (!props.selectedData) return false
+  if (Array.isArray(props.selectedData)) return props.selectedData.length > 0
+  if (typeof props.selectedData === 'object') return Object.keys(props.selectedData).length > 0
+  return !!props.selectedData
+})
+</script>
+
+<template>
+  <div class="attachment-page">
+    <div class="attachment-header">
+      <div class="attachment-title">
+        附件{{ attachmentNo }}:{{ title }}
+      </div>
+      <el-button
+        v-if="!isTextMode"
+        type="primary"
+        size="small"
+        plain
+        @click="emit('select')"
+      >
+        从列表中选择
+      </el-button>
+    </div>
+
+    <div v-if="hasData" class="attachment-content">
+      <div class="attachment-body">
+        <slot :data="selectedData"></slot>
+      </div>
+    </div>
+
+    <div v-else class="attachment-empty">
+      <el-empty :description="isTextMode ? '' : '请点击上方按钮从列表中选择附件数据'" />
+    </div>
+  </div>
+</template>
+
+<style scoped lang="scss">
+.attachment-page {
+  width: 210mm;
+  min-height: 297mm;
+  margin: 4mm auto;
+  padding: 10mm 14mm;
+  background: #fff;
+  box-shadow: 0 0 8px rgba(0, 0, 0, 0.12);
+  box-sizing: border-box;
+}
+
+.attachment-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding-bottom: 8px;
+  border-bottom: 1.5px solid #333;
+  margin-bottom: 16px;
+}
+
+.attachment-title {
+  font-size: 18px;
+  font-weight: bold;
+  color: #222;
+}
+
+.attachment-content {
+  font-size: 14px;
+  line-height: 1.9;
+  color: #333;
+}
+
+.attachment-body {
+  padding: 4px 0;
+}
+
+.attachment-empty {
+  margin-top: 40px;
+}
+
+@media print {
+  .attachment-page {
+    width: 100% !important;
+    min-height: auto !important;
+    height: auto !important;
+    margin: 0 !important;
+    padding: 10mm 14mm !important;
+    box-shadow: none !important;
+    page-break-after: always;
+    break-after: page;
+  }
+
+  .attachment-page:last-child {
+    page-break-after: auto;
+    break-after: auto;
+  }
+
+  @page {
+    size: A4;
+    margin: 0;
+  }
+}
+</style>

+ 86 - 0
src/views/elderly/contracts/components/AttachmentSelector.vue

@@ -0,0 +1,86 @@
+<script setup lang="ts">
+import { ref, watch } from 'vue'
+
+const props = defineProps<{
+  visible?: boolean
+  title?: string
+  list?: any[]
+}>()
+
+const emit = defineEmits<{
+  (e: 'update:visible', val: boolean): void
+  (e: 'select', row: any): void
+}>()
+
+const localVisible = ref(false)
+const selectedRow = ref<any>(null)
+
+watch(
+  () => props.visible,
+  (val) => {
+    localVisible.value = val || false
+    if (val) selectedRow.value = null
+  },
+  { immediate: true }
+)
+
+const close = () => {
+  localVisible.value = false
+  emit('update:visible', false)
+}
+
+const handleSelect = (row: any) => {
+  selectedRow.value = row
+}
+
+const handleConfirm = () => {
+  if (!selectedRow.value) return
+  emit('select', selectedRow.value)
+  close()
+}
+
+const mockList = ref<any[]>([
+  { 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' }
+])
+</script>
+
+<template>
+  <el-drawer
+    v-model="localVisible"
+    :title="`选择${title}数据`"
+    size="60%"
+    direction="rtl"
+    destroy-on-close
+    @close="close"
+  >
+    <el-alert
+      title="请根据日期从以下列表中选择一份数据用于此附件"
+      type="info"
+      :closable="false"
+      show-icon
+      style="margin-bottom: 12px;"
+    />
+
+    <el-table
+      :data="list && list.length > 0 ? list : mockList"
+      border
+      highlight-current-row
+      @current-change="handleSelect"
+      style="width: 100%"
+    >
+      <el-table-column type="index" label="序号" width="60" align="center" />
+      <el-table-column prop="title" label="名称/说明" min-width="260" />
+      <el-table-column prop="version" label="版本" width="100" align="center" />
+      <el-table-column prop="createTime" label="日期/创建时间" width="160" align="center" />
+    </el-table>
+
+    <template #footer>
+      <div style="text-align: right;">
+        <el-button @click="close">取消</el-button>
+        <el-button type="primary" :disabled="!selectedRow" @click="handleConfirm">确认选择</el-button>
+      </div>
+    </template>
+  </el-drawer>
+</template>

+ 1721 - 0
src/views/elderly/contracts/components/ContractBody.vue

@@ -0,0 +1,1721 @@
+<script setup lang="ts">
+import { reactive, computed, ref, watch } from 'vue'
+import { formatBackendDateTime } from '@/utils/formatTime'
+import { DICT_TYPE, getDictLabel } from '@/utils/dict'
+import { getCheckInRecordId } from '@/api/elderly/apply/check-in'
+import FieldItem from './FieldItem.vue'
+import SignatureItem from './SignatureItem.vue'
+
+const props = defineProps<{
+  recordRow?: any
+  isTextMode?: boolean
+}>()
+
+const emit = defineEmits<{
+  (e: 'update:data', val: any): void
+}>()
+
+const loading = ref(false)
+const detailData = ref<any>(null)
+
+const elderId = computed(() => {
+  if (!props.recordRow) return ''
+  return props.recordRow.elderId || props.recordRow.id || ''
+})
+
+const contractForm = reactive({
+  contractNumber: '',
+  elderName: '',
+  elderGenderText: '',
+  elderBirth: '',
+  elderPapersType: '',
+  elderIdCard: '',
+  elderAge: '',
+  elderAddress: '',
+  elderZip: '',
+  partyAName: '颐年健康产业(集团)有限公司',
+  partyACode: '',
+  partyAAddr: '',
+  partyAZip: '',
+  partyALegal: '',
+  partyAPhone: '',
+  partyCName: '',
+  partyCGenderText: '',
+  partyCBirth: '',
+  partyCPapersType: '',
+  partyCRelation: '',
+  partyCIdCard: '',
+  partyCPhone: '',
+  partyCAddress: '',
+  partyCHomeAddr: '',
+  partyCZip: '',
+  partyCWorkUnit: '',
+  partyCCommAddr: '',
+  nurseLevelName: '',
+  contractMonths: '',
+  startDate: '',
+  endDate: '',
+  servicePlace: '颐年集团养老服务机构',
+  bedFee: '',
+  nurseFee: '',
+  mealFee: '',
+  manageFee: '',
+  totalFee: '',
+  // 费用相关扩展字段
+  roomType: '',
+  roomNo: '',
+  freeElectric: '',
+  freeWater: '',
+  hotWaterFee: '',
+  coldWaterFee: '',
+  electricFee: '',
+  diagnosisFee: '',
+  oneTimeEquipFee: '',
+  oneTimeEquipStart: '',
+  oneTimeEquipEnd: '',
+  depositFee: '',
+  depositType: '',
+  depositInterest: '',
+  payMode: '1',
+  payMonthDay: '5',
+  paySeasonMonth: '1',
+  paySeasonDay: '5',
+  partyAAccountName: '',
+  partyABank: '',
+  partyAAccount: '',
+  partyCAccountName: '',
+  partyCBank: '',
+  partyCAccount: '',
+  depositRefund: '',
+  otherPayMode: '',
+  otherPayMode2: '',
+  // 合同续签/变更/解除
+  renewNoticeDays: '30',
+  moveOutDays: '3',
+  changeConfirmDays: '7',
+  priceAdjustNoticeDays: '30',
+  priceThreshold: '6',
+  priceObjDays: '15',
+  priceConfirmDays: '15',
+  leaveDays: '60',
+  depositAmt: '',
+  depositAmtCn: '',
+  depositAmt1: '',
+  depositAmtCn1: '',
+  depositAmt2: '',
+  depositAmtCn2: '',
+  disputeMode: '2',
+  copyCount: '叁',
+  partyACopy: '壹',
+  partyBCopy: '壹',
+  partyCCopy: '壹',
+  partyASign: '',
+  partyALegalSign: '',
+  partyADate: '',
+  partyBSign: '',
+  partyBDate: '',
+  partyCSign: '',
+  partyCDate: ''
+})
+
+const parseIdCardBirth = (idCard: string): string => {
+  if (!idCard || idCard.length < 14) return ''
+  const year = idCard.substring(6, 10)
+  const month = idCard.substring(10, 12)
+  const day = idCard.substring(12, 14)
+  return `${year}年${month}月${day}日`
+}
+
+const numToChinese = (num: number | string): string => {
+  const n = Number(num)
+  if (isNaN(n) || n < 0) return ''
+  if (n === 0) return '零元整'
+  const fractions = ['角', '分']
+  const digit = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
+  const radices = ['', '拾', '佰', '仟']
+  const bigRadices = ['', '万', '亿']
+  const dStr = n.toFixed(2)
+  const parts = dStr.split('.')
+  let intPart = parts[0]
+  let decPart = parts[1]
+  let chinese = ''
+  let zeroFlag = false
+  for (let i = 0; i < intPart.length; i++) {
+    const ch = intPart.charAt(i)
+    const numDigit = parseInt(ch)
+    const pos = intPart.length - i - 1
+    const radixIdx = pos % 4
+    const bigRadixIdx = Math.floor(pos / 4)
+    if (numDigit === 0) {
+      zeroFlag = true
+    } else {
+      if (zeroFlag) {
+        chinese += '零'
+        zeroFlag = false
+      }
+      chinese += digit[numDigit] + radices[radixIdx]
+    }
+    if (radixIdx === 0 && numDigit !== 0) {
+      chinese += bigRadices[bigRadixIdx]
+    } else if (radixIdx === 0 && intPart.length > 4) {
+      const segStart = Math.max(0, intPart.length - (bigRadixIdx + 1) * 4)
+      const seg = intPart.substring(segStart, intPart.length - bigRadixIdx * 4)
+      if (parseInt(seg) > 0) {
+        chinese += bigRadices[bigRadixIdx]
+      }
+    }
+  }
+  chinese = chinese.replace(/零+/g, '零').replace(/零$/, '')
+  chinese += '元'
+  if (decPart === '00') {
+    chinese += '整'
+  } else {
+    const jiao = parseInt(decPart.charAt(0))
+    const fen = parseInt(decPart.charAt(1))
+    if (jiao > 0) chinese += digit[jiao] + fractions[0]
+    if (fen > 0) chinese += digit[fen] + fractions[1]
+    if (jiao === 0 && fen > 0) {
+      // 零元几分的情况
+    }
+  }
+  return chinese
+}
+
+const fillContractForm = (data: any) => {
+  if (!data) return
+  detailData.value = data
+  const contract = data.elderlyContractDO || {}
+
+  contractForm.contractNumber = contract.contractNumber || ''
+  contractForm.elderName = contract.elderName || data.elderName || ''
+
+  if (data.elderSex) {
+    contractForm.elderGenderText = Number(data.elderSex) === 1 ? '男' : '女'
+  }
+
+  if (data.idCard) {
+    contractForm.elderIdCard = data.idCard
+    contractForm.elderBirth = parseIdCardBirth(data.idCard)
+  }
+  if (data.papersType != null && data.papersType !== '' && data.papersType !== undefined) {
+    contractForm.elderPapersType = data.papersType
+  }
+
+  contractForm.elderAge = data.elderAge || ''
+  contractForm.elderAddress = data.elderAddress || ''
+  contractForm.elderZip = data.elderZip || ''
+
+  contractForm.nurseLevelName = data.nurseLevelName || ''
+
+  if (contract.contractTerm) {
+    contractForm.contractMonths = String(contract.contractTerm)
+  }
+
+  if (data.checkInTime) {
+    contractForm.startDate = formatBackendDateTime(data.checkInTime, 'YYYY年MM月DD日')
+  }
+  if (data.checkInDeadlineTime) {
+    contractForm.endDate = formatBackendDateTime(data.checkInDeadlineTime, 'YYYY年MM月DD日')
+  }
+
+  if (contract.beginTime) {
+    contractForm.startDate = formatBackendDateTime(contract.beginTime, 'YYYY年MM月DD日')
+  }
+  if (contract.expireTime) {
+    contractForm.endDate = formatBackendDateTime(contract.expireTime, 'YYYY年MM月DD日')
+  }
+
+  const monthly = data.monthlyExpenses || []
+  const findItem = (list: any[], key: string): any => {
+    return list.find(
+      (x: any) => (x.itemName || '').includes(key) || (x.itemCategoryName || '').includes(key)
+    )
+  }
+  const findAmt = (list: any[], key: string): string => {
+    const item = findItem(list, key)
+    return item ? String(item.actualAmount || item.amount || '') : ''
+  }
+  contractForm.bedFee = findAmt(monthly, '床位') || ''
+  contractForm.nurseFee = findAmt(monthly, '护理') || ''
+  contractForm.mealFee = findAmt(monthly, '膳食') || ''
+  contractForm.manageFee = findAmt(monthly, '服务') || ''
+
+  const total = monthly.reduce(
+    (sum: number, it: any) => sum + (Number(it.actualAmount) || Number(it.amount) || 0),
+    0
+  )
+  contractForm.totalFee = total > 0 ? String(total) : ''
+
+  const bedItem = findItem(monthly, '床位')
+  if (bedItem && bedItem.itemName) {
+    const m = bedItem.itemName.match(/^(.+?)\(/)
+    contractForm.roomType = m ? m[1] : bedItem.itemName
+  }
+
+  if (data.bedId) {
+    contractForm.roomNo = String(data.bedId)
+  }
+
+  const oneTime = data.oneTimeExpenses || []
+  const deposit = findItem(oneTime, '押金')
+  if (deposit) {
+    const depositAmt = Number(deposit.actualAmount || deposit.amount || 0)
+    contractForm.depositFee = String(depositAmt)
+    contractForm.depositAmt = String(depositAmt)
+    contractForm.depositAmtCn = numToChinese(depositAmt)
+    contractForm.depositAmt1 = String(depositAmt)
+    contractForm.depositAmtCn1 = numToChinese(depositAmt)
+    contractForm.depositAmt2 = String(depositAmt)
+    contractForm.depositAmtCn2 = numToChinese(depositAmt)
+    contractForm.depositType = deposit.itemName || ''
+  }
+
+  const relative = (data.relativesList && data.relativesList[0]) || {}
+  contractForm.partyCName = relative.name || ''
+  if (relative.gender) {
+    contractForm.partyCGenderText = Number(relative.gender) === 1 ? '男' : '女'
+  }
+  if (relative.idCard) {
+    contractForm.partyCIdCard = relative.idCard
+    contractForm.partyCBirth = parseIdCardBirth(relative.idCard)
+  }
+  if (relative.papersType != null && relative.papersType !== '' && relative.papersType !== undefined) {
+    contractForm.partyCPapersType = relative.papersType
+  }
+  contractForm.partyCRelation = relative.relation || ''
+  contractForm.partyCPhone = relative.phone || ''
+  contractForm.partyCAddress = relative.address || relative.nowAddress || ''
+  contractForm.partyCHomeAddr = relative.nowAddress || ''
+  contractForm.partyCWorkUnit = relative.workUnit || ''
+
+  emit('update:data', { ...contractForm })
+}
+
+const fetchContractData = async (row: any) => {
+  if (!row) return
+  // 如果已经有完整数据(如直接返回了elderlyContractDO),直接填充
+  if (row.elderlyContractDO) {
+    fillContractForm(row)
+    return
+  }
+  // 否则调用接口获取
+  const recordId = row.checkInRecordId || row.id || row.elderId
+  if (!recordId) {
+    fillContractForm(row)
+    return
+  }
+  loading.value = true
+  try {
+    const status = row.status ?? ''
+    const res = await getCheckInRecordId(recordId, status)
+    if (res && res.data) {
+      fillContractForm(res.data)
+    }
+  } catch (e) {
+    console.error('获取合同详情失败', e)
+  } finally {
+    loading.value = false
+  }
+}
+
+watch(
+  () => props.recordRow,
+  (row) => {
+    if (row) {
+      fetchContractData(row)
+    }
+  },
+  { immediate: true }
+)
+
+watch(
+  () => contractForm.depositAmt1,
+  (val) => {
+    const n = Number(val)
+    if (!isNaN(n) && n >= 0) {
+      contractForm.depositAmtCn1 = numToChinese(n)
+    }
+  }
+)
+
+watch(
+  () => contractForm.depositAmt2,
+  (val) => {
+    const n = Number(val)
+    if (!isNaN(n) && n >= 0) {
+      contractForm.depositAmtCn2 = numToChinese(n)
+    }
+  }
+)
+
+const displayDate = computed(() => {
+  const today = new Date()
+  return `${today.getFullYear()}年${today.getMonth() + 1}月${today.getDate()}日`
+})
+</script>
+
+<template>
+  <div class="contract-body">
+    <!-- ========== 第1页:封面 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">-1-</span>
+      </div>
+      <div class="page-content cover-page">
+        <div class="cover-fields">
+          <p>
+            <span class="label">合同编号:</span>
+            <FieldItem
+              v-model="contractForm.contractNumber"
+              :is-text-mode="isTextMode"
+              width="180px"
+              placeholder="请输入合同编号"
+            />
+          </p>
+          <p>
+            <span class="label">长者姓名:</span>
+            <FieldItem
+              v-model="contractForm.elderName"
+              :is-text-mode="isTextMode"
+              width="180px"
+              placeholder="请输入长者姓名"
+            />
+          </p>
+        </div>
+        <h1 class="doc-title">养老机构服务合同</h1>
+        <p class="cover-issuer">
+          广州市民政局<br />
+          广州市市场监督管理局&nbsp;&nbsp;制定
+        </p>
+      </div>
+    </div>
+
+    <!-- ========== 第2页:重要提示 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">2</span>
+      </div>
+      <div class="page-content">
+        <h2 class="section-title">重要提示</h2>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;为了维护您的利益,请您在签署本合同(本协议)前,仔细阅读如下注意事项:
+        </p>
+        <p class="content-text">
+          一、您已阅读本合同(协议)、补充协议及相关文件的所有条款,并已知悉其含义,同时对涉及贵方权利与义务的内容给予了充分的注意。
+        </p>
+        <p class="content-text">二、您已确保提交的有关证件及资料是真实、合法、有效的。</p>
+        <p class="content-text">
+          三、您已确保向合同(协议)签署相关方所作的陈述、健康状况披露及其他信息披露均完整、充分、真实。
+        </p>
+        <p class="content-text">四、本合同(协议)所有条款均为签署方的真实意思表示。</p>
+      </div>
+    </div>
+
+    <!-- ========== 第3页:甲乙丙方信息 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">3</span>
+      </div>
+      <div class="page-content">
+        <h3 class="subsection-title">甲方(养老机构):</h3>
+        <p class="content-text">
+          甲方运营机构:
+          <FieldItem v-model="contractForm.partyAName" :is-text-mode="isTextMode" width="200px" placeholder="请输入" />
+        </p>
+        <p class="content-text">
+          统一社会信用代码:
+          <FieldItem v-model="contractForm.partyACode" :is-text-mode="isTextMode" width="200px" placeholder="请输入" />
+        </p>
+        <p class="content-text">
+          地址:
+          <FieldItem v-model="contractForm.partyAAddr" :is-text-mode="isTextMode" width="220px" placeholder="请输入" />
+          邮编:
+          <FieldItem v-model="contractForm.partyAZip" :is-text-mode="isTextMode" width="100px" placeholder="请输入" />
+        </p>
+        <p class="content-text">
+          法定代表人:
+          <FieldItem v-model="contractForm.partyALegal" :is-text-mode="isTextMode" width="160px" placeholder="请输入" />
+          联系方式:
+          <FieldItem v-model="contractForm.partyAPhone" :is-text-mode="isTextMode" width="160px" placeholder="请输入" />
+        </p>
+
+        <h3 class="subsection-title" style="margin-top: 16px;">乙方(入住老年人)</h3>
+        <p class="content-text">
+          姓名:
+          <FieldItem v-model="contractForm.elderName" :is-text-mode="isTextMode" width="140px" placeholder="请输入" />
+          &nbsp;&nbsp;性别:
+          <FieldItem v-model="contractForm.elderGenderText" :is-text-mode="isTextMode" width="60px" placeholder="男/女" />
+          &nbsp;&nbsp;出生年月日:
+          <FieldItem v-model="contractForm.elderBirth" :is-text-mode="isTextMode" type="date" width="200px" placeholder="请选择日期" />
+        </p>
+        <p class="content-text">
+          证件类型:
+          <FieldItem v-model="contractForm.elderPapersType" :is-text-mode="isTextMode" type="dict" dictType="PAPERS_TYPE" width="200px" placeholder="请选择证件类型" />
+        </p>
+        <p class="content-text">
+          证件号码:
+          <FieldItem v-model="contractForm.elderIdCard" :is-text-mode="isTextMode" width="220px" placeholder="请输入" />
+        </p>
+        <p class="content-text">
+          家庭地址:
+          <FieldItem v-model="contractForm.elderAddress" :is-text-mode="isTextMode" width="260px" placeholder="请输入" />
+        </p>
+        <p class="content-text">
+          户籍所在地:
+          <FieldItem v-model="contractForm.elderAddress" :is-text-mode="isTextMode" width="260px" placeholder="请输入" />
+          邮编:
+          <FieldItem v-model="contractForm.elderZip" :is-text-mode="isTextMode" width="100px" placeholder="请输入" />
+        </p>
+
+        <h3 class="subsection-title" style="margin-top: 16px;">丙方(老年人家属/监护人/担保人/委托代理人的个人或组织)</h3>
+        <p class="content-text">
+          姓名:
+          <FieldItem v-model="contractForm.partyCName" :is-text-mode="isTextMode" width="140px" placeholder="请输入" />
+          &nbsp;&nbsp;性别:
+          <FieldItem v-model="contractForm.partyCGenderText" :is-text-mode="isTextMode" width="60px" placeholder="男/女" />
+          &nbsp;&nbsp;出生年月:
+          <FieldItem v-model="contractForm.partyCBirth" :is-text-mode="isTextMode" type="date" width="200px" placeholder="请选择日期" />
+        </p>
+        <p class="content-text">
+          与乙方关系:
+          <FieldItem v-model="contractForm.partyCRelation" :is-text-mode="isTextMode" width="140px" placeholder="请输入" />
+        </p>
+        <p class="content-text">
+          证件类型:
+          <FieldItem v-model="contractForm.partyCPapersType" :is-text-mode="isTextMode" type="dict" dictType="PAPERS_TYPE" width="200px" placeholder="请选择证件类型" />
+        </p>
+        <p class="content-text">
+          证件号码:
+          <FieldItem v-model="contractForm.partyCIdCard" :is-text-mode="isTextMode" width="220px" placeholder="请输入" />
+          &nbsp;&nbsp;联系方式:
+          <FieldItem v-model="contractForm.partyCPhone" :is-text-mode="isTextMode" width="160px" placeholder="请输入" />
+        </p>
+        <p class="content-text">
+          住所(址):
+          <FieldItem v-model="contractForm.partyCAddress" :is-text-mode="isTextMode" width="280px" placeholder="请输入" />
+        </p>
+        <p class="content-text">
+          户籍所在地:
+          <FieldItem v-model="contractForm.partyCHomeAddr" :is-text-mode="isTextMode" width="260px" placeholder="请输入" />
+          邮编:
+          <FieldItem v-model="contractForm.partyCZip" :is-text-mode="isTextMode" width="100px" placeholder="请输入" />
+        </p>
+        <p class="content-text">
+          工作单位:
+          <FieldItem v-model="contractForm.partyCWorkUnit" :is-text-mode="isTextMode" width="280px" placeholder="请输入" />
+        </p>
+        <p class="content-text">
+          通信地址:
+          <FieldItem v-model="contractForm.partyCCommAddr" :is-text-mode="isTextMode" width="280px" placeholder="请输入" />
+        </p>
+        <p class="content-text" style="margin-top: 14px; font-size: 13px;">
+          (若乙方属于限制民事行为能力或者无民事行为能力的入住老年人,须由监护人签字确认)
+        </p>
+      </div>
+    </div>
+
+    <!-- ========== 第4页:鉴于 + 第一条 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">4</span>
+      </div>
+      <div class="page-content">
+        <h3 class="subsection-title">鉴于:</h3>
+        <p class="content-text">
+          1、甲方是依法成立的养老机构,能够提供个人生活照料、康复护理、精神慰藉、文化娱乐等养老服务;
+        </p>
+        <p class="content-text">
+          2、乙方和丙方经实地考察甲方,自愿决定乙方入住甲方开办的养老机构,接受甲方提供的专业养老服务,并向甲方支付相应费用;
+        </p>
+        <p class="content-text">
+          3、乙方授权丙方作为乙方在紧急情况下的代理人、联系人,代为处理乙方在本合同项下的相关事务,丙方同意接受乙方授权并作为乙方履行本合同义务的保证人。
+        </p>
+        <p class="content-text">
+          4、接收条件:乙方保证无精神病,无传染性疾病,无吸毒嗜好,无自杀、自残、攻击他人等危害自身、他人和公共安全的精神性障碍或缺陷,并且适应集体生活;
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;为了营造温馨、舒适、安全的生活环境,满足老年人"老有所养、老有所乐"的需要,切实保障老年人的合法权益,同时明确各自的权利义务,甲、乙、丙三方根据《中华人民共和国民法典》《中华人民共和国老年人权益保障法》《广东省养老服务条例》《广州市养老服务条例》和《养老机构管理办法》等有关法律、法规的规定,本着平等、自愿、公平、诚实守信的原则,经友好协商,就甲方为乙方提供养老服务事宜达成一致,签订本合同。
+        </p>
+
+        <h2 class="section-title">第一条&nbsp;&nbsp;服务内容</h2>
+        <p class="content-text">
+          1.甲方按照约定向乙方提供生活照料、康复护理、精神慰藉、文化娱乐等服务。甲方提供的服务应当符合法律法规规章和国家强制性标准《养老机构服务安全基本规范》要求,并积极适用行业和地方标准。
+        </p>
+        <p class="content-text">
+          2.甲方应依据广州市老年人照护需求综合评估规范,对乙方进行照护需求等级评估,根据评估结果和乙方提供的《体检报告》,经与乙方或丙方商定后,确定乙方照护等级,并由甲方按照约定的《护理等级与服务项目》(附件)为乙方提供相应服务。
+        </p>
+        <p class="content-text">
+          2.1根据乙方提供的《体检报告》、《入住登记表》(见本合同附件)及甲方对乙方进行护理等级首评,确定乙方护理级别为:
+          <FieldItem v-model="contractForm.nurseLevelName" :is-text-mode="isTextMode" width="180px" placeholder="请输入" />
+          ,甲方向乙方提供的护理等级服务项目详见本合同附件《护理等级与服务项目》。
+        </p>
+        <p class="content-text">
+          2.2因老年人护理等级评估涉及到乙方的日常生活、精神状态、感知觉与沟通、社会参与等方面的评估,甲方为乙方进行护理等级复评,如复评与首评的护理等级一致,则按照首评护理等级服务项目进行收费和服务;如果复评与首评的护理等级不一致,则按照复评结果调整护理等级服务项目,并调整服务项目的收费和服务内容,甲方应通知乙方、丙方签订书面补充协议进行护理等级变更。
+        </p>
+        <p class="content-text">
+          2.3因老年人的身体机能处在不断的变化中,每入住半年或根据老年人身体变化需要,甲方会对乙方护理等级进行动态评估,如护理等级有调整,按照新的护理等级服务项目进行收费和服务,并签订书面补充协议。
+        </p>
+        <p class="content-text">
+          3.在本合同履行过程中,乙方或丙方如果选择《护理等级与服务项目》以外的其他服务项目,经当事人协商一致后另行签署书面补充协议确定。
+        </p>
+      </div>
+    </div>
+
+    <!-- ========== 第5页:第二条 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">5</span>
+      </div>
+      <div class="page-content">
+        <h2 class="section-title">第二条&nbsp;&nbsp;服务地点及设施</h2>
+        <p class="content-text">
+          1.经协商,确定本合同期限为
+          <FieldItem v-model="contractForm.contractMonths" :is-text-mode="isTextMode" width="60px" placeholder="12" />
+          个月,自
+          <FieldItem v-model="contractForm.startDate" :is-text-mode="isTextMode" type="date" width="180px" placeholder="请选择日期" />
+          起至
+          <FieldItem v-model="contractForm.endDate" :is-text-mode="isTextMode" type="date" width="180px" placeholder="请选择日期" />
+          止。
+        </p>
+        <p class="content-text">
+          2.甲方为乙方提供养老服务的地点为:
+          <FieldItem v-model="contractForm.servicePlace" :is-text-mode="isTextMode" width="260px" placeholder="请输入" />
+        </p>
+
+        <h3 class="subsection-title" style="margin-top: 14px;">第三条&nbsp;&nbsp;服务费用</h3>
+        <p class="content-text">
+          1.养老服务费用标准:
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;(1)养老服务费用为:
+          <FieldItem v-model="contractForm.totalFee" :is-text-mode="isTextMode" width="100px" placeholder="0" />
+          元/月。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;其中:床位费:
+          <FieldItem v-model="contractForm.bedFee" :is-text-mode="isTextMode" width="100px" placeholder="0" />
+          元/月;护理费:
+          <FieldItem v-model="contractForm.nurseFee" :is-text-mode="isTextMode" width="100px" placeholder="0" />
+          元/月;伙食费:
+          <FieldItem v-model="contractForm.mealFee" :is-text-mode="isTextMode" width="100px" placeholder="0" />
+          元/月;
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;其他费用:1)水电费:超出床位费包含的每人每月
+          <FieldItem v-model="contractForm.manageFee" :is-text-mode="isTextMode" width="80px" placeholder="0" />
+          千瓦时电和
+          <FieldItem v-model="contractForm.manageFee" :is-text-mode="isTextMode" width="80px" placeholder="0" />
+          立方冷水的免费额度后,超出部分按实际支出进行对应房型具体入住床数进行均摊收取。
+        </p>
+      </div>
+    </div>
+
+    <!-- ========== 第6页:第二条继续 + 第三条开头 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">6</span>
+      </div>
+      <div class="page-content">
+        <p class="content-text">
+          3.乙方或丙方为乙方选择入住的房间类型为(在以下几种情况中选择一种):
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;□单间&nbsp;&nbsp;□双人间&nbsp;&nbsp;□三人间&nbsp;&nbsp;□多人间(四人以上六人以下,含四人、六人)&nbsp;&nbsp;□其他(套房等)。
+        </p>
+        <p class="content-text">
+          4.乙方或丙方为乙方选择的具体房间为:
+          <FieldItem v-model="contractForm.roomNo" :is-text-mode="isTextMode" width="120px" placeholder="请输入" />
+          。
+        </p>
+        <p class="content-text">
+          5.乙方或丙方基于正当理由要求调整房间的,甲方在条件许可的范围内应尽量满足。若因房间变化,需要相应调整费用的,应由各方协商一致书面确认后调整,如各方不能达成一致意见书面确认,则仍依本合同约定房间履行。
+        </p>
+        <p class="content-text">
+          6.甲方提供的服务设施除了住宿的房屋,还包括房间内生活起居必要的基础设施及其他公共设施。
+        </p>
+
+        <h3 class="subsection-title" style="margin-top: 14px;">第三条&nbsp;&nbsp;服务费用及费用支付方式</h3>
+        <p class="content-text">
+          1.甲方的收费标准和调整应遵守养老机构服务收费管理的相关规定,不得违规收取大额预付、向服务对象兜售保健品,不得以许诺还本付息或者给予其他投资回报、虚假夸大宣传、承诺明显低于市场价入住、折扣返利等与事实不符的条件诱导乙方或丙方交纳费用。
+        </p>
+        <p class="content-text">
+          2.甲方提供的各种服务项目的收费标准和收费依据应在养老机构内公共区域显著位置进行公示,并以公共区域或网络方式(养老机构网站、政府部门有关网站等)进行线上公示,服务项目及其收费标准应作为本合同附件。
+        </p>
+        <p class="content-text">
+          3.根据本合同第一条、第二条乙方选择的房间、照护等级及服务项目,各方共同确认,乙方入住甲方需支付的养老服务费用具体如下:
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;(1)养老服务费用为:
+          <FieldItem v-model="contractForm.totalFee" :is-text-mode="isTextMode" width="100px" placeholder="0" />
+          元/月。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;其中:
+        </p>
+      </div>
+    </div>
+
+    <!-- ========== 第7页:第三条费用条款明细 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">7</span>
+      </div>
+      <div class="page-content">
+        <p class="content-text">
+          床位费:
+          <FieldItem v-model="contractForm.bedFee" :is-text-mode="isTextMode" width="120px" placeholder="0" />
+          元/月;
+        </p>
+        <p class="content-text">
+          护理费:
+          <FieldItem v-model="contractForm.nurseFee" :is-text-mode="isTextMode" width="120px" placeholder="0" />
+          元/月;
+        </p>
+        <p class="content-text">
+          伙食费:
+          <FieldItem v-model="contractForm.mealFee" :is-text-mode="isTextMode" width="120px" placeholder="0" />
+          元/月;
+        </p>
+        <p class="content-text">
+          其他费用:
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1)水电费:超出床位费包含的每人每月
+          <FieldItem v-model="contractForm.freeElectric" :is-text-mode="isTextMode" width="80px" placeholder="0" />
+          千瓦时电和
+          <FieldItem v-model="contractForm.freeWater" :is-text-mode="isTextMode" width="80px" placeholder="0" />
+          立方冷水的免费额度后,超出部分按实际支出进行对应房型具体入住床数进行均摊收取,超出部分收费标准为:热水
+          <FieldItem v-model="contractForm.hotWaterFee" :is-text-mode="isTextMode" width="80px" placeholder="0" />
+          元/立方;冷水
+          <FieldItem v-model="contractForm.coldWaterFee" :is-text-mode="isTextMode" width="80px" placeholder="0" />
+          元/立方;电
+          <FieldItem v-model="contractForm.electricFee" :is-text-mode="isTextMode" width="80px" placeholder="0" />
+          元/千瓦时;
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2)诊查费:
+          <FieldItem v-model="contractForm.diagnosisFee" :is-text-mode="isTextMode" width="120px" placeholder="0" />
+          元/月
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          出现合同中止或终止情形的,扣除实际入住天数产生的费用后予以退款。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;(2)一次性收取的费用(如有请填写)。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;①一次性设施设备费
+          <FieldItem v-model="contractForm.oneTimeEquipFee" :is-text-mode="isTextMode" width="100px" placeholder="0" />
+          元,收取的期限自
+          <FieldItem v-model="contractForm.oneTimeEquipStart" :is-text-mode="isTextMode" type="date" width="180px" placeholder="请选择日期" />
+          至
+          <FieldItem v-model="contractForm.oneTimeEquipEnd" :is-text-mode="isTextMode" type="date" width="180px" placeholder="请选择日期" />
+          (建议时长不超过3年)。出现合同中止或终止情形的,扣除实际入住天数产生的费用后,按照以下标准予以退款:
+          <FieldItem v-model="contractForm.depositRefund" :is-text-mode="isTextMode" width="180px" placeholder="请填写" />
+          。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;②押金(如有请填写押金类型:履约及医疗保证金:
+          <FieldItem v-model="contractForm.depositFee" :is-text-mode="isTextMode" width="100px" placeholder="0" />
+          元。出现合同中止情形的,予以全额退还(□押金不计利息 ☑押金计利息,计息标准为:
+          <FieldItem v-model="contractForm.depositInterest" :is-text-mode="isTextMode" width="160px" placeholder="无" />
+          &nbsp;&nbsp;元&nbsp;&nbsp;)。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;合同期限内出现押金不足时,乙方或丙方应在接到甲方通知之日起5日内补足。涉及退款的,在出现合同中止或终止情形后,双方进行结算,经双方确认无误之日起15个工作日内将资金退给付款方。
+        </p>
+        <p class="content-text">
+          4.定期支付的费用按第
+          <FieldItem v-model="contractForm.payMode" :is-text-mode="isTextMode" width="40px" placeholder="1" />
+          种方式支付:
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;(1)按月支付(每月
+          <FieldItem v-model="contractForm.payMonthDay" :is-text-mode="isTextMode" width="40px" placeholder="5" />
+          日前支付下一个月费用);
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;(2)按季度支付(每季度第
+          <FieldItem v-model="contractForm.paySeasonMonth" :is-text-mode="isTextMode" width="40px" placeholder="1" />
+          个月的
+          <FieldItem v-model="contractForm.paySeasonDay" :is-text-mode="isTextMode" width="40px" placeholder="5" />
+          日前支付当季费用);
+        </p>
+      </div>
+    </div>
+
+    <!-- ========== 第8页:第三条继续 + 第四条甲方权利义务 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">8</span>
+      </div>
+      <div class="page-content">
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;(3)其它:
+          <FieldItem v-model="contractForm.otherPayMode" :is-text-mode="isTextMode" width="160px" placeholder="请填写" />
+          /
+          <FieldItem v-model="contractForm.otherPayMode2" :is-text-mode="isTextMode" width="100px" placeholder="请填写" />
+          。
+        </p>
+        <p class="content-text">
+          5.甲方指定的收款账户信息如下:
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;户名:
+          <FieldItem v-model="contractForm.partyAAccountName" :is-text-mode="isTextMode" width="260px" placeholder="请输入" />
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;开户银行:
+          <FieldItem v-model="contractForm.partyABank" :is-text-mode="isTextMode" width="260px" placeholder="请输入" />
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;账号:
+          <FieldItem v-model="contractForm.partyAAccount" :is-text-mode="isTextMode" width="280px" placeholder="请输入" />
+        </p>
+        <p class="content-text">
+          6.乙方或丙方指定的付款账户信息如下:
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;户名:
+          <FieldItem v-model="contractForm.partyCAccountName" :is-text-mode="isTextMode" width="260px" placeholder="请输入" />
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;开户银行:
+          <FieldItem v-model="contractForm.partyCBank" :is-text-mode="isTextMode" width="260px" placeholder="请输入" />
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;账号:
+          <FieldItem v-model="contractForm.partyCAccount" :is-text-mode="isTextMode" width="280px" placeholder="请输入" />
+        </p>
+        <p class="content-text">
+          7.乙方接受甲方除本合同约定外的其他服务项目的,应根据甲方公示的收费标准和补充合同的约定交纳费用。
+        </p>
+        <p class="content-text">
+          8.甲方每月向乙方或丙方提供《个人费用明细表》,乙方或丙方应签字确认。乙方或丙方如有异议,可在收到《个人费用明细表》后7日内书面提出,甲方应做出书面说明。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;对于双方无争议费用金额应按照本合同约定时间支付,乙方或丙方不得以异议费用为由拒绝支付有关费用。
+        </p>
+        <p class="content-text">
+          9.乙方、丙方共同承担向甲方支付本合同约定价款的义务。
+        </p>
+        <p class="content-text">
+          10.甲方在收到款项后应向付款人开具等额的合法收费发票。
+        </p>
+
+        <h2 class="section-title">第四条&nbsp;&nbsp;甲方权利及义务</h2>
+        <h3 class="subsection-title">1.甲方权利</h3>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.1&nbsp;有权按照本合同约定收取相关费用。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.2&nbsp;制订、修改并在养老机构公示管理制度,并按照公开的管理制度对乙方进行管理。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.3&nbsp;为了乙方的健康和安全,乙方出现紧急情况时,有权在通知
+        </p>
+      </div>
+    </div>
+
+    <!-- ========== 第9页:第四条甲方权利义务继续 + 甲方义务 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">9</span>
+      </div>
+      <div class="page-content">
+        <p class="content-text">
+          乙方或丙方同意的同时,采取必要的处置措施,包括但不限于转送医疗机构,由此产生的费用由乙方或丙方承担。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.4&nbsp;如乙方的身体状况、生活自理能力出现变化,由甲方根据对乙方护理等级评价另行确定护理等级,相关费用随之进行调整,如一周联系不上乙方,甲方有权根据乙方所需服务项目的变化情况在押金中扣除,不足部分甲方有权要求乙方和丙方支付所产生变化的费用,由乙方和丙方按甲方核定的标准支付。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.5&nbsp;乙方入住后因精神、情绪、性格、生活习惯等原因不适宜院内生活的,经甲方努力,仍无改善的,为维护乙方及院内其他老人的权利,甲方有权要求丙方在两天内为乙方办理退院或转院手续,丙方必须积极配合,做好安抚工作,对此甲方无需承担任何责任。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.6&nbsp;如乙方患病需要去医院治疗的,由乙方亲人送医,有权紧急处置,所涉及的各项费用由乙方和丙方承担。如乙方需甲方提供住院期间陪护服务的,相关费用由乙方和丙方承担,具体陪护事宜由当事人协商一致后另行签署书面协议确定。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.7&nbsp;有权依照本合同约定及法律规定解除合同。
+        </p>
+
+        <h3 class="subsection-title" style="margin-top: 14px;">2.甲方义务</h3>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.1&nbsp;甲方应是依法成立的养老机构,应履行养老机构备案承诺,按照建筑、消防、食品安全、医疗卫生、特种设备等法律、法规和强制性标准及服务安全相关规范要求开展服务活动,确保按约定向乙方提供符合服务质量标准的养老服务;建立各类安全、疫情防控等应急预案,并应定期对应急预案进行演练。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.2&nbsp;应当提供符合乙方住宿条件的居住用房,并配备适合乙方安全保护要求的设施、设备及用具,定期对乙方的活动场所和物品进行消毒
+        </p>
+      </div>
+    </div>
+
+    <!-- ========== 第10页:第四条甲方义务继续 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">10</span>
+      </div>
+      <div class="page-content">
+        <p class="content-text">
+          和清洗;甲方提供的饮食应当符合食品安全要求、适宜乙方食用、有利于乙方营养平衡和身体健康。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.3&nbsp;应根据登记类型、经营性质、设施设备条件、管理水平、服务质量、照料护理等级等因素合理确定服务项目收费标准,调整收费标准时应遵守国家、省、广州和广州市价格管理的有关规定。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.4&nbsp;应保证从事医疗、康复、消防等服务人员符合资质要求,保证养老护理人员接受专业技能培训,并定期组织工作人员进行职业道德教育和业务培训,能够满足岗位职责要求。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.5&nbsp;在提供服务过程中,甲方及其工作人员应尊重乙方、尽力合理地保障乙方的人格尊严和人身、财产安全,并接受乙方、丙方的合理建议和监督。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.6&nbsp;应当根据需要为乙方提供情绪疏导、心理咨询、危机干预等精神慰藉服务;应当开展适合老年人的文化、教育、体育、娱乐活动,丰富老年人的精神文化生活。甲方开展文化、教育、体育、娱乐活动时,应当为乙方提供必要的安全防护措施。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.7&nbsp;定期组织所在地的医疗机构为乙方开展体检并建立个人健康档案。妥善保存乙方的入住登记表、体检报告等健康资料以及日常经费开支情况等个人信息。应当建立各类信息资料的保管、归档和保密制度,除向乙方、丙方和其他有权部门(公安局、检察院、法院、纪委监察、养老服务行业主管部门因办案、监督、检查需要)提供查阅、允许复制外,不得对外透露。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.8&nbsp;发现乙方为疑似传染病病人或者精神障碍患者时,应依照传染病防治、精神卫生等相关法律法规的规定处理,及时向附近的疾病预防控制机构或者医疗机构报告,配合实施卫生处理、隔离等预防控制措施,
+        </p>
+      </div>
+    </div>
+
+    <!-- ========== 第11页:甲方义务继续 + 第五条 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">11</span>
+      </div>
+      <div class="page-content">
+        <p class="content-text">
+          并及时通知丙方。乙方需要外出就医的,甲方应及时告知丙方并由有相关义务的丙方亲自携带乙方就诊,丙方确实未能亲自携带乙方就诊的,应通过委托办理等方式作出妥善安排。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.9&nbsp;应当为乙方家庭成员看望或者问候老年人提供便利,为乙方联系家庭成员提供帮助;但不得影响甲方对于乙方正常服务运营或执行政府部门规定的疫情防控等管理要求,否则甲方有权拒绝。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.10&nbsp;在发生公共卫生事件等特殊情况下,甲方应贯彻执行政府部门的防控政策规定,积极落实防控措施,并向乙方或丙方做好解释工作。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.11&nbsp;甲方暂停、终止服务的,应当在暂停或终止服务60日前,书面通知乙方或丙方,并向社会公告;将入住老年人的安置方案书面告知甲方所在地的区级民政部门。在解散清算前,甲方应当依法妥善安置乙方。如乙方或丙方有意与其他养老机构签订服务协议的,甲方应当积极为乙方联系与甲方具有同等资质和服务水平的养老服务机构,努力促进双方建立合同;如乙方或丙方解除或终止服务协议的,甲方应当退还乙方或丙方剩余未消费或合同约定的有关费用。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.12&nbsp;当乙方出现紧急情况时,应及时联系和通知丙方。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.13&nbsp;在甲方服务期间,经鉴定乙方正常死亡的,甲方应及时与丙方取得联系。无法与丙方取得联系的且机构内不具备遗体保存条件,可严格按照规定要求使用《广州市养老机构死亡报告书》并对接殡仪馆,妥善保存遗体。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.14&nbsp;乙方符合长期护理保险等申报条件的,甲方应积极为其申请。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.15&nbsp;乙方入住养老机构、请假外出、终止合同离院和去世,甲方应及时在广州市为老服务综合平台填报有关信息。
+        </p>
+
+        <h2 class="section-title">第五条&nbsp;&nbsp;乙方权利及义务</h2>
+      </div>
+    </div>
+
+    <!-- ========== 第12页:乙方权利及义务 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">12</span>
+      </div>
+      <div class="page-content">
+        <h3 class="subsection-title">1.乙方的权利</h3>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.1&nbsp;享有隐私权,人格尊严和人身、财产安全不受非法侵害的权利。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.2&nbsp;有权按照约定的服务项目获得甲方提供的符合服务标准的养老服务,对甲方的服务有批评建议的权利。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.3&nbsp;对自身的健康状况、费用支出、入院记录等有知情权,有权查阅、复印甲方为其建立的个人档案。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.4&nbsp;有权了解提供服务的人员是否经过专业培训,是否具备相应资质,有权要求甲方更换未经专业培训或不具备相应资质或提供服务不合格的人员。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.5&nbsp;在突发疾病的情况下乙方有权获得及时、必要的医疗帮助。
+        </p>
+
+        <h3 class="subsection-title" style="margin-top: 14px;">2.乙方的义务</h3>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.1&nbsp;应当按照约定自行或与丙方共同支付养老服务费及相关费用。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.2&nbsp;应当按照约定提供相关的体检报告,如实告知甲方本人的健康状况、药品使用情况及过往病史等信息,并如实填写《入住登记表》。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.3&nbsp;应当配合甲方做好持续评估及确认照护等级;配合甲方定期参加体检。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.4&nbsp;应当与其他入住老年人和谐相处。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.5&nbsp;在接收甲方提供的养老服务期间,因疾病进行诊疗时,应在治疗期间遵守医嘱,配合治疗。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.6&nbsp;应当服从甲方管理,遵守甲方的规章制度,维护养老机构正常服务秩序,爱护甲方提供的各项服务设施,入住期间损坏甲方设施设备的,乙方或丙方应当予以赔偿。损坏有关服务设施的赔偿价格可与甲方协商约定。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.7&nbsp;对于甲方提供的其他符合合同约定、法律规定的养老服务,乙
+        </p>
+      </div>
+    </div>
+
+    <!-- ========== 第13页:乙方义务继续 + 第六条 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">13</span>
+      </div>
+      <div class="page-content">
+        <p class="content-text">
+          方应予配合甲方的服务工作。
+        </p>
+
+        <h2 class="section-title">第六条&nbsp;&nbsp;丙方权利及义务</h2>
+        <h3 class="subsection-title">1.丙方的权利</h3>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.1&nbsp;对乙方有探视权,但不得影响甲方对乙方的正常服务管理和执行政府规定的疫情防控等管理要求。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.2&nbsp;对乙方的健康状况、享受服务情况、费用支出、入院记录等有知情权,有权查阅、复印甲方为乙方建立的个人档案。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.3&nbsp;有权了解提供服务的人员是否经过专业培训,是否具备相应资质,有权要求甲方更换未经专业培训或不具备相应资质或提供服务不合格的人员;有权对甲方的服务提出批评建议。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.4&nbsp;遇紧急情况时,包括但不限于乙方走失、身体健康状况出现紧急情况时,有权及时从甲方得到相关信息。
+        </p>
+
+        <h3 class="subsection-title" style="margin-top: 14px;">2.丙方的义务</h3>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.1&nbsp;乙方入住前,丙方要如实向甲方反映乙方的情况,如脾气秉性、家庭成员、既往病史、健康状况和药品使用情况等,协助乙方如实填写《入住登记表》。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.2&nbsp;劝导乙方入住后自觉遵守养老机构的规章制度,接受管理,爱护甲方提供的各项服务设施。乙方违反本合同约定或甲方制定的规章制度,造成甲方损失或第三人人身、财产损害的,乙方需承担赔偿责任,负有付款义务或需连带责任的丙方应当承担有关赔偿责任。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.3&nbsp;应劝导乙方与其他入住老年人和谐相处,并经常与乙方沟通,保持联络,满足乙方的精神需求。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.4&nbsp;应劝导乙方在接收甲方提供的养老服务期间,因疾病进行诊疗时,应在治疗期间遵守医嘱,配合治疗。乙方需外出就医的,负有相关
+        </p>
+      </div>
+    </div>
+
+    <!-- ========== 第14页:丙方义务继续 + 第七条 + 第八条 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">14</span>
+      </div>
+      <div class="page-content">
+        <p class="content-text">
+          义务的丙方应当及时携乙方到医院就诊,并向甲方如实告知乙方的就医情况。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.5&nbsp;按时足额向甲方支付约定的养老服务费、保证金及相关费用。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.6&nbsp;丙方的家庭及单位地址、联系方式变更时,应及时通知甲方。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.7&nbsp;及时协助甲方处理乙方出现的紧急情况。当甲方按照合同约定处理时,负有付款义务或连带责任的丙方应当及时足额支付由此产生的费用。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.8&nbsp;乙方在养老机构去世的,丙方应及时进行善后处理并解决费用问题。
+        </p>
+
+        <h2 class="section-title">第七条&nbsp;&nbsp;合同的续签</h2>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.合同期满前
+          <FieldItem v-model="contractForm.renewNoticeDays" :is-text-mode="isTextMode" width="40px" placeholder="30" />
+          日,乙方或丙方可向养老机构申请续签合同。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.续签的养老服务合同内容应当由甲方、乙方和丙方协商确定。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;3.如果乙方或丙方未在合同期限届满前
+          <FieldItem v-model="contractForm.renewNoticeDays" :is-text-mode="isTextMode" width="40px" placeholder="30" />
+          日提出续签合同,或者乙方或丙方虽在合同期限届满前
+          <FieldItem v-model="contractForm.renewNoticeDays" :is-text-mode="isTextMode" width="40px" placeholder="30" />
+          日提出续签合同申请,但各方未就合同续签达成一致,乙方应于合同到期后
+          <FieldItem v-model="contractForm.moveOutDays" :is-text-mode="isTextMode" width="40px" placeholder="3" />
+          日内搬离甲方,办理离院手续并结清所有费用。
+        </p>
+
+        <h2 class="section-title">第八条&nbsp;&nbsp;合同的变更和解除</h2>
+        <h3 class="subsection-title">1.合同的变更</h3>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.1&nbsp;根据乙方健康状况的变化以及护理等级的评估结果,乙方、丙方可以要求甲方变更服务方案,甲方亦可以提出变更服务方案,并以书面形式通知乙方及丙方。任何一方要求变更服务方案的,需经甲方、乙方、丙方三方协商一致,签署补充协议。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;若甲方提出变更服务方案,乙方或丙方收到甲方变更服务方案的书面通知后
+          <FieldItem v-model="contractForm.changeConfirmDays" :is-text-mode="isTextMode" width="40px" placeholder="7" />
+          日内既不确认又不提出异议,但乙方实际接受甲方提供的相
+        </p>
+      </div>
+    </div>
+
+    <!-- ========== 第15页:合同变更继续 + 合同解除 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">15</span>
+      </div>
+      <div class="page-content">
+        <p class="content-text">
+          应服务的,视为甲、乙、丙三方就合同约定的服务项目的变更达成一致,乙方或丙方有义务按照新的服务项目支付相应的服务费用。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;若乙方或者丙方提出变更方案,甲方应在收到其变更服务方案的要求后
+          <FieldItem v-model="contractForm.priceObjDays" :is-text-mode="isTextMode" width="40px" placeholder="30" />
+          日内会同乙方或者丙方进行研究确定,变更方案符合有关规定和实际情况的,甲方应予以采纳。经沟通未能达成一致意见的,甲方有义务应向乙方或丙方解释不采纳其变更方案的理由和依据,乙方或丙方仍不能接受的,可向属地民政部门反映或向司法部门起诉。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;如果根据乙方健康状况的变化以及护理等级的评估结果,不调整服务项目将导致乙方的健康安全无法保障的,甲方提出变更的服务方案后,乙方或丙方既不同意,也不接受实际服务的,甲方、乙方或丙方均有权解除本合同。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;当食品材料市场价格发生重大变化,致使甲方服务成本急剧上升(单项价格变动幅度超过
+          <FieldItem v-model="contractForm.priceThreshold" :is-text-mode="isTextMode" width="40px" placeholder="6" />
+          %时),甲方可适当调整伙食费收费标准,将价格调整的通知在调价前
+          <FieldItem v-model="contractForm.priceAdjustNoticeDays" :is-text-mode="isTextMode" width="40px" placeholder="30" />
+          日以书面形式通知乙方及丙方,并签订补充合同。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;乙方或丙方对价格调整有异议的,可在收到通知后
+          <FieldItem v-model="contractForm.priceObjDays" :is-text-mode="isTextMode" width="40px" placeholder="15" />
+          日内以书面形式提出解除合同;乙方或丙方要求继续按照原收费标准履行合同的,甲方有权提出解除合同。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;乙方或丙方收到通知后
+          <FieldItem v-model="contractForm.priceConfirmDays" :is-text-mode="isTextMode" width="40px" placeholder="15" />
+          日内不以书面形式提出异议,但拒绝根据调整后的价格支付相关费用的,甲方有权解除合同并按照原收费标准收取已提供服务的费用。
+        </p>
+
+        <h3 class="subsection-title" style="margin-top: 14px;">2.合同的解除</h3>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.1&nbsp;除本合同另有约定外,下列情况下,乙方或丙方可以单方解除本合同,并无需承担违约责任:
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          (1)甲方提供的服务不符合合同约定,经乙方或丙方提出,30日内不改正的;
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          (2)因甲方或甲方工作人员的严重过错造成乙方人身或重大财产损害的;
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          (3)乙方因疾病或其他个人原因离院的,但乙方或丙方不提出解除本合同而要求保留床位或房间的除外;乙方因疾病需要长期住院治疗(凭7天内住院证明)或去世解除合同的,免收违约金;
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          (4)履行合同过程中,乙方或丙方提前30日书面通知甲方并结清服务费用的;
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          (5)乙方首次入住15日内不适应居住环境或管理方式的,乙方可以单方解除本合同,并无需承担违约责任。
+        </p>
+
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.2&nbsp;除本合同另有约定外,下列情况下,甲方可以单方解除本合同,并无需承担违约责任:
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          (1)乙方或丙方无无故拖欠各项费用超过15日,经甲方书面催告后7日内仍不交纳的,甲方有权解除合同,并书面通知乙方搬出养老机构。乙方在甲方发出书面解除合同通知后7日内仍不搬出的,甲方有权提起诉讼,请求法院确认合同解除。乙方和丙方除应支付拖欠的服务费用,诉讼期间的服务费用以外,还应每天支付应付未付费用金额的1%违约金,并负担甲方由此产生的一切费用(包括但不限于诉讼费、甲方聘请律师的实际支出、搬出费用)等。
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          (2)乙方严重违反甲方的规章制度,造成甲方难以履行对乙方的养老服务,或造成其他入住老人伤害或存在可能造成他人伤害危险的。需对有关事实进行甄别别的,可提请属地民政部门或委托第三方协助认定。
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          (3)乙方或丙方隐瞒乙方健康状况,或者乙方患有须隔离治疗的
+        </p>
+      </div>
+    </div>
+
+    <!-- ========== 第17页:合同解除继续 + 第九条违约责任 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">17</span>
+      </div>
+      <div class="page-content">
+        <p class="content-text">
+          传染性疾病或者患有精神疾病等其他不适宜在机构内集中生活的。
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          (4)发生不可抗力致甲方不能履行合同的。
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          (5)甲方因丧失养老机构执业资格等原因暂停、终止服务的。甲方应当于暂停或者终止服务60日前向实施许可或者备案的属地民政部门提交老年人安置方案,经批准后方可解除养老机构服务合同。
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          (6)乙方连续请假外出超过
+          <FieldItem v-model="contractForm.leaveDays" :is-text-mode="isTextMode" width="60px" placeholder="60" />
+          天(限期不得少于30天)。请假期间,因病情严重需要医治或疫情防控等管理要求,乙方无法返院或甲方不具备返院条件的情形除外。
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          (7)丙方与甲方中断联系达到30天的,甲方有权选择单方解除合同。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.3&nbsp;除本合同另有约定外,下列情况下,乙方提前终止合同的,按照以下约定执行:
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;如乙方提前解除合同(除因疾病需长期住院治疗、去世解除合同外),须提前30天书面向甲方提出申请,经甲方批准后方可办理离院手续,乙方应按照本月实际享受服务天数结算本月床位费、护理费、膳食费、管理费、水电费等费用,并按照附件《服务项目收费标准》中乙方所定房型向甲方缴纳一个月床位费的违约金。
+        </p>
+
+        <h2 class="section-title">第九条&nbsp;&nbsp;违约责任</h2>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.因甲方及其工作人员的过错,损害乙方人身或财产权利的,由甲方承担赔偿责任。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.甲方服务人员资质不合格、没有按约定提供服务或者提供的服务不合格,造成乙方人身或财产损失的,甲方应当承担赔偿责任。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;3.甲方或其工作人员侵犯乙方、丙方对甲方提供的养老服务的知情权的,乙方和丙方有权要求甲方改正,造成损失的甲方应承担赔偿责任。
+        </p>
+      </div>
+    </div>
+
+    <!-- ========== 第18页:违约责任继续 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">18</span>
+      </div>
+      <div class="page-content">
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;4.如果乙方或丙方无故拖欠各项费用超过15日,经甲方发出催告通知后7日内仍不交纳的,甲方有权解除合同,书面通知乙方和丙方,要求乙方出院。如果乙方在甲方发出解除合同通知后7日内仍不出院,甲方有权强制要求乙方出院或者送回乙方或丙方住所。此种情况下解除合同,乙方及丙方除应支付拖欠的费用外,还应每天支付应付未付费用金额的1%违约金,并负担甲方由此产生的一切费用(包括但不限于诉讼费、甲方聘请律师的实际支出、搬出费用)等;
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;5.乙方或丙方未将乙方健康状况、用药情况及过往病史如实告知甲方,造成甲方在提供服务过程中护理失当的,由乙方或丙方承担相应的后果。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;6.乙方需外出就医的,甲方履行告知义务,乙方拒绝外出就医或丙方拒绝及时携乙方到医院就诊而造成的后果,由乙、丙方自行承担。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;7.甲方没有过错,因乙方原因造成其自身损害的,由乙方、丙方自行承担全部后果和责任。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;8.因乙方原因造成甲方或第三人人身或财产损失的,乙方、丙方应承担赔偿责任。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;9.签订养老服务合同后,乙方未按照合同约定时间入住的,按照以下约定办理:因紧急住院治疗无法按期办理且向公办养老机构提出由医疗机构出具的诊断结论的,由公办养老机构适当延长其资格核验、办理入住手续期限。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;10.本合同提前终止或服务期满的,乙方逾期搬离甲方养老机构的,按乙方在服务期满前一个月的养老服务费用标准的1.5倍按日计算养老服务费用,直至办理完毕离院手续并搬离甲方养老机构之日止。
+        </p>
+      </div>
+    </div>
+
+    <!-- ========== 第19页:违约责任继续 + 第十条通知与送达 + 第十一条陈述与保证 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">19</span>
+      </div>
+      <div class="page-content">
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;11.甲方按本合同约定应承担赔偿责任的,赔偿限额以甲方实际收费为限。
+        </p>
+
+        <h2 class="section-title">第十条&nbsp;&nbsp;通知与送达</h2>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.在本合同首页中所标明的甲方、乙方和丙方的地址和联系方式为各方各自有效的通讯地址和联系方式。一方变更通讯地址和联络方式应及时通知其他各方。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.以下情形,视为送达,但受送达人有证据证明其因客观原因未实际接收到通知的除外:
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          以特快专递形式发送,已经签收的,以签收日为送达日;未签收的,同城自发送之日起2日视为文件已经送达,异地5日视为送达,境外15日视为送达;以手机短信发送的,发送成功即视为送达;电子邮件自发出后进入收件方邮箱服务器视为送达;传真发送自对方传真机接收视为送达。
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          因受送达人通讯地址或其他相关信息错误、不详或发生变更未及时通知其他各方造成无法送达的,由受送达人自行承担相关后果。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;3.乙方入住甲方期间,有关本合同的履行事宜甲方应以书面或数据电文形式通知乙方或丙方,由乙方或丙方确认签收;乙方或丙方拒绝的,书面通知在第三方见证下送至收件人地址的视为已通知或已送达,数据电文进入收件人接收系统的视为已通知或已送达。
+        </p>
+
+        <h2 class="section-title">第十一条&nbsp;&nbsp;陈述与保证</h2>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.甲方保证为依照法律、行政法规设立并依法登记的养老机构,具有提供本合同约定的养老服务的资格和能力。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.乙方或丙方保证乙方不属于患有精神病、甲类或乙类传染性疾病等不符合入住养老机构疾病的老年人。
+        </p>
+      </div>
+    </div>
+
+    <!-- ========== 第20页:陈述与保证继续 + 第十二条特别约定 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">20</span>
+      </div>
+      <div class="page-content">
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;3.乙方或丙方保证向甲方提供乙方在本协议签署前1个月内在甲方所在地二级甲等以上医院进行体检的《体检报告》(体检项目包括:精神健康状况、传染性疾病及养老机构要求的其他体检项目等)(作为本合同附件)。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;4.乙方或丙方保证向甲方提供的乙方或丙方共同签字的《入住登记表》(作为本协议附件)是真实的,没有任何虚假或隐瞒。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;5.丙方保证履行本合同履行过程的联系人,接收甲方的通知,如涉及诉讼、仲裁或其他法律程序的,保证作为相关机构法律文书的接收人,甲方或相关机构向乙方或保证人所列明的地址、联系方式等送达相关文书的,均视为有效送达。
+        </p>
+
+        <h2 class="section-title">第十二条&nbsp;&nbsp;特别约定</h2>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.甲方仅提供与合同约定护理等级相符的相关服务,对于超出护理等级的看护、注意义务,甲方将依据现实情况、乙方身体状况尽可能的提供帮扶、协助,但不表示甲方愿意接受超出合同约定的范围的约束;甲方不是专业的医疗机构,对乙方进行的常规体检不代表甲方对乙方真实身体状况的了解,也不能代表甲方对乙方身体状况的确认,一切以专业的医疗机构及医护人员的判断为准。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.突发疾病或出现事故等紧急情况的处理
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          (1)乙方在入住期间突发疾病或身体伤害事故,甲方应及时通知丙方,及时联系120等医疗急救机构;如需到医疗机构急救,甲方应派人陪送至医疗机构。甲方不能及时联系上丙方的,应尽早与本合同附件确定的其他联系人取得联系并通报情况。
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          (2)甲方具有医疗资质的,在乙方生命垂危等紧急情况下应尽到合理诊疗义务,费用由乙方和丙方承担。
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          (3)因乙方发生紧急情况产生的费用急救费用、治疗费用、住院押金等均由乙方和丙方负担。甲方因此垫付费用的,乙方或丙方应按照甲方要求的时间内清偿。
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          (4)为保证入住长者的生活环境,甲方暂未设有临终关怀服务,当乙方生命垂危时,丙方应全力配合甲方将乙方送医院进行抢救;若乙方或丙方任何一方不予配合,甲方有权将乙方送往就近医院抢救并扣除乙方入住时缴纳人民币
+          <FieldItem v-model="contractForm.depositAmt1" :is-text-mode="isTextMode" width="120px" placeholder="0" />
+          元(大写金额:
+          <FieldItem v-model="contractForm.depositAmtCn1" :is-text-mode="isTextMode" width="200px" placeholder="零元整" />
+          )的押金,救护费用不足部分由乙方及丙方承担;
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          (5)若乙方在甲方养老院突然去世,丙方须全力配合甲方将乙方以医疗救护的方式将乙方送往就近医院;若丙方不予配合,甲方有权扣除乙方入住时缴纳人民币
+          <FieldItem v-model="contractForm.depositAmt2" :is-text-mode="isTextMode" width="120px" placeholder="0" />
+          元(大写金额:
+          <FieldItem v-model="contractForm.depositAmtCn2" :is-text-mode="isTextMode" width="200px" placeholder="零元整" />
+          )的押金,费用不足部分由丙方承担。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;3.乙方去世的善后服务及相关费用
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          乙方在甲方服务期间去世的,甲方应及时与丙方取得联系,丙方负责善后处理并承担相关费用。无法与丙方取得联系的,应及时联系殡仪馆,妥善保存遗体,发生的费用由丙方承担。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;4.甲方与丙方联系中断
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          因丙方提供的联系地址、方式不准确或不详细或变更后未及时通知甲方,或其他客观原因致使甲方无法与丙方及时联系,连续达30天则视为联系中断。甲方与乙方协商后,可以重新确定联系人。联系中断不免除丙方在本合同项下的责任。
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          因乙方、丙方原因导致联系中断的,如乙方仍有其他直系亲属的,则甲方有权自行联系其他直系亲属协商重新确定联系人或解除合同关系,无其他直系亲属或无其他亲属愿意承担乙方相关费用的,则甲方有
+        </p>
+      </div>
+    </div>
+
+    <!-- ========== 第22页:特别约定继续 + 第十三条争议解决 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">22</span>
+      </div>
+      <div class="page-content">
+        <p class="content-text">
+          权自行联系相关政府部门或其他机构解决处理有关乙方的托养事宜,因此而产生的相关费用,甲方有权向乙方或丙方追偿。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;5.非因甲方故意或重大过失的原因造成乙方人身、财产损害的,甲方不承担责任。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;乙方入住后若发生根据体检报告所反映出的一系列疾病、并发症或突发性疾病导致死亡,与甲方无关;
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;由于乙方属高龄及有疾病的长者,易发生意外,入住期间非因甲方原因发生骨折、心脏骤停、脑梗、脑溢血、呛咳、肺部感染等疾病导致死亡与甲方无关;
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;乙方入住后,经甲方诊断有疾病且书面通知乙方前往三甲及以上的医院进行治疗的,乙方应及时前往医院就医;若乙方或丙方不予配合,乙方发生任何意外,由乙方和丙方承担全部责任。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;6.乙方具有完全民事行为能力,但拒绝接收甲方提供服务,造成其自身人身、财产损害的,由乙方自行承担后果。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;7.本合同关于乙方和丙方权利义务的约定,并不免除对乙方有法定赡养义务的其他人员的法定责任。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;8.因不可抗力导致本合同无法继续履行的、受到不可抗力影响的一方应在不可抗力情形发生后及时通知合同其他相关方,本合同可依法解除,合同各方不承担解除合同的责任。丙方应及时接回并妥善安置乙方。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;9.甲方破产、停业、转让:甲方需提前30天通知乙方和丙方,并协助丙方将乙方转至其他养老机构托养或送回住所;
+        </p>
+
+        <h2 class="section-title">第十三条&nbsp;&nbsp;争议解决方式</h2>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;本合同在履行过程中发生争议,当事人尽量协商解决。协商不成的,当事人可以选择下列第
+          <FieldItem v-model="contractForm.disputeMode" :is-text-mode="isTextMode" width="40px" placeholder="2" />
+          种方式解决:
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;☑ 1.向仲裁机构申请仲裁。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;☑ 2.向有管辖权的人民法院提起诉讼。
+        </p>
+      </div>
+    </div>
+
+    <!-- ========== 第23页:第十四条合同生效及附件 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">23</span>
+      </div>
+      <div class="page-content">
+        <h2 class="section-title">第十四条&nbsp;&nbsp;合同生效及附件</h2>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;本合同一式【
+          <FieldItem v-model="contractForm.copyCount" :is-text-mode="isTextMode" width="60px" placeholder="叁" />
+          】份,甲方执【
+          <FieldItem v-model="contractForm.partyACopy" :is-text-mode="isTextMode" width="40px" placeholder="壹" />
+          】份,乙方执【
+          <FieldItem v-model="contractForm.partyBCopy" :is-text-mode="isTextMode" width="40px" placeholder="壹" />
+          】份,乙方监护人执【
+          <FieldItem v-model="contractForm.partyCCopy" :is-text-mode="isTextMode" width="40px" placeholder="壹" />
+          】份,自各方签字或盖章之日起生效。
+        </p>
+
+        <p class="content-text" style="margin-top: 16px;">
+          &nbsp;&nbsp;&nbsp;&nbsp;1.下列文件为本合同附件,与本合同具有同等法律效力:
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          附件一:《知情同意书》
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          附件二:《入住登记表》
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          附件三:《入住须知》
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          附件四:《长者安全承诺书》
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          附件五:《长者外出情况确认书》
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          附件六:《签名代理申请》
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          附件七:《授权委托书》
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          附件八:《委托代理人确认表》
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          附件九:《机构服务范围及收费标准》
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          附件十:《房间设施设备清单》
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          附件十一:二级甲等以上医院出具的《体检报告项目说明》
+        </p>
+        <p class="content-text" style="padding-left: 3em; font-size: 13px;">
+          (体检时间应在签订服务合同前30日以内)
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          附件十二:乙方有效证件(身份证、户口本)复印件
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          附件十三:乙方监护人(丙方)身份证、户口本复印件
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          附件十四:甲方登记证书及民政部门备案回执
+        </p>
+      </div>
+    </div>
+
+    <!-- ========== 第24页:附件继续 + 签署页 ========== -->
+    <div class="a4-page">
+      <div class="page-header">
+        <div class="logo-line">
+          <span class="logo-circle">颐</span>
+          <span class="logo-text">颐年医养</span>
+        </div>
+        <span class="page-no-right">24</span>
+      </div>
+      <div class="page-content">
+        <p class="content-text" style="padding-left: 2em;">
+          附件十五:老年人能力综合评估结果
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          附件十六:首次服务项目确认表
+        </p>
+        <p class="content-text" style="padding-left: 2em;">
+          附件十七:变更事项确认表
+        </p>
+
+        <p class="content-text" style="margin-top: 12px;">
+          &nbsp;&nbsp;&nbsp;&nbsp;2.本合同附件系本合同不可分割的组成部分,与本合同具有同等法律效力。
+        </p>
+        <p class="content-text">
+          &nbsp;&nbsp;&nbsp;&nbsp;3.本合同附件是本合同的组成部分,与合同正文具有同等法律效力。
+        </p>
+
+        <p class="content-text" style="text-align: center; margin-top: 30px; font-size: 14px;">
+          (本文以下无正文,为合同签署页)
+        </p>
+
+        <div style="margin-top: 30px; font-size: 14px; line-height: 2.2;">
+          <p>
+            甲方(盖章):
+            <FieldItem v-model="contractForm.partyASign" :is-text-mode="isTextMode" width="260px" placeholder="(盖章处)" />
+          </p>
+          <p>
+            法定代表人(签字):
+            <SignatureItem :elder-id="props.recordRow.elderId" v-model="contractForm.partyALegalSign" :is-text-mode="isTextMode" width="260" height="80" placeholder="(签字处)" title="法定代表人签字" />
+          </p>
+          <p>
+            日期:
+            <FieldItem v-model="contractForm.partyADate" :is-text-mode="isTextMode" type="date" width="200px" placeholder="请选择日期" />
+          </p>
+          <p style="margin-top: 20px;">
+            乙方(签字):
+            <SignatureItem :elder-id="props.recordRow.elderId" v-model="contractForm.partyBSign" :is-text-mode="isTextMode" width="260" height="80" placeholder="(签字处)" title="乙方签字" />
+          </p>
+          <p>
+            日期:
+            <FieldItem v-model="contractForm.partyBDate" :is-text-mode="isTextMode" type="date" width="200px" placeholder="请选择日期" />
+          </p>
+          <p style="margin-top: 20px;">
+            丙方(签字/盖章):
+            <SignatureItem :elder-id="props.recordRow.elderId" v-model="contractForm.partyCSign" :is-text-mode="isTextMode" width="260" height="80" placeholder="(签字/盖章处)" title="丙方签字"  />
+          </p>
+          <p>
+            日期:
+            <FieldItem v-model="contractForm.partyCDate" :is-text-mode="isTextMode" type="date" width="200px" placeholder="请选择日期" />
+          </p>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.contract-body {
+  width: 100%;
+  padding: 0;
+  background: #f5f5f5;
+}
+
+.a4-page {
+  width: 210mm;
+  min-height: 297mm;
+  margin: 4mm auto;
+  padding: 10mm 14mm;
+  background: #fff;
+  box-shadow: 0 0 8px rgba(0, 0, 0, 0.12);
+  position: relative;
+  box-sizing: border-box;
+}
+
+.page-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding-bottom: 6px;
+  border-bottom: 1.5px solid #333;
+  margin-bottom: 16px;
+}
+
+.logo-line {
+  display: flex;
+  align-items: center;
+}
+
+.logo-circle {
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  width: 24px;
+  height: 24px;
+  border-radius: 50%;
+  background: #2b7c4e;
+  color: #fff;
+  font-size: 14px;
+  font-weight: bold;
+  margin-right: 8px;
+}
+
+.logo-text {
+  font-size: 16px;
+  font-weight: bold;
+  color: #333;
+}
+
+.page-no-right {
+  font-size: 12px;
+  color: #666;
+}
+
+.page-content {
+  font-size: 14px;
+  line-height: 1.9;
+  color: #333;
+}
+
+.cover-page {
+  text-align: center;
+  padding-top: 30mm;
+}
+
+.cover-fields {
+  text-align: left;
+  margin: 0 auto;
+  width: 100%;
+}
+
+.cover-fields .label {
+  display: inline-block;
+  min-width: 80px;
+  font-size: 14px;
+}
+
+.doc-title {
+  margin-top: 50mm;
+  font-size: 32px;
+  font-weight: bold;
+  letter-spacing: 4px;
+  color: #222;
+}
+
+.cover-issuer {
+  margin-top: 60mm;
+  font-size: 16px;
+  line-height: 2;
+  text-align: center;
+}
+
+.section-title {
+  font-size: 18px;
+  font-weight: bold;
+  text-align: center;
+  margin: 20px 0 14px 0;
+  color: #222;
+}
+
+.subsection-title {
+  font-size: 15px;
+  font-weight: bold;
+  margin: 12px 0 6px 0;
+  color: #222;
+}
+
+.content-text {
+  font-size: 14px;
+  line-height: 1.9;
+  margin: 4px 0;
+  text-indent: 0;
+  text-align: left;
+  color: #333;
+}
+
+@media print {
+  .contract-body {
+    background: #fff;
+    margin: 0;
+    padding: 0;
+    width: 100%;
+  }
+
+  .a4-page {
+    width: 100% !important;
+    min-height: auto !important;
+    height: auto !important;
+    margin: 0 !important;
+    padding: 10mm 14mm !important;
+    box-shadow: none !important;
+    page-break-after: always;
+    break-after: page;
+  }
+
+  .a4-page:last-child {
+    page-break-after: auto;
+    break-after: auto;
+  }
+
+  @page {
+    size: A4;
+    margin: 0;
+  }
+}
+</style>

+ 222 - 0
src/views/elderly/contracts/components/FieldItem.vue

@@ -0,0 +1,222 @@
+<script setup lang="ts">
+import { computed } from 'vue'
+import { DICT_TYPE, getIntDictOptions, getDictLabel } from '@/utils/dict'
+
+const props = defineProps<{
+  modelValue?: string | number
+  readOnly?: boolean
+  placeholder?: string
+  width?: string
+  isTextMode?: boolean
+  underlineWidth?: string
+  type?: 'text' | 'date' | 'datetime' | 'dict'
+  dictType?: string
+}>()
+
+const emit = defineEmits<{
+  (e: 'update:modelValue', val: any): void
+}>()
+
+const localValue = computed({
+  get: () => props.modelValue ?? '',
+  set: (val: any) => emit('update:modelValue', val)
+})
+
+const isDateType = computed(() => props.type === 'date' || props.type === 'datetime')
+const isDictType = computed(() => props.type === 'dict')
+
+const dictOptions = computed(() => {
+  if (!props.dictType) return []
+  return getIntDictOptions((DICT_TYPE as any)[props.dictType])
+})
+
+const dictLabel = computed(() => {
+  if (!props.dictType || localValue.value === '' || localValue.value == null) return ''
+  return getDictLabel((DICT_TYPE as any)[props.dictType], localValue.value)
+})
+
+const dateValue = computed({
+  get: () => {
+    if (!localValue.value) return ''
+    // 如果已经是 YYYY-MM-DD 或 YYYY-MM-DD HH:mm:ss 格式直接用
+    if (/^\d{4}-\d{2}-\d{2}/.test(localValue.value)) return localValue.value
+    // 如果是时间戳
+    const t = Number(localValue.value)
+    if (!Number.isNaN(t) && t > 0) {
+      const d = new Date(t)
+      const y = d.getFullYear()
+      const m = String(d.getMonth() + 1).padStart(2, '0')
+      const day = String(d.getDate()).padStart(2, '0')
+      return `${y}-${m}-${day}`
+    }
+    // 其他格式:尝试解析 "2024年01月01日" 或 "2024/01/01"
+    const m = localValue.value.match(/(\d{4})[年/\-.](\d{1,2})[月/\-.](\d{1,2})/)
+    if (m) {
+      return `${m[1]}-${m[2].padStart(2, '0')}-${m[3].padStart(2, '0')}`
+    }
+    return localValue.value
+  },
+  set: (val: any) => {
+    if (!val) {
+      emit('update:modelValue', '')
+      return
+    }
+    // value-format="YYYY-MM-DD" 时,val 是字符串格式
+    if (typeof val === 'string') {
+      const m = val.match(/^(\d{4})-(\d{2})-(\d{2})/)
+      if (m) {
+        emit('update:modelValue', `${m[1]}年${m[2]}月${m[3]}日`)
+        return
+      }
+    }
+    if (val instanceof Date) {
+      const y = val.getFullYear()
+      const m = String(val.getMonth() + 1).padStart(2, '0')
+      const day = String(val.getDate()).padStart(2, '0')
+      emit('update:modelValue', `${y}年${m}月${day}日`)
+    } else {
+      emit('update:modelValue', String(val))
+    }
+  }
+})
+</script>
+
+<template>
+  <span class="field-item" :class="{ 'is-text': isTextMode }">
+    <!-- 打印模式:统一显示下划线文本 -->
+    <template v-if="isTextMode">
+      <span v-if="isDictType ? dictLabel : localValue" class="fill-text">{{ isDictType ? dictLabel : localValue }}</span>
+      <span v-else class="fill-blank" :style="{ width: underlineWidth || width || '160px' }"></span>
+    </template>
+
+    <!-- 编辑模式:日期选择器 -->
+    <el-date-picker
+      v-else-if="isDateType"
+      v-model="dateValue"
+      :type="type"
+      :placeholder="placeholder || '请选择日期'"
+      :style="{ width: width || '180px' }"
+      :readonly="readOnly"
+      value-format="YYYY-MM-DD"
+      format="YYYY年MM月DD日"
+      class="field-date-picker"
+    />
+
+    <!-- 编辑模式:字典下拉选择 -->
+    <el-select
+      v-else-if="isDictType"
+      v-model="localValue"
+      :placeholder="placeholder || '请选择'"
+      :style="{ width: width || '160px' }"
+      :disabled="readOnly"
+      clearable
+      class="field-dict-select"
+    >
+      <el-option
+        v-for="(item, index) in dictOptions"
+        :key="index"
+        :label="item.label"
+        :value="item.value"
+      />
+    </el-select>
+
+    <!-- 编辑模式:普通文本输入框 -->
+    <input
+      v-else
+      v-model="localValue"
+      :placeholder="placeholder"
+      :readonly="readOnly"
+      :style="{ width: width || '160px' }"
+      class="text-input"
+    />
+  </span>
+</template>
+
+<style scoped lang="scss">
+.field-item {
+  display: inline-block;
+  vertical-align: middle;
+}
+
+.field-date-picker {
+  display: inline-block;
+  height: 28px;
+}
+
+.field-date-picker :deep(.el-input__wrapper) {
+  padding: 0 8px;
+  box-shadow: 0 0 0 1px #dcdfe6 inset;
+  border-radius: 4px;
+}
+
+.field-date-picker :deep(.el-input__wrapper:hover) {
+  box-shadow: 0 0 0 1px #409eff inset;
+}
+
+.field-date-picker :deep(.el-input__inner) {
+  height: 28px;
+  line-height: 28px;
+  font-size: 14px;
+}
+
+.field-dict-select {
+  display: inline-block;
+  height: 28px;
+}
+
+.field-dict-select :deep(.el-input__wrapper) {
+  padding: 0 8px;
+  box-shadow: 0 0 0 1px #dcdfe6 inset;
+  border-radius: 4px;
+}
+
+.field-dict-select :deep(.el-input__wrapper:hover) {
+  box-shadow: 0 0 0 1px #409eff inset;
+}
+
+.field-dict-select :deep(.el-input__inner) {
+  height: 28px;
+  line-height: 28px;
+  font-size: 14px;
+}
+
+.text-input {
+  border: 1px solid #dcdfe6;
+  border-radius: 4px;
+  padding: 2px 8px;
+  font-size: 14px;
+  outline: none;
+  height: 28px;
+  box-sizing: border-box;
+  background: #fff;
+
+  &:focus {
+    border-color: #409eff;
+  }
+
+  &[readonly] {
+    background: #f5f7fa;
+    cursor: not-allowed;
+  }
+}
+
+.is-text {
+  .fill-text {
+    display: inline-block;
+    border-bottom: 1px solid #333;
+    padding: 0 4px;
+    text-align: center;
+    min-width: 60px;
+    color: #333;
+    font-size: 14px;
+  }
+
+  .fill-blank {
+    display: inline-block;
+    border-bottom: 1px solid #333;
+    height: 1em;
+    vertical-align: middle;
+    margin: 0 2px;
+  }
+}
+</style>

+ 421 - 0
src/views/elderly/contracts/components/RiskDisclosureBody.vue

@@ -0,0 +1,421 @@
+<script setup lang="ts">
+import { reactive, watch, computed } from 'vue'
+import FieldItem from './FieldItem.vue'
+import SignatureItem from './SignatureItem.vue'
+
+interface FormData {
+  elderName?: string
+  companyName?: string
+  assessor?: string
+  assessDate?: string
+  partyBSign?: string
+  partyBDate?: string
+  partyCSign?: string
+  partyCDate?: string
+}
+
+const props = withDefaults(defineProps<{
+  isTextMode?: boolean
+  modelValue?: FormData
+}>(), {
+  isTextMode: false,
+  modelValue: () => ({})
+})
+
+const emit = defineEmits<{
+  (e: 'update:modelValue', val: FormData): void
+}>()
+
+const form = reactive<FormData>({
+  elderName: '',
+  companyName: '颐年医养',
+  assessor: '',
+  assessDate: '',
+  partyBSign: '',
+  partyBDate: '',
+  partyCSign: '',
+  partyCDate: ''
+})
+
+watch(
+  () => props.modelValue,
+  (val) => {
+    if (val) {
+      Object.assign(form, val)
+    }
+  },
+  { immediate: true, deep: true }
+)
+
+const updateForm = (key: keyof FormData, val: any) => {
+  (form as any)[key] = val
+  emit('update:modelValue', { ...form })
+}
+</script>
+
+<template>
+  <div class="risk-disclosure">
+    <!-- Page 1 -->
+    <div class="a4-page">
+      <div class="doc-header">
+        <div class="doc-logo">颐年医养</div>
+        <div class="doc-title">风险知情告知书</div>
+      </div>
+
+      <div class="doc-body">
+        <p class="intro">
+          为充分保障乙方(姓名
+          <FieldItem
+            :model-value="form.elderName"
+            :is-text-mode="isTextMode"
+            width="140px"
+            placeholder="长者姓名"
+            @update:model-value="(v: any) => updateForm('elderName', v)"
+          />
+          )的健康与安全,结合乙方年迈体弱之特点,甲方(公司名称:
+          <FieldItem
+            :model-value="form.companyName"
+            :is-text-mode="isTextMode"
+            width="260px"
+            placeholder="请填写公司名称"
+            @update:model-value="(v: any) => updateForm('companyName', v)"
+          />
+          )特向乙方、丙方告知以下事项,乙、丙两方须认真研读:
+        </p>
+
+        <h2 class="section-title">一、保护性约束风险</h2>
+        <p>
+          考虑到乙方年事已高,或受疾病、精神等因素影响,在入住甲方期间,有可能采取保护性约束措施,以避免其自伤或伤人情况的发生,保障乙方安全以及各项治疗护理工作的顺利开展。现将施行保护性约束措施的必要性及医疗风险告知如下:
+        </p>
+
+        <h3 class="sub-title">(一)必要性</h3>
+        <ol class="num-list">
+          <li>为保障治疗工作顺利推进;</li>
+          <li>避免乙方因精神方面的因素出现伤害自身或他人的情况;</li>
+          <li>防止乙方在意识不清时自行移除引流导尿管、鼻胃管等医疗设备;</li>
+          <li>防范乙方发生跌倒或坠床事件;</li>
+          <li>基于其他必要的因素。</li>
+        </ol>
+
+        <h3 class="sub-title">(二)医疗风险</h3>
+        <ol class="num-list">
+          <li>改变约束部位皮肤的完整性以及血液循环状况;</li>
+          <li>在使用约束背心或约束带时,因乙方躁动致使约束过紧,进而导致呼吸改变,存在发生窒息的风险;使用约束带时,若乙方有暴力倾向且不配合,可能引发骨折或其他伤害。</li>
+          <li>因乙方或丙方意外或有意解除约束带,可能导致各种管道及静脉通路脱出,或者致使乙方发生跌倒、坠床等意外伤害。</li>
+          <li>被约束肢体出现损伤。</li>
+          <li>存在其他医疗风险。</li>
+        </ol>
+
+        <h2 class="section-title">二、请假外出风险</h2>
+        <p>
+          协议履行期间甲方不建议乙方经常请假外出,若确需请假外出,乙方否则因此产生的一切风险后果由乙方、乙方监护人均需遵照本条款执行:
+        </p>
+        <ol class="num-list">
+          <li>严禁私自离院,及家属自行承担,甲方不承担任何责任。</li>
+          <li>有家属监护人/代理人陪同的,乙方应当向工作人员提出请假申请,工作人员为符合条件老人办理请假申请、审批手续。</li>
+          <li>无家属监护人/代理人陪同的,乙方需近三个月内MMSE评分为正常方可自行提出请假申请,工作人员评估其符合自行请假条件后为其办理请假、审批手续;若乙方近三个月内MMSE评分有异常,或经工作人员评估其不符合自行请假条件的,不予办理请假、审批手续;认知症老人一律不予办理自行单独请假、外出审批手续。</li>
+          <li>乙方经工作人员评估暂不适宜请假外出,或不符合在无家属、监护人陪同的自行请假条件,经与乙方、家属或监护人沟通,劝阻无果,乙方、监护人或家属仍坚持要求请假外出的,一切风险由乙方、监护人及家属自行承担。</li>
+          <li>凡当天不能返院,需在外留宿者,需在其离院24小时内致电所在护理区报平安。如需延长请假,需来电或来信说明原因。</li>
+          <li>外出时将请假假条交予门卫门岗,并配合门卫做好相关登记,以示外出。</li>
+          <li>携带乙方外出者,负责保障乙方外出期间的安全。</li>
+          <li>对于乙方请假期间在监护人、家属、代理人自行承担责任,甲方不承担任何责任。</li>
+          <li>乙方请假外出期间在甲方处以外所产生的住宿、伙食、交通、护理、救治等一切费用,均由乙方自行承担。</li>
+          <li>对于乙方请假外出,需自行解决往返交通。</li>
+          <li>其他相关请假外出规定。</li>
+        </ol>
+      </div>
+    </div>
+
+    <!-- Page 2 -->
+    <div class="a4-page">
+      <div class="doc-header">
+        <div class="doc-logo">颐年医养</div>
+      </div>
+
+      <div class="doc-body">
+        <h2 class="section-title">二、难免性压疮风险</h2>
+        <p>
+          鉴于乙方体质特殊,身体素质欠佳且营养吸收能力较弱,加之患病、皮肤抵抗力低下、大小便失禁以及长期使用石膏绷带和夹板等因素,在治疗与护理过程中极易引发压疮。因此,乙方在入住期间,将严格遵照甲方护理级别,采取定期翻身、清洁身体、避免潮湿、摩擦及排泄物刺激、促进局部血液循环、增加营养摄入等防范措施。乙方与丙方应配合甲方积极开展治疗。即便甲方积极采取相应措施,压疮仍有可能发生,乙方、丙方及其他亲属需对压疮风险予以知悉并理解。
+        </p>
+
+        <h2 class="section-title">三、跌倒坠床风险</h2>
+        <p>
+          鉴于老人年老体弱,在自行走动(活动)或卧床时易发生跌倒、坠床等意外情况。对于此类意外的发生,乙方及丙方应充分理解。同时,为减少跌倒/坠床情况的发生,特告知以下事项:
+        </p>
+        <ol class="num-list">
+          <li>存在跌倒、坠床风险的老人(包含:1. 肢体乏力、行动不便、步态不稳者;2. 身体较为虚弱、伴有头晕症状、患有贫血病症以及血压不稳定者;3. 存在精神或意识方面较差状况或存在意识障碍的人员;4. 使用麻醉类及精神类药物的人员;5. 高龄、视力不佳者严禁随意下床或跨越床栏。家属或陪护人员在陪伴老人期间,应及时拉起床栏;未经甲方工作人员同意,严禁随意放下栏,以防发生坠床事故。);</li>
+          <li>身体较为虚弱、伴有头晕症状、患有贫血病症以及血压不稳定者;</li>
+          <li>存在精神或意识方面较差状况或存在意识障碍的人员;</li>
+          <li>使用麻醉类及精神类药物的人员;</li>
+          <li>高龄、视力不佳者严禁随意下床或跨越床栏。家属或陪护人员在陪伴老人期间,应及时拉起床栏;未经甲方工作人员同意,严禁随意放下栏,以防发生坠床事故。</li>
+          <li>对于存在跌倒、坠床风险的老人,在外出进行检查时,必须由护理人员或陪护人员陪同,严禁自行行动。</li>
+          <li>当老人有变更体位进行活动的需求时,需遵循循序渐进的原则,在确认无异常情况之后,方可开始进行,以此避免因突然改变体位而导致跌倒。</li>
+          <li>老年人穿鞋脱袜及袜子,以此避免因突然改变体位而导致跌倒。</li>
+          <li>浴室已安装防滑地板,并配备扶手与座厕。如厕时,应自觉使用扶手。</li>
+          <li>行动不便者,需在他人陪护下进行起床、行走、活动、锻炼、沐浴或如厕等行为,并使用合适的助行用具或轮椅。同时,助行器应放置在老人易于取用之处。</li>
+          <li>老人床头及厕所均设置有呼叫器,老人需掌握呼叫器的使用方法。当在行走过程中突发状况的出现(下蹲、头发晕、下肢无力、行走不稳或无法移动等情况),应即刻在原地坐下(或靠墙站立),并按下呼叫器或大声呼喊以寻求帮助。</li>
+          <li>应时刻留意警示牌,避免行走于湿滑、有果皮、存在障碍物或凹凸不平的路面。若发现地面湿滑,需及时通知医护人员以消除安全隐患。</li>
+          <li>服用镇静类、催眠类、抗焦虑类、抗抑郁类、抗心律失常类、降压类、利尿类、降糖类等药物的老年人,严禁擅自离床或独自外出。</li>
+          <li>老年人应全面、客观地评估自身身体状况,及时向工作人员寻求协助,并认真听取工作人员提出的合理化建议。若从事超出自身能力范围的事务,以避免发生跌倒情况。若不慎发生跌倒或坠床,切勿急于起身;若身体受伤,应留在原地并大声呼救。</li>
+          <li>为防止此风险发生,乙方与丙方应遵循甲方工作人员的建议,将该情况告知其他家属、监护人及陪护人员。</li>
+        </ol>
+      </div>
+    </div>
+
+    <!-- Page 3 -->
+    <div class="a4-page">
+      <div class="doc-header">
+        <div class="doc-logo">颐年医养</div>
+      </div>
+
+      <div class="doc-body">
+        <h2 class="section-title">四、误吸噎食风险</h2>
+        <p>
+          鉴于老年人因年老体弱或罹患疾病等缘故,常出现吞咽反射迟缓或吞咽功能障碍的情况,易引发误吸、噎食现象。为降低此类情况的发生几率,现将相关危险因素及防范措施告知如下:
+        </p>
+
+        <h3 class="sub-title">(一)危险因素</h3>
+        <ol class="num-list">
+          <li>年龄因素:随着年龄的增加,老年人的口腔黏膜会逐渐萎缩变薄,神经末梢感受器的反射功能会逐渐迟钝,同时咽喉及食管的蠕动能力减弱,这些衰老性、退行性变化易致使老年人吞咽功能出现障碍,进而引发误吸、噎食。</li>
+          <li>相关疾病:老年人可能因罹患以下疾病而出现误吸情况:1)颅脑病变,例如颅内肿瘤、颅脑外伤、脑血管病变、脑干受损、颅内压升高、帕金森综合征、癫痫等;2)神经肌肉病变,如急性感染性神经炎、神经肌肉接头病变、多发性肌炎、多发性皮肌炎、重症肌无力等;3)咽喉及其邻近部位病损,例如咽喉部及邻近部位;4)咽喉部肿瘤、咽喉部及邻近部位;5)咽喉及头颈部手术、咽部及食管憩室、颈椎骨质增生等;6)呼吸功能不全,例如慢性阻塞性肺疾患、支气管哮喘等。3. 体位:老年患者的体位与误吸存在一定关联,长期卧床的老年人在进食或喂食时,若床头高度低于30°,会增加反流物及分泌物逆流的可能性,进而导致误吸。</li>
+          <li>进食方式:进食过程中速度过快、过于急切、食量过多等情况,均会增加误吸、噎食的几率。</li>
+          <li>留置胃管:鼻饲并发症包括误吸、黏膜损伤、便秘、胃潴留、水电解质血糖紊乱等。</li>
+        </ol>
+
+        <h3 class="sub-title">(二)防范措施</h3>
+        <ol class="num-list">
+          <li>若丙两方为乙方喂食,应选取质地柔软、密度与性状均匀、具备适当粘度、不易松散、湿润但无水分或汁液溢出的食物,例如米糊、菜泥、蛋羹等食物。同时,需留意食物温度适宜、色香味俱佳,以促进乙方食欲,引发吞咽反射。</li>
+          <li>乙方进食时应采取坐位或半坐卧位,对于卧床老人,至少应将床头抬高30°。进食后不宜立即躺下,需保持进食体位30分钟以上。</li>
+          <li>乙方在进食过程中,不宜进行交谈,需集中精力进食,以防发生呛咳。应细嚼慢咽,避免进食速度过快,每次进食量以一小口为宜,约为一茶匙或5毫升的分量。需待口腔内食物完全咽下后,方可进食第二口。饭后需用温水漱口,以清除口腔内的食物残渣。若进食时出现呛咳现象,应立即停止进食,鼓励乙方咳嗽,并轻叩其背部,促使食物颗粒咳出,以减少误吸情况的发生。</li>
+          <li>在日常生活中,乙方应增加咳嗽、咳痰方面的锻炼。平时需注重口腔卫生,进餐后应及时漱口;对于无法自行漱口、刷牙的乙方,应进行口腔护理。</li>
+          <li>经评估存在误吸风险且需留置胃管的老年人,需严格遵循医嘱口服。为规避此类风险,乙方及丙方应遵循甲方工作人员的建议,并将此情况告知其家属、监护人及陪护人员。</li>
+        </ol>
+
+        <h2 class="section-title">五、烫伤风险</h2>
+        <p>
+          鉴于老人存在年老体弱、行动不便、视力减退或存在障碍、感觉迟钝或存在障碍等情况,其发生烫伤的可能性较高。为降低烫伤发生的概率,现将以下事项告知如下:
+        </p>
+        <ol class="num-list">
+          <li>乙方或丙方不得独自接触热源,例如打开开水等行为。</li>
+          <li>未经甲方工作人员许可,严禁使用热水袋、理疗仪等易引发烫伤的发热设备。</li>
+          <li>乙方自行冲凉或丙方协助冲凉时,应先放冷水再放热水,且水温不得超过50℃。</li>
+          <li>乙方或丙方为老人准备食用的食物时,应确保温度适宜,以避免老人被烫伤。</li>
+        </ol>
+        <p>为防范此类风险,乙方及丙方应遵循甲方工作人员的建议,并将相关情况告知其他家属、监护人及陪护人员。</p>
+
+        <h2 class="section-title">六、食品药品误食风险</h2>
+        <p>
+          鉴于乙方存在罹患疾病、知识储备不足、安全意识淡薄等情况,易出现误食食品药品的现象。为降低此类风险,特作如下告知:乙方应配合甲方定期对食品、药品进行检查,一旦发现异常需及时处理,避免使用过期、变质的食品、药品。
+        </p>
+        <ol class="num-list">
+          <li>丙方不得携带不适宜乙方食用或服用的食品和药品。</li>
+          <li>若乙方存在记忆力差、认知功能减退、视力异常等情形,则不适合自行准备和服用药物。关于乙方服药事宜,应与甲方工作人员进行沟通协商。丙方不得擅自让乙方自行保管药物及服药,乙方和丙方应当遵守甲方的自备药管理规定。为避免此类风险的发生,乙方和丙方应听取甲方工作人员的建议,并将此类情况告知其他家</li>
+        </ol>
+      </div>
+    </div>
+
+    <!-- Page 4 - Signatures -->
+    <div class="a4-page">
+      <div class="doc-body">
+        <div style="margin-top: 60px; font-size: 14px; line-height: 2.4;">
+          <p style="margin-bottom: 30px;">
+            本人(乙方及丙方)已仔细阅读并充分理解以上告知事项的全部内容,对上述风险已有清楚的认知。本人自愿选择入住甲方,并承诺在入住期间严格遵守甲方的相关规章制度。乙方及丙方确认:在甲方工作人员已就上述风险向本人进行了充分的告知和解释,本人已完全知悉并理解上述风险的内容及可能产生的后果。</p>
+          <p style="margin-bottom: 30px;">
+            乙方及丙方同意:如因乙方或丙方的原因(包括但不限于违反告知书的相关规定、未遵守甲方管理规定、未听从甲方工作人员的合理建议等)导致发生意外情况,乙方及丙方自愿承担相应风险及后果,与甲方无关。</p>
+          <p style="margin-bottom: 40px;">
+            本告知书自各方签字之日起生效。</p>
+        </div>
+
+        <div class="signatures" style="margin-top: 80px; font-size: 14px;">
+          <div class="signature-group">
+            <p>乙方(签字):
+              <SignatureItem
+                :model-value="form.partyBSign"
+                :is-text-mode="isTextMode"
+                width="200"
+                height="80"
+                placeholder="(签字处)"
+                title="乙方签字"
+                @update:model-value="(v: any) => updateForm('partyBSign', v)"
+              />
+            </p>
+            <p>日期:
+              <FieldItem
+                :model-value="form.partyBDate"
+                :is-text-mode="isTextMode"
+                type="date"
+                width="200px"
+                placeholder="请选择日期"
+                @update:model-value="(v: any) => updateForm('partyBDate', v)"
+              />
+            </p>
+          </div>
+
+          <div class="signature-group">
+            <p>丙方(签字/盖章):
+              <SignatureItem
+                :model-value="form.partyCSign"
+                :is-text-mode="isTextMode"
+                width="200"
+                height="80"
+                placeholder="(签字/盖章处)"
+                title="丙方签字"
+                @update:model-value="(v: any) => updateForm('partyCSign', v)"
+              />
+            </p>
+            <p>日期:
+              <FieldItem
+                :model-value="form.partyCDate"
+                :is-text-mode="isTextMode"
+                type="date"
+                width="200px"
+                placeholder="请选择日期"
+                @update:model-value="(v: any) => updateForm('partyCDate', v)"
+              />
+            </p>
+          </div>
+
+          <div class="signature-group">
+            <p>记录人(签字):
+              <FieldItem
+                :model-value="form.assessor"
+                :is-text-mode="isTextMode"
+                width="200px"
+                placeholder="请填写记录人"
+                @update:model-value="(v: any) => updateForm('assessor', v)"
+              />
+            </p>
+            <p>记录日期:
+              <FieldItem
+                :model-value="form.assessDate"
+                :is-text-mode="isTextMode"
+                type="date"
+                width="200px"
+                placeholder="请选择日期"
+                @update:model-value="(v: any) => updateForm('assessDate', v)"
+              />
+            </p>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<style scoped lang="scss">
+.risk-disclosure {
+  width: 100%;
+}
+
+.a4-page {
+  width: 210mm;
+  min-height: 297mm;
+  margin: 0 auto 20px;
+  padding: 20mm 18mm;
+  background: #fff;
+  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+  box-sizing: border-box;
+}
+
+.doc-header {
+  text-align: center;
+  margin-bottom: 24px;
+  padding-bottom: 16px;
+  border-bottom: 2px solid #333;
+}
+
+.doc-logo {
+  font-size: 16px;
+  font-weight: 700;
+  color: #000;
+  letter-spacing: 3px;
+  margin-bottom: 12px;
+}
+
+.doc-title {
+  font-size: 22px;
+  font-weight: 700;
+  color: #000;
+  letter-spacing: 4px;
+}
+
+.doc-body {
+  font-size: 14px;
+  line-height: 1.9;
+  color: #222;
+  text-align: justify;
+}
+
+.intro {
+  font-size: 14px;
+  line-height: 1.9;
+  text-indent: 0;
+  margin-bottom: 18px;
+}
+
+.section-title {
+  font-size: 16px;
+  font-weight: 700;
+  color: #000;
+  margin: 24px 0 10px;
+  text-align: center;
+}
+
+.sub-title {
+  font-size: 15px;
+  font-weight: 600;
+  color: #000;
+  margin: 14px 0 6px;
+  padding-left: 0;
+}
+
+.num-list {
+  list-style: decimal;
+  padding-left: 26px;
+  margin: 6px 0;
+}
+
+.num-list li {
+  margin-bottom: 5px;
+  line-height: 1.9;
+  text-align: justify;
+}
+
+.signatures {
+  margin-top: 40px;
+  padding-top: 30px;
+  border-top: 1px solid #999;
+}
+
+.signature-group {
+  margin-bottom: 30px;
+}
+
+.signature-group p {
+  margin-bottom: 10px;
+}
+
+@media print {
+  .a4-page {
+    width: 100% !important;
+    min-height: auto !important;
+    margin: 0 !important;
+    padding: 15mm 15mm !important;
+    box-shadow: none !important;
+    page-break-after: always;
+    break-after: page;
+  }
+  .a4-page:last-child {
+    page-break-after: auto;
+    break-after: auto;
+  }
+  @page {
+    size: A4;
+    margin: 0;
+  }
+  body {
+    margin: 0;
+    padding: 0;
+  }
+}
+</style>

+ 642 - 0
src/views/elderly/contracts/components/SignPad.vue

@@ -0,0 +1,642 @@
+<script setup lang="ts">
+import { ref, onMounted, onBeforeUnmount, watch, nextTick } from 'vue'
+import { getFamilyMemberSign } from '@/api/elderly/common'
+import { ElMessage } from 'element-plus'
+
+interface StrokePoint {
+  x: number
+  y: number
+}
+
+interface Stroke {
+  points: StrokePoint[]
+}
+
+interface SignPadProps {
+  modelValue?: string
+  title?: string
+  width?: number
+  height?: number
+  elderId?: number | string
+}
+
+const props = withDefaults(defineProps<SignPadProps>(), {
+  modelValue: '',
+  title: '请签字',
+  width: 600,
+  height: 260,
+  elderId: ''
+})
+
+const emit = defineEmits<{
+  (e: 'update:modelValue', val: string): void
+  (e: 'confirm', val: string): void
+  (e: 'cancel'): void
+}>()
+
+const visible = ref(false)
+const canvasRef = ref<HTMLCanvasElement | null>(null)
+const previewRef = ref<HTMLCanvasElement | null>(null)
+const isDrawing = ref(false)
+const strokes = ref<Stroke[]>([])
+const currentStroke = ref<Stroke>({ points: [] })
+const hasContent = ref(false)
+const loadingApi = ref(false)
+const apiFamilyList = ref<any[]>([])
+const selectedFamilyId = ref<string>('')
+const activeTab = ref<'draw' | 'family'>('draw')
+// 选中家属签名时,可能是图片格式,直接保存原始值
+const selectedRawSign = ref<string>('')
+
+let ctx: CanvasRenderingContext2D | null = null
+
+// ============ 格式检测 ============
+const detectSignFormat = (data: string): 'vector' | 'image' | 'empty' => {
+  if (!data) return 'empty'
+  if (data.startsWith('data:image')) return 'image'
+  try {
+    const jsonStr = decodeURIComponent(escape(atob(data)))
+    const parsed = JSON.parse(jsonStr)
+    if (Array.isArray(parsed) && parsed.length > 0) return 'vector'
+  } catch (e) {
+    // fallback
+  }
+  if (data.length > 100) return 'image'
+  return 'empty'
+}
+
+// ============ 矢量编解码 ============
+const vectorToBase64 = (strokeList: Stroke[]): string => {
+  const simpleData = strokeList.map((s) => s.points.map((p) => [Math.round(p.x), Math.round(p.y)]))
+  const jsonStr = JSON.stringify(simpleData)
+  return btoa(unescape(encodeURIComponent(jsonStr)))
+}
+
+const base64ToVector = (b64: string): Stroke[] => {
+  try {
+    const jsonStr = decodeURIComponent(escape(atob(b64)))
+    const parsed = JSON.parse(jsonStr)
+    if (!Array.isArray(parsed)) return []
+    return parsed.map((strokeArr: number[][]) => ({
+      points: strokeArr.map(([x, y]) => ({ x, y }))
+    }))
+  } catch (e) {
+    return []
+  }
+}
+
+// ============ Canvas渲染 ============
+const renderVectorToCanvas = (canvas: HTMLCanvasElement, b64: string) => {
+  const c = canvas.getContext('2d')
+  if (!c) return
+  c.clearRect(0, 0, canvas.width, canvas.height)
+  c.fillStyle = '#ffffff'
+  c.fillRect(0, 0, canvas.width, canvas.height)
+  if (!b64) return
+  const vStrokes = base64ToVector(b64)
+  if (vStrokes.length === 0) return
+
+  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity
+  vStrokes.forEach((s) => {
+    s.points.forEach((p) => {
+      if (p.x < minX) minX = p.x
+      if (p.y < minY) minY = p.y
+      if (p.x > maxX) maxX = p.x
+      if (p.y > maxY) maxY = p.y
+    })
+  })
+
+  const contentWidth = maxX - minX || 1
+  const contentHeight = maxY - minY || 1
+  const padding = 8
+  const scaleX = (canvas.width - padding * 2) / contentWidth
+  const scaleY = (canvas.height - padding * 2) / contentHeight
+  const scale = Math.min(scaleX, scaleY, 2)
+  const offsetX = padding + (canvas.width - padding * 2 - contentWidth * scale) / 2 - minX * scale
+  const offsetY = padding + (canvas.height - padding * 2 - contentHeight * scale) / 2 - minY * scale
+
+  c.strokeStyle = '#000000'
+  c.lineWidth = 2
+  c.lineCap = 'round'
+  c.lineJoin = 'round'
+
+  vStrokes.forEach((stroke) => {
+    if (stroke.points.length < 2) return
+    c.beginPath()
+    c.moveTo(stroke.points[0].x * scale + offsetX, stroke.points[0].y * scale + offsetY)
+    for (let i = 1; i < stroke.points.length; i++) {
+      c.lineTo(stroke.points[i].x * scale + offsetX, stroke.points[i].y * scale + offsetY)
+    }
+    c.stroke()
+  })
+}
+
+const renderImageToCanvas = (canvas: HTMLCanvasElement, src: string) => {
+  const c = canvas.getContext('2d')
+  if (!c) return
+  const img = new Image()
+  img.onload = () => {
+    c.clearRect(0, 0, canvas.width, canvas.height)
+    c.fillStyle = '#ffffff'
+    c.fillRect(0, 0, canvas.width, canvas.height)
+    const scale = Math.min(canvas.width / img.width, canvas.height / img.height)
+    const w = img.width * scale
+    const h = img.height * scale
+    const x = (canvas.width - w) / 2
+    const y = (canvas.height - h) / 2
+    c.drawImage(img, x, y, w, h)
+  }
+  img.src = src.startsWith('data:') ? src : `data:image/png;base64,${src}`
+}
+
+// 渲染签名到canvas(自动判断格式)
+const renderSignToCanvas = (canvas: HTMLCanvasElement, signData: string) => {
+  const fmt = detectSignFormat(signData)
+  if (fmt === 'vector') {
+    renderVectorToCanvas(canvas, signData)
+  } else if (fmt === 'image') {
+    renderImageToCanvas(canvas, signData)
+  }
+}
+
+// 家属签名预览渲染
+const renderFamilyPreview = (canvas: HTMLCanvasElement, id: string | number) => {
+  const item = apiFamilyList.value.find((i) => String(i.id) === String(id))
+  if (!item || !item.sign) return
+  renderSignToCanvas(canvas, item.sign)
+}
+
+const setFamilyPreviewRef = (el: any, id: string | number) => {
+  if (el) {
+    renderFamilyPreview(el, id)
+  }
+}
+
+// ============ 手写画板 ============
+const redrawCanvas = () => {
+  if (!ctx || !canvasRef.value) return
+  const canvas = canvasRef.value
+  ctx.clearRect(0, 0, canvas.width, canvas.height)
+  ctx.fillStyle = '#ffffff'
+  ctx.fillRect(0, 0, canvas.width, canvas.height)
+  ctx.strokeStyle = '#000000'
+  ctx.lineWidth = 2.2
+  ctx.lineCap = 'round'
+  ctx.lineJoin = 'round'
+
+  const allStrokes = [...strokes.value, currentStroke.value]
+  allStrokes.forEach((stroke) => {
+    if (!stroke.points || stroke.points.length < 2) return
+    ctx!.beginPath()
+    ctx!.moveTo(stroke.points[0].x, stroke.points[0].y)
+    for (let i = 1; i < stroke.points.length; i++) {
+      ctx!.lineTo(stroke.points[i].x, stroke.points[i].y)
+    }
+    ctx!.stroke()
+  })
+}
+
+const getCanvasPosition = (e: MouseEvent | TouchEvent): StrokePoint => {
+  const canvas = canvasRef.value!
+  const rect = canvas.getBoundingClientRect()
+  const scaleX = canvas.width / rect.width
+  const scaleY = canvas.height / rect.height
+  let clientX = 0
+  let clientY = 0
+  if ('touches' in e) {
+    clientX = e.touches[0].clientX
+    clientY = e.touches[0].clientY
+  } else {
+    clientX = (e as MouseEvent).clientX
+    clientY = (e as MouseEvent).clientY
+  }
+  return { x: (clientX - rect.left) * scaleX, y: (clientY - rect.top) * scaleY }
+}
+
+const handleMouseDown = (e: MouseEvent | TouchEvent) => {
+  if (activeTab.value !== 'draw') return
+  e.preventDefault()
+  isDrawing.value = true
+  currentStroke.value = { points: [getCanvasPosition(e)] }
+}
+
+const handleMouseMove = (e: MouseEvent | TouchEvent) => {
+  if (!isDrawing.value) return
+  e.preventDefault()
+  currentStroke.value.points.push(getCanvasPosition(e))
+  redrawCanvas()
+}
+
+const handleMouseUp = () => {
+  if (!isDrawing.value) return
+  isDrawing.value = false
+  if (currentStroke.value.points.length >= 2) {
+    strokes.value.push({ ...currentStroke.value, points: [...currentStroke.value.points] })
+    hasContent.value = true
+  }
+  currentStroke.value = { points: [] }
+  redrawCanvas()
+}
+
+const clearCanvas = () => {
+  strokes.value = []
+  currentStroke.value = { points: [] }
+  hasContent.value = false
+  selectedFamilyId.value = ''
+  selectedRawSign.value = ''
+  if (activeTab.value === 'draw') {
+    redrawCanvas()
+  }
+}
+
+// ============ 弹窗控制 ============
+const initCanvas = () => {
+  if (!canvasRef.value) return
+  ctx = canvasRef.value.getContext('2d')
+}
+
+const open = async (existingValue?: string) => {
+  visible.value = true
+  loadingApi.value = false
+  apiFamilyList.value = []
+  selectedFamilyId.value = ''
+  selectedRawSign.value = ''
+  activeTab.value = 'draw'
+  await nextTick()
+  initCanvas()
+  const val = existingValue ?? props.modelValue
+  if (val) {
+    const fmt = detectSignFormat(val)
+    if (fmt === 'vector') {
+      strokes.value = base64ToVector(val)
+      hasContent.value = strokes.value.length > 0
+    } else {
+      strokes.value = []
+      hasContent.value = false
+    }
+  } else {
+    strokes.value = []
+    hasContent.value = false
+  }
+  redrawCanvas()
+}
+
+const confirmSign = () => {
+  if (!hasContent.value) {
+    ElMessage.warning('请先完成签字')
+    return
+  }
+
+  let result = ''
+  if (activeTab.value === 'family' && selectedRawSign.value) {
+    // 家属签名:直接使用原始值(可能是图片base64或矢量base64)
+    result = selectedRawSign.value
+  } else if (strokes.value.length > 0) {
+    // 手写签字:矢量编码
+    result = vectorToBase64(strokes.value)
+  }
+
+  if (!result) {
+    ElMessage.warning('请先完成签字')
+    return
+  }
+
+  emit('update:modelValue', result)
+  emit('confirm', result)
+  visible.value = false
+}
+
+const cancelSign = () => {
+  emit('cancel')
+  visible.value = false
+}
+
+// ============ 家属签名 ============
+const loadFamilySignFromApi = async () => {
+  if (!props.elderId) {
+    ElMessage.warning('缺少长者信息,无法读取家属签名')
+    return
+  }
+  loadingApi.value = true
+  try {
+    const res: any = await getFamilyMemberSign(props.elderId)
+    if (res && res.data) {
+      apiFamilyList.value = Array.isArray(res.data) ? res.data : []
+      if (apiFamilyList.value.length === 0) {
+        ElMessage.info('暂无家属签名数据')
+      }
+    }
+  } catch (e) {
+    console.error('读取家属签名失败', e)
+    ElMessage.error('读取家属签名失败')
+  } finally {
+    loadingApi.value = false
+  }
+}
+
+const selectFamilySign = (item: any) => {
+  if (!item || !item.sign) return
+  selectedFamilyId.value = String(item.id)
+  selectedRawSign.value = item.sign
+  hasContent.value = true
+
+  // 如果是矢量格式,也同步到strokes(用于预览)
+  const fmt = detectSignFormat(item.sign)
+  if (fmt === 'vector') {
+    strokes.value = base64ToVector(item.sign)
+  } else {
+    strokes.value = []
+  }
+
+  // 渲染预览
+  nextTick(() => {
+    if (previewRef.value) {
+      renderSignToCanvas(previewRef.value, item.sign)
+    }
+  })
+}
+
+const handleTabChange = (tab: 'draw' | 'family') => {
+  activeTab.value = tab
+  // 切换tab时不清除已选内容,但需要重新初始化canvas
+  nextTick(() => {
+    if (tab === 'draw') {
+      initCanvas()
+      redrawCanvas()
+    } else if (tab === 'family' && apiFamilyList.value.length === 0) {
+      // 自动加载家属签名
+      loadFamilySignFromApi()
+    }
+  })
+}
+
+watch(visible, (val) => {
+  if (val) {
+    document.body.style.overflow = 'hidden'
+  } else {
+    document.body.style.overflow = ''
+  }
+})
+
+onMounted(() => {
+  window.addEventListener('mouseup', handleMouseUp)
+  window.addEventListener('touchend', handleMouseUp)
+})
+
+onBeforeUnmount(() => {
+  window.removeEventListener('mouseup', handleMouseUp)
+  window.removeEventListener('touchend', handleMouseUp)
+})
+
+defineExpose({ open })
+</script>
+
+<template>
+  <Teleport to="body">
+    <div v-if="visible" class="sign-pad-mask" @click.self="cancelSign">
+      <div class="sign-pad-dialog">
+        <div class="sign-pad-header">
+          <span class="sign-pad-title">{{ title }}</span>
+          <span class="sign-pad-close" @click="cancelSign">×</span>
+        </div>
+
+        <!-- Tab切换:始终显示 -->
+        <div class="sign-pad-tabs">
+          <div
+            class="sign-pad-tab"
+            :class="{ active: activeTab === 'draw' }"
+            @click="handleTabChange('draw')"
+          >手写签字</div>
+          <div
+            class="sign-pad-tab"
+            :class="{ active: activeTab === 'family' }"
+            @click="handleTabChange('family')"
+          >读取签名</div>
+        </div>
+
+        <div class="sign-pad-body">
+          <!-- 手写签字 -->
+          <template v-if="activeTab === 'draw'">
+            <div class="sign-pad-canvas-wrap">
+              <canvas
+                ref="canvasRef"
+                :width="width"
+                :height="height"
+                class="sign-pad-canvas"
+                @mousedown="handleMouseDown"
+                @mousemove="handleMouseMove"
+                @touchstart="handleMouseDown"
+                @touchmove="handleMouseMove"
+              ></canvas>
+            </div>
+          </template>
+
+          <!-- 读取家属签名 -->
+          <div v-if="activeTab === 'family'" class="sign-pad-family">
+            <div v-if="apiFamilyList.length === 0" class="sign-pad-empty">
+              <el-button type="primary" :loading="loadingApi" @click="loadFamilySignFromApi">
+                {{ loadingApi ? '加载中...' : '点击加载家属签名' }}
+              </el-button>
+            </div>
+            <div v-else class="sign-pad-family-list">
+              <div
+                class="sign-pad-family-item"
+                v-for="item in apiFamilyList"
+                :key="item.id"
+                :class="{ selected: selectedFamilyId === String(item.id) }"
+                @click="selectFamilySign(item)"
+              >
+                <div class="sign-pad-family-name">{{ item.name || '家属' }}</div>
+                <div class="sign-pad-family-sign">
+                  <canvas
+                    :ref="(el: any) => setFamilyPreviewRef(el, item.id)"
+                    :width="200"
+                    :height="80"
+                    class="sign-pad-family-preview"
+                  ></canvas>
+                </div>
+              </div>
+            </div>
+
+            <!-- 已选签名预览 -->
+            <div v-if="hasContent && selectedFamilyId" class="sign-pad-family-preview-label">已选签名预览</div>
+            <div class="sign-pad-canvas-wrap" v-if="hasContent && selectedFamilyId">
+              <canvas
+                ref="previewRef"
+                :width="width"
+                :height="height"
+                class="sign-pad-canvas"
+                style="pointer-events: none; background: #fff;"
+              ></canvas>
+            </div>
+          </div>
+        </div>
+
+        <div class="sign-pad-footer">
+          <el-button @click="clearCanvas">清空</el-button>
+          <el-button type="primary" :disabled="!hasContent" @click="confirmSign">确认签字</el-button>
+          <el-button @click="cancelSign">取消</el-button>
+        </div>
+      </div>
+    </div>
+  </Teleport>
+</template>
+
+<style scoped lang="scss">
+.sign-pad-mask {
+  position: fixed;
+  inset: 0;
+  background: rgba(0, 0, 0, 0.45);
+  z-index: 3000;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.sign-pad-dialog {
+  background: #fff;
+  border-radius: 8px;
+  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15);
+  width: 640px;
+  max-width: 95vw;
+  display: flex;
+  flex-direction: column;
+  overflow: hidden;
+}
+
+.sign-pad-header {
+  padding: 14px 20px;
+  border-bottom: 1px solid #eee;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+
+  .sign-pad-title {
+    font-size: 16px;
+    font-weight: 600;
+    color: #303133;
+  }
+
+  .sign-pad-close {
+    font-size: 24px;
+    cursor: pointer;
+    color: #909399;
+    line-height: 1;
+    user-select: none;
+
+    &:hover {
+      color: #303133;
+    }
+  }
+}
+
+.sign-pad-tabs {
+  display: flex;
+  border-bottom: 1px solid #e4e7ed;
+  background: #fafafa;
+
+  .sign-pad-tab {
+    flex: 1;
+    padding: 12px 20px;
+    text-align: center;
+    cursor: pointer;
+    font-size: 14px;
+    color: #606266;
+    transition: all 0.2s;
+
+    &.active {
+      color: #409eff;
+      font-weight: 500;
+      border-bottom: 2px solid #409eff;
+      background: #fff;
+    }
+
+    &:hover:not(.active) {
+      color: #409eff;
+      background: #f2f6fc;
+    }
+  }
+}
+
+.sign-pad-body {
+  padding: 20px;
+}
+
+.sign-pad-canvas-wrap {
+  border: 2px dashed #dcdfe6;
+  border-radius: 6px;
+  overflow: hidden;
+  background: #fff;
+
+  &:hover {
+    border-color: #c0c4cc;
+  }
+}
+
+.sign-pad-canvas {
+  display: block;
+  width: 100%;
+  height: auto;
+  cursor: crosshair;
+  touch-action: none;
+}
+
+.sign-pad-family {
+   height: 260px;
+  .sign-pad-empty {
+    text-align: center;
+    padding: 40px 0;
+  }
+
+  .sign-pad-family-list {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 14px;
+  }
+
+  .sign-pad-family-item {
+    border: 1px solid #dcdfe6;
+    border-radius: 6px;
+    padding: 12px;
+    cursor: pointer;
+    min-width: 200px;
+    background: #fafafa;
+
+    &:hover {
+      border-color: #409eff;
+      background: #f2f6fc;
+    }
+
+    &.selected {
+      border-color: #409eff;
+      background: #ecf5ff;
+    }
+  }
+
+  .sign-pad-family-name {
+    font-size: 14px;
+    color: #303133;
+    margin-bottom: 8px;
+  }
+
+  .sign-pad-family-preview {
+    display: block;
+    background: #fff;
+  }
+
+  .sign-pad-family-preview-label {
+    text-align: center;
+    margin: 16px 0 8px;
+    font-size: 13px;
+    color: #606266;
+  }
+}
+
+.sign-pad-footer {
+  padding: 14px 20px;
+  border-top: 1px solid #eee;
+  display: flex;
+  justify-content: center;
+  gap: 12px;
+}
+</style>

+ 279 - 0
src/views/elderly/contracts/components/SignatureItem.vue

@@ -0,0 +1,279 @@
+<script setup lang="ts">
+import { ref, onMounted, watch, nextTick, computed, onUpdated } from 'vue'
+import SignPad from './SignPad.vue'
+
+interface SignatureItemProps {
+  modelValue?: string
+  isTextMode?: boolean
+  title?: string
+  width?: number
+  height?: number
+  placeholder?: string
+  elderId?: number | string
+}
+
+const props = withDefaults(defineProps<SignatureItemProps>(), {
+  modelValue: '',
+  isTextMode: false,
+  title: '请签字',
+  width: 260,
+  height: 80,
+  placeholder: '(签字处)',
+  elderId: ''
+})
+
+const emit = defineEmits<{
+  (e: 'update:modelValue', val: string): void
+}>()
+
+const signPadRef = ref<InstanceType<typeof SignPad> | null>(null)
+const textCanvasRef = ref<HTMLCanvasElement | null>(null)
+const editCanvasRef = ref<HTMLCanvasElement | null>(null)
+
+interface StrokePoint {
+  x: number
+  y: number
+}
+
+interface Stroke {
+  points: StrokePoint[]
+}
+
+const detectSignFormat = (data: string): 'vector' | 'image' | 'empty' => {
+  if (!data) return 'empty'
+  if (data.startsWith('data:image')) return 'image'
+  try {
+    const jsonStr = decodeURIComponent(escape(atob(data)))
+    const parsed = JSON.parse(jsonStr)
+    if (Array.isArray(parsed) && parsed.length > 0) return 'vector'
+  } catch (e) {
+    // fallback
+  }
+  if (data.length > 100) return 'image'
+  return 'empty'
+}
+
+const signFormat = computed(() => detectSignFormat(props.modelValue))
+
+const base64ToVector = (b64: string): Stroke[] => {
+  try {
+    const jsonStr = decodeURIComponent(escape(atob(b64)))
+    const parsed = JSON.parse(jsonStr)
+    if (!Array.isArray(parsed)) return []
+    return parsed.map((strokeArr: number[][]) => ({
+      points: strokeArr.map(([x, y]) => ({ x, y }))
+    }))
+  } catch (e) {
+    return []
+  }
+}
+
+const renderVectorToCanvas = (canvas: HTMLCanvasElement, b64: string) => {
+  const ctx = canvas.getContext('2d')
+  if (!ctx) return
+  ctx.clearRect(0, 0, canvas.width, canvas.height)
+  ctx.fillStyle = '#ffffff'
+  ctx.fillRect(0, 0, canvas.width, canvas.height)
+  if (!b64) return
+  const strokes = base64ToVector(b64)
+  if (strokes.length === 0) return
+
+  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity
+  strokes.forEach((s) => {
+    s.points.forEach((p) => {
+      if (p.x < minX) minX = p.x
+      if (p.y < minY) minY = p.y
+      if (p.x > maxX) maxX = p.x
+      if (p.y > maxY) maxY = p.y
+    })
+  })
+
+  const contentWidth = maxX - minX || 1
+  const contentHeight = maxY - minY || 1
+  const padding = 8
+  const scaleX = (canvas.width - padding * 2) / contentWidth
+  const scaleY = (canvas.height - padding * 2) / contentHeight
+  const scale = Math.min(scaleX, scaleY, 2)
+  const offsetX = padding + (canvas.width - padding * 2 - contentWidth * scale) / 2 - minX * scale
+  const offsetY = padding + (canvas.height - padding * 2 - contentHeight * scale) / 2 - minY * scale
+
+  ctx.strokeStyle = '#000000'
+  ctx.lineWidth = 2
+  ctx.lineCap = 'round'
+  ctx.lineJoin = 'round'
+
+  strokes.forEach((stroke) => {
+    if (stroke.points.length < 2) return
+    ctx.beginPath()
+    ctx.moveTo(stroke.points[0].x * scale + offsetX, stroke.points[0].y * scale + offsetY)
+    for (let i = 1; i < stroke.points.length; i++) {
+      ctx.lineTo(stroke.points[i].x * scale + offsetX, stroke.points[i].y * scale + offsetY)
+    }
+    ctx.stroke()
+  })
+}
+
+const renderImageToCanvas = (canvas: HTMLCanvasElement, src: string) => {
+  const ctx = canvas.getContext('2d')
+  if (!ctx) return
+  const img = new Image()
+  img.onload = () => {
+    ctx.clearRect(0, 0, canvas.width, canvas.height)
+    ctx.fillStyle = '#ffffff'
+    ctx.fillRect(0, 0, canvas.width, canvas.height)
+    const scale = Math.min(canvas.width / img.width, canvas.height / img.height)
+    const w = img.width * scale
+    const h = img.height * scale
+    const x = (canvas.width - w) / 2
+    const y = (canvas.height - h) / 2
+    ctx.drawImage(img, x, y, w, h)
+  }
+  img.src = src.startsWith('data:') ? src : `data:image/png;base64,${src}`
+}
+
+const resolvedImageSrc = computed(() => {
+  if (signFormat.value !== 'image') return ''
+  const val = props.modelValue
+  if (!val) return ''
+  return val.startsWith('data:') ? val : `data:image/png;base64,${val}`
+})
+
+const hasSignature = computed(() => signFormat.value !== 'empty')
+
+const openSignPad = () => {
+  signPadRef.value?.open(props.modelValue)
+}
+
+const handleSignConfirm = (b64: string) => {
+  emit('update:modelValue', b64)
+}
+
+const renderAll = async () => {
+  await nextTick()
+  const fmt = signFormat.value
+  if (fmt === 'vector') {
+    if (textCanvasRef.value) renderVectorToCanvas(textCanvasRef.value, props.modelValue)
+    if (editCanvasRef.value) renderVectorToCanvas(editCanvasRef.value, props.modelValue)
+  } else if (fmt === 'image') {
+    if (textCanvasRef.value) renderImageToCanvas(textCanvasRef.value, props.modelValue)
+    if (editCanvasRef.value) renderImageToCanvas(editCanvasRef.value, props.modelValue)
+  }
+  console.log("props.modelValue",props.modelValue)
+}
+
+watch(
+  () => [props.modelValue, props.isTextMode],
+  async () => {
+    await renderAll()
+  },
+  { immediate: true, deep: true }
+)
+
+onMounted(async () => {
+  await renderAll()
+})
+
+onUpdated(async () => {
+  await renderAll()
+})
+</script>
+
+<template>
+  <span class="signature-item" :class="{ 'is-text': isTextMode }" :style="{ width: width + 'px' }">
+    <template v-if="isTextMode">
+      <template v-if="hasSignature">
+        <canvas ref="textCanvasRef" :width="width" :height="height" class="signature-canvas"></canvas>
+      </template>
+      <span v-else class="fill-blank" :style="{ width: width + 'px' }"></span>
+    </template>
+
+    <template v-else>
+      <div class="signature-edit-area" :style="{ width: width + 'px', height: height + 'px' }">
+        <template v-if="hasSignature">
+          <canvas ref="editCanvasRef" :width="width" :height="height" class="signature-canvas"></canvas>
+        </template>
+        <div v-else class="signature-empty">
+          <span class="signature-placeholder">{{ placeholder }}</span>
+        </div>
+        <el-button
+          size="small"
+          type="primary"
+          class="signature-sign-btn"
+          @click="openSignPad"
+        >
+          {{ hasSignature ? '重签' : '点击签字' }}
+        </el-button>
+      </div>
+    </template>
+
+    <SignPad ref="signPadRef" :title="title" :elder-id="elderId" @confirm="handleSignConfirm" />
+  </span>
+</template>
+
+<style scoped lang="scss">
+.signature-item {
+  display: inline-flex;
+  vertical-align: middle;
+  position: relative;
+}
+
+.signature-edit-area {
+  position: relative;
+  border: 1px dashed #dcdfe6;
+  border-radius: 4px;
+  background: #fafafa;
+  overflow: hidden;
+  display: inline-block;
+  vertical-align: middle;
+  box-sizing: border-box;
+
+  &:hover {
+    border-color: #409eff;
+  }
+}
+
+.signature-canvas {
+  display: block;
+  width: 100%;
+  height: 100%;
+}
+
+.signature-empty {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 100%;
+  height: 100%;
+  position: relative;
+}
+
+.signature-placeholder {
+  color: #c0c4cc;
+  font-size: 13px;
+}
+
+.signature-sign-btn {
+  position: absolute;
+  bottom: 4px;
+  right: 4px;
+}
+
+.is-text {
+  display: inline-block;
+  vertical-align: middle;
+
+  .fill-blank {
+    display: inline-block;
+    border-bottom: 1px solid #333;
+    height: 18px;
+    vertical-align: middle;
+    margin: 0 2px;
+  }
+
+  .signature-canvas {
+    display: inline-block;
+    vertical-align: middle;
+    background: transparent;
+  }
+}
+</style>

+ 1181 - 0
src/views/elderly/contracts/risk-disclosure-statement/AddForm.vue

@@ -0,0 +1,1181 @@
+<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="attack-risk-form">
+      <h1 class="form-title">风险知情书(附件)</h1>
+      <!-- 基本信息 -->
+      <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="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">
+        <RiskDisclosureBody
+          v-model="riskDisclosureForm"
+          :is-text-mode="isDetail"
+        />
+      </div>
+
+    </div>
+
+
+
+    <template #footer>
+      <el-button @click="handleClosed">关闭</el-button>
+      <el-button  v-if="isDetail" type="success" @click="handleExport">打印</el-button>
+      <el-button style="margin-left: 22px;margin-right: 30px" v-loading="formLoading" type="primary" v-show="!isDetail" @click="submitForm">确定</el-button>
+    </template>
+
+  </el-drawer>
+</template>
+
+<script lang="ts" setup>
+import { computed, ref, watch, reactive } from 'vue'
+
+import dayjs from 'dayjs'
+import RiskDisclosureBody from '../components/RiskDisclosureBody.vue'
+
+import { attackRiskCreate, attackRiskGetById, attackRiskUpdate, attackRiskGetByElderId } from "@/api/social-work";
+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: '',
+  contractNumber: '', //档案号
+  elderName: '',//长者姓名
+  bedName: '', //床位号
+  elderAge: '', //年龄
+  elderSex: '', //性别
+  checkInTime: '', //入院日期
+  elderId: '',
+  tenantId: undefined
+})
+
+
+
+
+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||e.fileNumber
+  dataForm.value.elderAge = e.elderAge
+}
+
+// ========== 攻击风险因素评估量表 表单序列化方法 ==========
+
+/** 风险程度文本 */
+const riskLevelText = computed(() => {
+  const level = form.attackLevel
+  if (!level || level === 0) return '无风险'
+  if (level === 1) return 'I级'
+  if (level === 2) return 'II级'
+  if (level === 3) return 'III级'
+  return 'IV级'
+})
+
+/** 风险程度样式类 */
+const riskLevelClass = computed(() => {
+  const level = form.attackLevel
+  if (!level || level === 0) return 'risk-none'
+  if (level === 1) return 'risk-low'
+  if (level === 2) return 'risk-medium'
+  return 'risk-high'
+})
+
+/** 自动判断风险等级 */
+const autoJudgeRiskLevel = () => {
+  const level = form.attackLevel
+  if (!level || level === 0) form.riskLevel = 'none'
+  else if (level === 1) form.riskLevel = 'low'
+  else if (level === 2) form.riskLevel = 'medium'
+  else form.riskLevel = 'high'
+}
+
+/** 处理级别选择变化 - 清空其他级别的选中项 */
+const handleLevelChange = (val: number) => {
+  // 根据选中的级别,清空其他级别的多选框
+  if (val === 1) {
+    form.attackLevel2Items = []
+    form.attackLevel3Items = []
+    form.attackLevel4Items = []
+  } else if (val === 2) {
+    form.attackLevel1Items = []
+    form.attackLevel3Items = []
+    form.attackLevel4Items = []
+  } else if (val === 3) {
+    form.attackLevel1Items = []
+    form.attackLevel2Items = []
+    form.attackLevel4Items = []
+  } else if (val === 4) {
+    form.attackLevel1Items = []
+    form.attackLevel2Items = []
+    form.attackLevel3Items = []
+  }
+}
+
+
+
+/** 将表单数据序列化为 JSON 对象 */
+const serializeFormData = () => {
+  return {
+    // 基本信息
+    assessor: form.assessor || '',
+    assessDate: form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : '',
+
+    // 攻击风险等级(1=I级,2=II级,3=III级,4=IV级)
+    attackLevel: form.attackLevel || 0,
+
+    // 各级别选择的具体项
+    attackLevel1Items: form.attackLevel1Items || [],
+    attackLevel2Items: form.attackLevel2Items || [],
+    attackLevel3Items: form.attackLevel3Items || [],
+    attackLevel4Items: form.attackLevel4Items || [],
+
+    // 风险程度
+    riskLevel: form.riskLevel || '',
+
+    // 预防措施
+    preventiveMeasures: form.preventiveMeasures || [],
+    preventiveMeasuresOther: form.preventiveMeasuresOther || '',
+
+    // 签名
+    familySignature: form.familySignature || '',
+    familySignDate: form.familySignDate ? dayjs(form.familySignDate).format('YYYY-MM-DD') : '',
+
+    // 风险知情书内容
+    riskDisclosure: {
+      companyName: riskDisclosureForm.companyName || '',
+      partyBSign: riskDisclosureForm.partyBSign || '',
+      partyBDate: riskDisclosureForm.partyBDate || '',
+      partyCSign: riskDisclosureForm.partyCSign || '',
+      partyCDate: riskDisclosureForm.partyCDate || ''
+    }
+  }
+}
+
+/** 将 JSON 对象反序列化为表单数据 */
+const deserializeFormData = (formData: Record<string, any>) => {
+  if (!formData) return
+
+  // 基本信息
+  form.assessor = formData.assessor || ''
+  form.assessDate = formData.assessDate ? dayjs(formData.assessDate).toDate() : ''
+
+  // 攻击风险等级
+  form.attackLevel = formData.attackLevel || 0
+
+  // 各级别选择的具体项
+  form.attackLevel1Items = formData.attackLevel1Items || []
+  form.attackLevel2Items = formData.attackLevel2Items || []
+  form.attackLevel3Items = formData.attackLevel3Items || []
+  form.attackLevel4Items = formData.attackLevel4Items || []
+
+  // 风险程度
+  form.riskLevel = formData.riskLevel || ''
+
+  // 预防措施
+  form.preventiveMeasures = formData.preventiveMeasures || []
+  form.preventiveMeasuresOther = formData.preventiveMeasuresOther || ''
+
+  // 签名
+  form.familySignature = formData.familySignature || ''
+  form.familySignDate = formData.familySignDate ? dayjs(formData.familySignDate).toDate() : ''
+
+  // 风险知情书内容
+  if (formData.riskDisclosure) {
+    riskDisclosureForm.companyName = formData.riskDisclosure.companyName || ''
+    riskDisclosureForm.partyBSign = formData.riskDisclosure.partyBSign || ''
+    riskDisclosureForm.partyBDate = formData.riskDisclosure.partyBDate || ''
+    riskDisclosureForm.partyCSign = formData.riskDisclosure.partyCSign || ''
+    riskDisclosureForm.partyCDate = formData.riskDisclosure.partyCDate || ''
+  }
+}
+
+/** 重置攻击风险因素评估表表单数据 */
+const resetAttackRiskForm = () => {
+  form.assessor = ''
+  form.assessDate = ''
+
+  // 攻击风险等级
+  form.attackLevel = 0
+
+  // 各级别选择的具体项
+  form.attackLevel1Items = []
+  form.attackLevel2Items = []
+  form.attackLevel3Items = []
+  form.attackLevel4Items = []
+
+  // 风险程度
+  form.riskLevel = ''
+
+  // 预防措施
+  form.preventiveMeasures = []
+  form.preventiveMeasuresOther = ''
+
+  // 签名
+  form.familySignature = ''
+  form.familySignDate = ''
+
+  // 风险知情书
+  riskDisclosureForm.companyName = '颐年医养'
+  riskDisclosureForm.partyBSign = ''
+  riskDisclosureForm.partyBDate = ''
+  riskDisclosureForm.partyCSign = ''
+  riskDisclosureForm.partyCDate = ''
+}
+
+/** 打开弹窗 */
+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
+  if (id) {
+    title.value = "编辑-攻击风险因素评估"
+    // 加载评估数据
+    await loadAttackRiskData(id)
+  } else {
+    title.value = "新增-攻击风险因素评估"
+    
+  }
+}
+
+/** 加载评估数据 */
+const loadAttackRiskData = async (id: number) => {
+  try {
+    const res = await attackRiskGetById(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('加载评估数据失败')
+  }
+}
+
+/** 根据长者ID加载评估数据 */
+const loadAttackRiskByElderId = async (elderId: number) => {
+  try {
+    const res = await attackRiskGetByElderId(elderId)
+    if (res && res.assessData) {
+      const formData = JSON.parse(res.assessData)
+      deserializeFormData(formData)
+    }
+  } catch (error) {
+    // 无历史数据,不处理
+  }
+}
+
+const form = reactive({
+  // 基本信息
+  assessor: '',
+  assessDate: '',
+
+  // 攻击风险等级(0=无,1=I级,2=II级,3=III级,4=IV级)
+  attackLevel: 0,
+
+  // 各级别选择的具体项
+  attackLevel1Items: [], // I级选择的项(1-7)
+  attackLevel2Items: [], // II级选择的项(1-3)
+  attackLevel3Items: [], // III级选择的项(1-4)
+  attackLevel4Items: [], // IV级选择的项(1-2)
+
+  // 风险程度
+  riskLevel: '',
+
+  // 预防措施
+  preventiveMeasures: [],
+  preventiveMeasuresOther: '',
+
+  // 签名
+  familySignature: '',
+  familySignDate: ''
+})
+
+// 监听攻击等级变化,自动判断风险等级
+watch(() => form.attackLevel, () => {
+  autoJudgeRiskLevel()
+})
+
+// 风险知情书表单数据
+const riskDisclosureForm = reactive({
+  elderName: '',
+  companyName: '颐年医养',
+  assessor: '',
+  assessDate: '',
+  partyBSign: '',
+  partyBDate: '',
+  partyCSign: '',
+  partyCDate: ''
+})
+
+// 长者信息变化时同步到风险告知书
+watch(
+  () => dataForm.value.elderName,
+  (name) => {
+    riskDisclosureForm.elderName = name
+  }
+)
+
+// 记录人变化时同步
+watch(
+  () => form.assessor,
+  (val) => {
+    riskDisclosureForm.assessor = val
+  }
+)
+
+watch(
+  () => form.assessDate,
+  (val) => {
+    riskDisclosureForm.assessDate = val ? dayjs(val).format('YYYY-MM-DD') : ''
+  }
+)
+
+
+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),
+      attackLevel: form.attackLevel,
+      riskLevel: form.riskLevel,
+      assessor: form.assessor,
+      assessScore: form.attackLevel,
+      assessDate: form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : ''
+    }
+
+    if (dataForm.value.id) {
+      const res = await attackRiskUpdate(tempParams)
+      if (res) {
+        message.success(t('common.updateSuccess'))
+        dialogVisible.value = false
+        // 发送操作成功的事件
+        emit('success')
+      }
+    } else {
+      const res = await attackRiskCreate(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: '',
+    contractNumber: '', //档案号
+    elderName: '',//长者姓名
+    bedName: '', //床位号
+    elderAge: '', //年龄
+    elderSex: '', //性别
+    checkInTime: '', //入院日期
+    elderId: '',
+    tenantId: undefined
+  }
+  formRef.value?.resetFields()
+
+  // 重置攻击风险因素评估表表单
+  resetAttackRiskForm()
+}
+
+// 关闭表单
+const handleClosed = () => {
+  dialogVisible.value = false
+  resetForm()
+}
+
+/** 导出打印 */
+const handleExport = () => {
+  // 创建打印窗口
+  const printWindow = window.open('', '_blank')
+  if (!printWindow) {
+    message.error('请允许弹出窗口')
+    return
+  }
+
+  // 构建打印内容
+  const printContent = `
+    <!DOCTYPE html>
+    <html>
+    <head>
+      <meta charset="UTF-8">
+      <title>攻击风险因素评估量表 - ${dataForm.value.elderName || ''}</title>
+      <style>
+        @media print {
+          @page { size: A4 portrait; margin: 15mm; }
+        }
+        body {
+          font-family: 'SimSun', 'Microsoft YaHei', serif;
+          font-size: 10pt;
+          line-height: 1.4;
+          color: #333;
+        }
+        .header {
+          text-align: center;
+          margin-bottom: 15px;
+          border-bottom: 2px solid #333;
+          padding-bottom: 10px;
+        }
+        .header h1 {
+          font-size: 16pt;
+          margin: 0;
+          letter-spacing: 2px;
+        }
+        .info-section {
+          margin-bottom: 15px;
+          padding: 10px;
+          border: 1px solid #999;
+          background: #fafafa;
+        }
+        .info-row {
+          display: flex;
+          flex-wrap: wrap;
+          gap: 20px;
+        }
+        .info-item {
+          display: flex;
+          align-items: center;
+        }
+        .info-item .label {
+          font-weight: bold;
+          margin-right: 8px;
+          color: #555;
+        }
+        .info-item .value {
+          border-bottom: 1px solid #333;
+          min-width: 80px;
+          padding: 0 5px;
+          text-align: center;
+        }
+        .score-summary {
+          display: flex;
+          justify-content: center;
+          align-items: center;
+          padding: 10px 15px;
+          background: #f0f0f0;
+          border: 2px solid #333;
+          margin-bottom: 15px;
+        }
+        .total-score {
+          font-size: 14pt;
+          font-weight: bold;
+        }
+        .total-score .score-value {
+          color: #d9534f;
+          font-size: 18pt;
+        }
+
+        .assessment-table {
+          width: 100%;
+          border-collapse: collapse;
+          margin-bottom: 15px;
+        }
+        .assessment-table th, .assessment-table td {
+          border: 1px solid #333;
+          padding: 8px;
+          text-align: left;
+          vertical-align: top;
+        }
+        .assessment-table th {
+          background: #e8e8e8;
+          font-weight: bold;
+          text-align: center;
+        }
+        .assessment-table .content-col {
+          width: 65%;
+        }
+        .assessment-table .level-col {
+          width: 10%;
+          text-align: center;
+        }
+        .assessment-table .select-col {
+          width: 25%;
+          text-align: center;
+        }
+        .assessment-table .content-title {
+          font-weight: bold;
+          margin-bottom: 5px;
+        }
+        .assessment-table .content-item {
+          margin-left: 15px;
+          margin-bottom: 3px;
+        }
+        .assessment-table .select {
+          text-align: center;
+          vertical-align: middle;
+        }
+        .assessment-table .print-multi-select {
+          margin-top: 8px;
+          padding-top: 8px;
+          border-top: 1px dashed #ccc;
+          font-size: 9pt;
+        }
+
+        .risk-judgment-section {
+          margin: 15px 0;
+          padding: 10px;
+          border: 1px solid #999;
+        }
+        .risk-judgment-title {
+          font-weight: bold;
+          margin-bottom: 10px;
+        }
+        .risk-options {
+          display: flex;
+          flex-wrap: wrap;
+          gap: 15px;
+        }
+
+        .measures-section {
+          margin: 15px 0;
+          border: 1px solid #999;
+        }
+        .measures-title {
+          font-weight: bold;
+          background: #e8e8e8;
+          padding: 8px 12px;
+          border-bottom: 1px solid #999;
+        }
+        .measures-content {
+          padding: 10px 12px;
+        }
+        .measure-item {
+          margin-bottom: 8px;
+          font-size: 10pt;
+        }
+        .measure-other {
+          margin-left: 10px;
+          border-bottom: 1px solid #333;
+          min-width: 200px;
+          display: inline-block;
+        }
+
+        .signature-section {
+          margin-top: 20px;
+          padding: 15px;
+          border: 1px solid #999;
+        }
+        .signature-row {
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+        }
+        .signature-item {
+          display: flex;
+          align-items: center;
+          gap: 10px;
+        }
+        .signature-label {
+          font-weight: bold;
+        }
+        .signature-value {
+          border-bottom: 1px solid #333;
+          min-width: 150px;
+          height: 25px;
+        }
+
+        .note-section {
+          margin-top: 15px;
+          padding: 10px;
+          border: 1px solid #999;
+          background: #fafafa;
+        }
+        .note-title {
+          font-weight: bold;
+          margin-bottom: 8px;
+        }
+        .note-content {
+          font-size: 9pt;
+          line-height: 1.6;
+        }
+        .note-content p {
+          margin: 3px 0;
+        }
+        .note-content .indent {
+          margin-left: 20px;
+        }
+      </style>
+    </head>
+    <body>
+      <div class="header">
+        <h1>攻击风险因素评估量表</h1>
+      </div>
+
+      <div class="info-section">
+        <div class="info-row">
+          <div class="info-item">
+            <span class="label">长者姓名:</span>
+            <span class="value">${dataForm.value.elderName || ''}</span>
+          </div>
+          <div class="info-item">
+            <span class="label">档案号:</span>
+            <span class="value">${dataForm.value.contractNumber || ''}</span>
+          </div>
+          <div class="info-item">
+            <span class="label">床位号:</span>
+            <span class="value">${dataForm.value.bedName || ''}</span>
+          </div>
+        </div>
+        <div class="info-row" style="margin-top: 10px;">
+          <div class="info-item">
+            <span class="label">评估日期:</span>
+            <span class="value">${form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : ''}</span>
+          </div>
+          <div class="info-item">
+            <span class="label">评估人:</span>
+            <span class="value">${form.assessor || ''}</span>
+          </div>
+        </div>
+      </div>
+
+
+
+      <!-- 评估表格 -->
+      <table class="assessment-table">
+        <thead>
+          <tr>
+            <th class="content-col">评估内容</th>
+            <th class="level-col">级别</th>
+            <th class="select-col">评估</th>
+          </tr>
+        </thead>
+        <tbody>
+          <tr>
+            <td class="content">
+              <div class="content-title">存在右之一者,若为男性则有两项:</div>
+              <div class="content-item">(1) 男性</div>
+              <div class="content-item">(2) 精神分裂症,伴有幻听或被害妄想</div>
+              <div class="content-item">(3) 躁狂</div>
+              <div class="content-item">(4) 酒药依赖的脱瘾期</div>
+              <div class="content-item">(5) 意识障碍伴行为紊乱</div>
+              <div class="content-item">(6) 痴呆伴行为紊乱</div>
+              <div class="content-item">(7) 既往人格不良者(有冲动、边缘型人格障碍)</div>
+            </td>
+            <td class="level">I级</td>
+            <td class="select">
+              <div>${form.attackLevel === 1 ? '☑' : '☐'} 符合</div>
+              <div class="print-multi-select">
+                ${[1,2,3,4,5,6,7].map(n => `${form.attackLevel1Items?.includes(n) ? '☑' : '☐'} ${n}`).join('&nbsp;&nbsp;')}
+              </div>
+            </td>
+          </tr>
+          <tr>
+            <td class="content">
+              <div class="content-title">存在右侧情形之一者</div>
+              <div class="content-item">(1) 被动的言语攻击行为,表现为激惹性增高,如无对象的抱怨、发牢骚、说怪话</div>
+              <div class="content-item">(2) 交谈时态度不好、抵触、有敌意或不信任</div>
+              <div class="content-item">(3) 或精神分裂症有命令性幻听者</div>
+            </td>
+            <td class="level">II级</td>
+            <td class="select">
+              <div>${form.attackLevel === 2 ? '☑' : '☐'} 符合</div>
+              <div class="print-multi-select">
+                ${[1,2,3].map(n => `${form.attackLevel2Items?.includes(n) ? '☑' : '☐'} ${n}`).join('&nbsp;&nbsp;')}
+              </div>
+            </td>
+          </tr>
+          <tr>
+            <td class="content">
+              <div class="content-title">存在右侧情形之一者</div>
+              <div class="content-item">(1) 主动的言语攻击行为,如有对象的辱骂</div>
+              <div class="content-item">(2) 被动的躯体攻击行为如毁物</div>
+              <div class="content-item">(3) 在交往时出现社交粗暴(交谈时突然离去、躲避、推挡他人善意的躯体接触)</div>
+              <div class="content-item">(4) 既往曾有过主动的躯体攻击行为</div>
+            </td>
+            <td class="level">III级</td>
+            <td class="select">
+              <div>${form.attackLevel === 3 ? '☑' : '☐'} 符合</div>
+              <div class="print-multi-select">
+                ${[1,2,3,4].map(n => `${form.attackLevel3Items?.includes(n) ? '☑' : '☐'} ${n}`).join('&nbsp;&nbsp;')}
+              </div>
+            </td>
+          </tr>
+          <tr>
+            <td class="content">
+              <div class="content-title">存在右侧情形之一者</div>
+              <div class="content-item">(1) 有主动的躯体攻击行为,如踢、打、咬或使用物</div>
+              <div class="content-item">(2) 攻击行为在一天内至少出现两次以上或攻击行为造成了他人肉体上的伤害</div>
+            </td>
+            <td class="level">IV级</td>
+            <td class="select">
+              <div>${form.attackLevel === 4 ? '☑' : '☐'} 符合</div>
+              <div class="print-multi-select">
+                ${[1,2].map(n => `${form.attackLevel4Items?.includes(n) ? '☑' : '☐'} ${n}`).join('&nbsp;&nbsp;')}
+              </div>
+            </td>
+          </tr>
+        </tbody>
+      </table>
+
+      <!-- 风险程度判断 -->
+      <div class="risk-judgment-section">
+        <div class="risk-judgment-title">风险程度判断:</div>
+        <div class="risk-options">
+          <span class="risk-option">${form.riskLevel === 'none' ? '☑' : '☐'} 无风险:无级别</span>
+          <span class="risk-option">${form.riskLevel === 'low' ? '☑' : '☐'} 低风险:I级</span>
+          <span class="risk-option">${form.riskLevel === 'medium' ? '☑' : '☐'} 中风险:II级</span>
+          <span class="risk-option">${form.riskLevel === 'high' ? '☑' : '☐'} 高风险:III级、IV级</span>
+        </div>
+      </div>
+
+      <!-- 预防措施 -->
+      <div class="measures-section">
+        <div class="measures-title">预防措施</div>
+        <div class="measures-content">
+          <div class="measure-item">${form.preventiveMeasures?.includes('patrol') ? '☑' : '☐'} 加强巡视</div>
+          <div class="measure-item">${form.preventiveMeasures?.includes('handover') ? '☑' : '☐'} 严格交接班</div>
+          <div class="measure-item">${form.preventiveMeasures?.includes('checkItems') ? '☑' : '☐'} 检查有无危险物品</div>
+          <div class="measure-item">${form.preventiveMeasures?.includes('emotion') ? '☑' : '☐'} 注重长者情绪行为</div>
+          <div class="measure-item">
+            ${form.preventiveMeasures?.includes('other') ? '☑' : '☐'} 其他
+            ${form.preventiveMeasures?.includes('other') ? '<span class="measure-other">' + (form.preventiveMeasuresOther || '') + '</span>' : ''}
+          </div>
+        </div>
+      </div>
+
+
+
+      <!-- 说明 -->
+      <div class="note-section">
+        <div class="note-title">说明:</div>
+        <div class="note-content">
+          <p>1. 新入住长者应在长者入住24小时内完成首次评估;</p>
+          <p>2. 定期评估:</p>
+          <p class="indent">(1)认知照护专区:高风险1个月评估一次,中风险、低风险3个月评估一次;</p>
+          <p class="indent">(2)非认知照护专区:高风险1个月评估一次,中风险3个月评估一次,低风险6个月评估一次;</p>
+          <p>3. 当长者身体发生变化者,应及时进行动态评估。</p>
+        </div>
+      </div>
+    </body>
+    </html>
+  `
+
+  // 写入内容并打印
+  printWindow.document.write(printContent)
+  printWindow.document.close()
+
+  // 延迟打印,确保样式加载完成
+  setTimeout(() => {
+    printWindow.print()
+  }, 500)
+}
+
+</script>
+
+<style scoped lang="scss">
+
+.form-title {
+  text-align: center;
+  font-size: 20px;
+  width: 100%;
+  margin-bottom: 20px;
+}
+
+.attack-risk-form {
+  max-width: 1200px;
+  margin: 0 auto;
+  background: #fff;
+
+
+
+
+
+  .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;
+  }
+
+  // 调整 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;
+  }
+}
+
+// NGASR自杀风险评估量表 特有样式
+.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;
+      vertical-align: top;
+    }
+
+    th {
+      background: #f5f7fa;
+      font-weight: bold;
+      text-align: center;
+    }
+
+    .content-col {
+      width: 65%;
+    }
+
+    .level-col {
+      width: 10%;
+      text-align: center;
+    }
+
+    .select-col {
+      width: 25%;
+      text-align: center;
+    }
+
+    .content {
+      text-align: left;
+
+      .content-title {
+        font-weight: bold;
+        margin-bottom: 8px;
+      }
+
+      .content-item {
+        margin-left: 15px;
+        margin-bottom: 4px;
+        font-size: 13px;
+      }
+    }
+
+    .level {
+      text-align: center;
+      font-weight: bold;
+    }
+
+    .select {
+      text-align: center;
+
+      :deep(.el-radio) {
+        margin-right: 0;
+      }
+    }
+  }
+}
+
+.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>

+ 344 - 0
src/views/elderly/contracts/risk-disclosure-statement/index.vue

@@ -0,0 +1,344 @@
+<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-input
+          v-model="queryParams.assessor"
+          placeholder="长者姓名"
+          class="!w-240px"
+          clearable
+        />
+      </el-form-item>
+
+      <el-form-item label="记录日期">
+        <el-date-picker
+          size="default"
+          ref="selectRef"
+          class="!w-240px"
+          v-model="queryParams.assessDate"
+          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="150" show-overflow-tooltip/>
+      <el-table-column prop="assessor" header-align="center" align="center" label="评估人" min-width="200" show-overflow-tooltip/>
+      <el-table-column header-align="center" align="center" label="风险等级" min-width="200" show-overflow-tooltip>
+        <template #default="scope">
+          <el-tag v-if="getRiskLevelInfo(scope.row.assessData).text" :type="getRiskLevelInfo(scope.row.assessData).type">
+            {{ getRiskLevelInfo(scope.row.assessData).text }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column prop="assessDate" header-align="center" align="center" label="记录日期" min-width="200" show-overflow-tooltip/>
+      <el-table-column prop="creator" header-align="center" align="center" label="记录人" min-width="200" show-overflow-tooltip/>
+
+
+      <el-table-column label="操作" align="center" width="200" >
+        <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,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 { useUserStore } from '@/store/modules/user'
+import {formatTimestamp, getCurrentMonthRange} from "@/utils/dateUtil";
+import Import from "@/components/ImportFile/index.vue";
+import {restraintCreatePage, restraintDelete} from "@/api/elderly/nursing/keep-fit";
+import {
+  attackRiskDelete, attackRiskPage,
+} from "@/api/social-work";
+import { getRiskLevelInfo } from "@/utils/risk-assessment";
+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: '',
+  assessor: '',
+  // assessDate: getCurrentMonthRange(),
+  assessDate: [],
+  tenantIds: userStore.orgTenantId
+})
+const queryFormRef = ref() // 搜索的表单
+
+
+// 打开导出弹窗
+const handleImportCard = async () => {
+
+  // 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 attackRiskPage(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.assessor = ''
+  queryParams.tenantIds = userStore.orgTenantId
+  // queryParams.assessDate= getCurrentMonthRange()
+  queryParams.assessDate = []
+  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[0], id,false)
+}
+
+const editRef = ref()
+const openFormEdit = (row: any = {}, id?: number) => {
+  formRef.value.open(row.tenantId, id,false)
+}
+
+
+const openFormDetail = (row: any = {},id?: number) => {
+  formRef.value.open(row.tenantId,id,true)
+}
+
+
+
+
+
+const openClose = async (item) => {
+  try {
+    console.log("任务ID",item)
+    const res = await message.confirm('确定要删除吗?', '提示')
+    if (res == 'confirm') {
+      // 发起
+      try {
+        const res = await attackRiskDelete(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 route = useRoute()
+/** 初始化 **/
+onMounted(() => {
+  if(route.query && route.query.elderName){
+    queryParams.elderName = route.query.elderName as string
+  }
+  getList()
+})
+
+// 表头格式
+const tableHeaderColor = ({ rowIndex }: any) => {
+  if (rowIndex === 0) {
+    return {
+      backgroundColor: '#f8f8f9',
+      color: '#666666',
+      fontWeight: 'bold'
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss"></style>

+ 4 - 0
src/views/elderly/elder/contract/index.vue

@@ -92,6 +92,7 @@
   </ContentWrap>
 
   <Form ref="formRef" @success="getList" />
+  <ContractManageForm ref="contractManageFormRef" />
   <Renewal ref="renewalRef" @success="getList" />
   <Detail ref="detailRef" />
 </template>
@@ -102,6 +103,7 @@ import { ContractColumns } from '../column'
 import Form from './Form.vue'
 import Renewal from './Renewal.vue'
 import Detail from './Detail.vue'
+import ContractManageForm from '@/views/elderly/contracts/ContractManageForm.vue'
 import { useUserStore } from '@/store/modules/user'
 import { formatTimestampYMD } from '@/utils/dateUtil'
 defineOptions({ name: 'Contract' })
@@ -120,6 +122,7 @@ const queryParams = reactive({
   tenantIds: userStore.orgTenantId
 })
 const queryFormRef = ref() // 搜索的表单
+const contractManageFormRef = ref() // 合同管理的表单
 
 /** 查询列表 */
 const getList = async () => {
@@ -151,6 +154,7 @@ const resetQuery = () => {
 /** 添加/修改操作 */
 const formRef = ref()
 const openForm = (row: any = {}, type: number = 1) => {
+  //contractManageFormRef.value.open(row, type)
   formRef.value.open(row, type)
 }