AddForm.vue 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166
  1. <template>
  2. <el-drawer
  3. v-model="dialogVisible"
  4. :title="title"
  5. resizable
  6. :close-on-click-modal="false"
  7. :close-on-press-escape="false"
  8. :destroy-on-close="true"
  9. size="70%"
  10. :before-close="handleClosed"
  11. >
  12. <div class="ngasr-form">
  13. <h1 class="form-title">自杀风险评估量表</h1>
  14. <!-- 基本信息 -->
  15. <el-row :gutter="40">
  16. <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
  17. <text>长者姓名</text>
  18. <search-the-elderly ref="selectElderRef" :disabled="isDetail" @update_elder="elderUp" v-model="dataForm.elderName" :tId="dataForm.tenantId"/>
  19. </el-col>
  20. <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
  21. <text>档案号</text>
  22. <el-input v-if="!isDetail" v-model="dataForm.contractNumber" disabled />
  23. <el-text v-else disabled="">{{dataForm.contractNumber}}</el-text>
  24. </el-col>
  25. </el-row>
  26. <el-row :gutter="40">
  27. <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
  28. <text>入院日期</text>
  29. <el-input v-if="!isDetail" :model-value="dayjs(dataForm.checkInTime).format('YYYY-MM-DD')=='Invalid Date'?'':dayjs(dataForm.checkInTime).format('YYYY-MM-DD')" disabled />
  30. <el-text v-else disabled="">{{dayjs(dataForm.checkInTime).format('YYYY-MM-DD')}}</el-text>
  31. </el-col>
  32. <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
  33. <text>床位号</text>
  34. <el-input v-if="!isDetail" v-model="dataForm.bedName" disabled />
  35. <el-text v-else disabled="">{{dataForm.bedName}}</el-text>
  36. </el-col>
  37. </el-row>
  38. <el-row :gutter="40">
  39. <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
  40. <text>评估人</text>
  41. <el-input :disabled="isDetail" v-model="form.assessor" />
  42. </el-col>
  43. <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" class="row">
  44. <text>评估日期</text>
  45. <el-date-picker :disabled="isDetail" v-model="form.assessDate" type="date" style="width: 100%;"/>
  46. </el-col>
  47. </el-row>
  48. <!-- 表单内容区域 -->
  49. <div class="form-body">
  50. <!-- 总分显示 -->
  51. <div class="total-score-section">
  52. <div class="total-score">
  53. <span class="score-label">评估总得分:</span>
  54. <span class="score-value">{{ totalScore }}</span>
  55. <span class="score-max">分</span>
  56. </div>
  57. </div>
  58. <!-- 评估表格 -->
  59. <div class="assessment-table">
  60. <table>
  61. <thead>
  62. <tr>
  63. <th class="risk-factor-col">危险因素</th>
  64. <th class="score-yes-col">是</th>
  65. <th class="score-no-col">否</th>
  66. <th class="select-col">选择</th>
  67. </tr>
  68. </thead>
  69. <tbody>
  70. <tr v-for="(item, index) in riskFactors" :key="index">
  71. <td class="risk-factor">{{ item.name }}</td>
  72. <td class="score-yes">{{ item.yesScore }}分</td>
  73. <td class="score-no">0分</td>
  74. <td class="select">
  75. <el-radio-group v-model="form.riskScores[index]" :disabled="isDetail">
  76. <el-radio :value="item.yesScore" style="margin-right: 26px"> 是</el-radio>
  77. <el-radio :value="0"> 否</el-radio>
  78. </el-radio-group>
  79. </td>
  80. </tr>
  81. </tbody>
  82. </table>
  83. </div>
  84. <!-- 风险程度判断 -->
  85. <div class="risk-judgment-section">
  86. <div class="risk-judgment-title">风险程度判断:</div>
  87. <div class="risk-options">
  88. <el-radio v-model="form.riskLevel" value="none" :disabled="isDetail">
  89. 无风险:0分
  90. </el-radio>
  91. <el-radio v-model="form.riskLevel" value="low" :disabled="isDetail">
  92. 低风险:1-5分
  93. </el-radio>
  94. <el-radio v-model="form.riskLevel" value="medium" :disabled="isDetail">
  95. 中风险:6-8分
  96. </el-radio>
  97. <el-radio v-model="form.riskLevel" value="high" :disabled="isDetail">
  98. 高风险:≥9分
  99. </el-radio>
  100. </div>
  101. </div>
  102. <!-- 预防措施 -->
  103. <div class="preventive-section">
  104. <div class="preventive-title">预防措施:</div>
  105. <div class="preventive-options">
  106. <el-checkbox v-model="form.preventiveMeasures" value="patrol" :disabled="isDetail">
  107. 加强巡视
  108. </el-checkbox>
  109. <el-checkbox v-model="form.preventiveMeasures" value="handover" :disabled="isDetail">
  110. 严格交接班
  111. </el-checkbox>
  112. <el-checkbox v-model="form.preventiveMeasures" value="checkItems" :disabled="isDetail">
  113. 检查有无危险物品
  114. </el-checkbox>
  115. <el-checkbox v-model="form.preventiveMeasures" value="emotion" :disabled="isDetail">
  116. 注重长者情绪行为
  117. </el-checkbox>
  118. <el-checkbox v-model="form.preventiveMeasures" value="other" :disabled="isDetail">
  119. 其他
  120. </el-checkbox>
  121. <el-input v-if="form.preventiveMeasures.includes('other')" v-model="form.preventiveMeasuresOther" placeholder="请输入其他措施" :disabled="isDetail" class="other-input"/>
  122. </div>
  123. </div>
  124. <!-- 签名区域 -->
  125. <div class="signature-section">
  126. <div class="signature-row">
  127. <div class="signature-item">
  128. <span class="signature-label">家属/监护人签名:</span>
  129. <el-input v-model="form.familySignature" :disabled="isDetail" class="signature-input"/>
  130. </div>
  131. </div>
  132. </div>
  133. <!-- 说明 -->
  134. <div class="note-section">
  135. <div class="note-title">说明:</div>
  136. <div class="note-content">
  137. <p>1. 新入住长者应在长者入住24小时内完成首次评估;</p>
  138. <p>2. 定期评估:</p>
  139. <p class="indent">(1)认知照护专区:高风险1个月评估一次,中风险、低风险3个月评估一次;</p>
  140. <p class="indent">(2)非认知照护专区:高风险1个月评估一次,中风险3个月评估一次,低风险6个月评估一次;</p>
  141. <p>3. 当长者身体发生变化者,应及时进行动态评估。</p>
  142. </div>
  143. </div>
  144. </div>
  145. </div>
  146. <template #footer>
  147. <el-button @click="handleClosed">关闭</el-button>
  148. <el-button v-if="isDetail" type="success" @click="handleExport">打印</el-button>
  149. <el-button style="margin-left: 22px;margin-right: 30px" v-loading="formLoading" type="primary" v-show="!isDetail" @click="submitForm">确定</el-button>
  150. </template>
  151. </el-drawer>
  152. </template>
  153. <script lang="ts" setup>
  154. import { computed, ref, watch } from 'vue'
  155. import dayjs from 'dayjs'
  156. import { ngasrCreate, ngasrGetById, ngasrUpdate, ngasrGetByElderId } from "@/api/social-work";
  157. const message = useMessage() // 消息弹窗
  158. const { t } = useI18n() // 国际化
  159. const title = ref('')
  160. const dialogVisible = ref(false) // 弹窗
  161. const formRef = ref() // 表单 Ref
  162. const selectElderRef = ref() // 表单 Ref
  163. const isDetail = ref(false) // 是否详情打开
  164. const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
  165. let dataForm = ref({
  166. // 表单字段
  167. id: undefined,
  168. idCard: '',
  169. contractNumber: '', //档案号
  170. elderName: '',//长者姓名
  171. bedName: '', //床位号
  172. elderAge: '', //年龄
  173. elderSex: '', //性别
  174. checkInTime: '', //入院日期
  175. elderId: '',
  176. tenantId: undefined
  177. })
  178. const elderUp = (e) => {
  179. dataForm.value.elderName = e.elderName
  180. dataForm.value.elderId = e.id
  181. dataForm.value.elderSex = e.elderSex === 1 ? '男' : '女'
  182. dataForm.value.bedName = e.bedName || ''
  183. dataForm.value.checkInTime = e.checkInTime
  184. dataForm.value.contractNumber = e.contractNumber
  185. dataForm.value.elderAge = e.elderAge
  186. }
  187. // ========== NGASR自杀风险评估量表 表单序列化方法 ==========
  188. // 危险因素列表
  189. const riskFactors = [
  190. { name: '绝望感', yesScore: 3 },
  191. { name: '近期负性生活事件', yesScore: 1 },
  192. { name: '被害妄想或有被害内容的幻听', yesScore: 1 },
  193. { name: '情绪低落/兴趣丧失或愉快感缺乏', yesScore: 3 },
  194. { name: '人际和社会功能退缩', yesScore: 1 },
  195. { name: '言语流露自杀意图', yesScore: 1 },
  196. { name: '计划采取自杀行动', yesScore: 3 },
  197. { name: '自杀家族史', yesScore: 1 },
  198. { name: '近亲人死亡或重要的亲密关系丧失', yesScore: 3 },
  199. { name: '精神病史', yesScore: 1 },
  200. { name: '鳏夫/寡妇', yesScore: 1 },
  201. { name: '自杀未遂史', yesScore: 3 },
  202. { name: '社会-经济地位低下', yesScore: 1 },
  203. { name: '饮酒史或酒精滥用', yesScore: 1 },
  204. { name: '罹患晚期疾病', yesScore: 1 }
  205. ]
  206. /** 风险程度文本 */
  207. const riskLevelText = computed(() => {
  208. const score = totalScore.value
  209. if (score === 0) return '无风险'
  210. if (score >= 1 && score <= 5) return '低风险'
  211. if (score >= 6 && score <= 8) return '中风险'
  212. return '高风险'
  213. })
  214. /** 风险程度样式类 */
  215. const riskLevelClass = computed(() => {
  216. const score = totalScore.value
  217. if (score === 0) return 'risk-none'
  218. if (score >= 1 && score <= 5) return 'risk-low'
  219. if (score >= 6 && score <= 8) return 'risk-medium'
  220. return 'risk-high'
  221. })
  222. /** 自动判断风险等级 */
  223. const autoJudgeRiskLevel = () => {
  224. const score = totalScore.value
  225. if (score === 0) form.riskLevel = 'none'
  226. else if (score >= 1 && score <= 5) form.riskLevel = 'low'
  227. else if (score >= 6 && score <= 8) form.riskLevel = 'medium'
  228. else form.riskLevel = 'high'
  229. }
  230. /** 将表单数据序列化为 JSON 对象 */
  231. const serializeFormData = () => {
  232. return {
  233. // 基本信息
  234. assessor: form.assessor || '',
  235. assessDate: form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : '',
  236. // 各危险因素得分
  237. riskScores: form.riskScores || [],
  238. // 总分
  239. totalScore: totalScore.value,
  240. // 风险程度
  241. riskLevel: form.riskLevel || '',
  242. // 预防措施
  243. preventiveMeasures: form.preventiveMeasures || [],
  244. preventiveMeasuresOther: form.preventiveMeasuresOther || '',
  245. // 签名
  246. familySignature: form.familySignature || '',
  247. familySignDate: form.familySignDate ? dayjs(form.familySignDate).format('YYYY-MM-DD') : ''
  248. }
  249. }
  250. /** 将 JSON 对象反序列化为表单数据 */
  251. const deserializeFormData = (formData: Record<string, any>) => {
  252. if (!formData) return
  253. // 基本信息
  254. form.assessor = formData.assessor || ''
  255. form.assessDate = formData.assessDate ? dayjs(formData.assessDate).toDate() : ''
  256. // 各危险因素得分
  257. form.riskScores = formData.riskScores || new Array(15).fill(0)
  258. // 风险程度
  259. form.riskLevel = formData.riskLevel || ''
  260. // 预防措施
  261. form.preventiveMeasures = formData.preventiveMeasures || []
  262. form.preventiveMeasuresOther = formData.preventiveMeasuresOther || ''
  263. // 签名
  264. form.familySignature = formData.familySignature || ''
  265. form.familySignDate = formData.familySignDate ? dayjs(formData.familySignDate).toDate() : ''
  266. }
  267. /** 重置NGASR评估表表单数据 */
  268. const resetNGASRForm = () => {
  269. form.assessor = ''
  270. form.assessDate = ''
  271. // 各危险因素得分(15个因素,初始为0)
  272. form.riskScores = new Array(15).fill(0)
  273. // 风险程度
  274. form.riskLevel = ''
  275. // 预防措施
  276. form.preventiveMeasures = []
  277. form.preventiveMeasuresOther = ''
  278. // 签名
  279. form.familySignature = ''
  280. form.familySignDate = ''
  281. }
  282. /** 打开弹窗 */
  283. const open = async (tenantId, id?: any, detail: boolean = false) => {
  284. resetForm()
  285. dialogVisible.value = true
  286. dataForm.value.id = id || undefined
  287. dataForm.value.tenantId = tenantId
  288. isDetail.value = detail
  289. if (id) {
  290. title.value = "编辑-自杀风险评估"
  291. // 加载评估数据
  292. await loadNGASRData(id)
  293. } else {
  294. title.value = "新增-自杀风险评估"
  295. }
  296. }
  297. /** 加载评估数据 */
  298. const loadNGASRData = async (id: number) => {
  299. try {
  300. const res = await ngasrGetById(id)
  301. if (res) {
  302. // 填充长者基本信息
  303. dataForm.value.elderName = res.elderName || ''
  304. dataForm.value.elderId = res.elderId || ''
  305. dataForm.value.elderSex = res.elderSex || ''
  306. dataForm.value.bedName = res.bedName || ''
  307. dataForm.value.checkInTime = res.checkInTime || ''
  308. dataForm.value.contractNumber = res.fileNumber || ''
  309. dataForm.value.elderAge = res.elderAge || ''
  310. await selectElderRef.value.upData(res.elderName, res.elderId)
  311. // 解析 assessData
  312. if (res.assessData) {
  313. const formData = JSON.parse(res.assessData)
  314. deserializeFormData(formData)
  315. }
  316. }
  317. } catch (error) {
  318. message.error('加载评估数据失败')
  319. }
  320. }
  321. /** 根据长者ID加载评估数据 */
  322. const loadNGASRByElderId = async (elderId: number) => {
  323. try {
  324. const res = await ngasrGetByElderId(elderId)
  325. if (res && res.assessData) {
  326. const formData = JSON.parse(res.assessData)
  327. deserializeFormData(formData)
  328. }
  329. } catch (error) {
  330. // 无历史数据,不处理
  331. }
  332. }
  333. const form = reactive({
  334. // 基本信息
  335. assessor: '',
  336. assessDate: '',
  337. // 各危险因素得分(15个因素)
  338. riskScores: new Array(15).fill(0),
  339. // 风险程度
  340. riskLevel: '',
  341. // 预防措施
  342. preventiveMeasures: [],
  343. preventiveMeasuresOther: '',
  344. // 签名
  345. familySignature: '',
  346. familySignDate: ''
  347. })
  348. /** 计算总分 */
  349. const totalScore = computed(() => {
  350. if (!form.riskScores || form.riskScores.length === 0) return 0
  351. return form.riskScores.reduce((sum, score) => sum + (score || 0), 0)
  352. })
  353. // 监听总分变化,自动判断风险等级
  354. watch(totalScore, () => {
  355. autoJudgeRiskLevel()
  356. })
  357. defineExpose({ open }) // 提供 open 方法,用于打开弹窗
  358. /** 提交表单 */
  359. const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
  360. const submitForm = async () => {
  361. if (formLoading.value) {
  362. return
  363. }
  364. formLoading.value = true
  365. // 提交请求
  366. try {
  367. const assessData = serializeFormData()
  368. const tempParams = {
  369. ...dataForm.value,
  370. assessData: JSON.stringify(assessData),
  371. totalScore: totalScore.value,
  372. assessor: form.assessor,
  373. assessDate: form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : ''
  374. }
  375. if (dataForm.value.id) {
  376. const res = await ngasrUpdate(tempParams)
  377. if (res) {
  378. message.success(t('common.updateSuccess'))
  379. dialogVisible.value = false
  380. // 发送操作成功的事件
  381. emit('success')
  382. }
  383. } else {
  384. const res = await ngasrCreate(tempParams)
  385. if (res) {
  386. message.success(t('common.createSuccess'))
  387. dialogVisible.value = false
  388. // 发送操作成功的事件
  389. emit('success')
  390. }
  391. }
  392. } finally {
  393. setTimeout(() => {
  394. formLoading.value = false
  395. }, 500)
  396. }
  397. }
  398. /** 重置表单 */
  399. const resetForm = () => {
  400. dataForm.value = {
  401. id: undefined,
  402. idCard: '',
  403. contractNumber: '', //档案号
  404. elderName: '',//长者姓名
  405. bedName: '', //床位号
  406. elderAge: '', //年龄
  407. elderSex: '', //性别
  408. checkInTime: '', //入院日期
  409. elderId: '',
  410. tenantId: undefined
  411. }
  412. formRef.value?.resetFields()
  413. // 重置NGASR评估表表单
  414. resetNGASRForm()
  415. }
  416. // 关闭表单
  417. const handleClosed = () => {
  418. dialogVisible.value = false
  419. resetForm()
  420. }
  421. /** 导出打印 */
  422. const handleExport = () => {
  423. // 创建打印窗口
  424. const printWindow = window.open('', '_blank')
  425. if (!printWindow) {
  426. message.error('请允许弹出窗口')
  427. return
  428. }
  429. // 构建危险因素表格行
  430. const riskFactorRows = riskFactors.map((item, index) => {
  431. const score = form.riskScores[index] || 0
  432. return `
  433. <tr>
  434. <td class="risk-factor">${item.name}</td>
  435. <td class="score-yes">${item.yesScore}分</td>
  436. <td class="score-no">0分</td>
  437. <td class="select">${score === item.yesScore ? '☑ 是' : '☐ 是'} / ${score === 0 ? '☑ 否' : '☐ 否'}</td>
  438. </tr>
  439. `
  440. }).join('')
  441. // 构建打印内容
  442. const printContent = `
  443. <!DOCTYPE html>
  444. <html>
  445. <head>
  446. <meta charset="UTF-8">
  447. <title>自杀风险评估量表(NGASR) - ${dataForm.value.elderName || ''}</title>
  448. <style>
  449. @media print {
  450. @page { size: A4 portrait; margin: 15mm; }
  451. }
  452. body {
  453. font-family: 'SimSun', 'Microsoft YaHei', serif;
  454. font-size: 11pt;
  455. line-height: 1.5;
  456. color: #333;
  457. }
  458. .header {
  459. text-align: center;
  460. margin-bottom: 20px;
  461. border-bottom: 2px solid #333;
  462. padding-bottom: 10px;
  463. }
  464. .header h1 {
  465. font-size: 18pt;
  466. margin: 0;
  467. letter-spacing: 2px;
  468. }
  469. .info-section {
  470. margin-bottom: 15px;
  471. padding: 10px;
  472. border: 1px solid #999;
  473. background: #fafafa;
  474. }
  475. .info-row {
  476. display: flex;
  477. flex-wrap: wrap;
  478. gap: 20px;
  479. }
  480. .info-item {
  481. display: flex;
  482. align-items: center;
  483. }
  484. .info-item .label {
  485. font-weight: bold;
  486. margin-right: 8px;
  487. color: #555;
  488. }
  489. .info-item .value {
  490. border-bottom: 1px solid #333;
  491. min-width: 80px;
  492. padding: 0 5px;
  493. text-align: center;
  494. }
  495. .score-summary {
  496. display: flex;
  497. justify-content: space-between;
  498. align-items: center;
  499. padding: 10px 15px;
  500. background: #f0f0f0;
  501. border: 2px solid #333;
  502. margin-bottom: 15px;
  503. }
  504. .total-score {
  505. font-size: 14pt;
  506. font-weight: bold;
  507. }
  508. .total-score .score-value {
  509. color: #d9534f;
  510. font-size: 18pt;
  511. }
  512. .risk-level {
  513. font-size: 12pt;
  514. font-weight: bold;
  515. padding: 5px 15px;
  516. }
  517. .risk-none { color: #5cb85c; }
  518. .risk-low { color: #f0ad4e; }
  519. .risk-medium { color: #d9534f; }
  520. .risk-high { color: #d9534f; background: #ffe6e6; padding: 5px 10px; border-radius: 3px; }
  521. .assessment-table {
  522. width: 100%;
  523. border-collapse: collapse;
  524. margin-bottom: 15px;
  525. }
  526. .assessment-table th, .assessment-table td {
  527. border: 1px solid #333;
  528. padding: 8px;
  529. text-align: left;
  530. }
  531. .assessment-table th {
  532. background: #e8e8e8;
  533. font-weight: bold;
  534. text-align: center;
  535. }
  536. .assessment-table .risk-factor-col {
  537. width: 45%;
  538. }
  539. .assessment-table .score-yes-col,
  540. .assessment-table .score-no-col {
  541. width: 12%;
  542. text-align: center;
  543. }
  544. .assessment-table .select-col {
  545. width: 31%;
  546. text-align: center;
  547. }
  548. .assessment-table .risk-factor {
  549. text-align: left;
  550. }
  551. .assessment-table .score-yes,
  552. .assessment-table .score-no {
  553. text-align: center;
  554. }
  555. .risk-judgment-section {
  556. margin: 15px 0;
  557. padding: 10px;
  558. border: 1px solid #999;
  559. }
  560. .risk-judgment-title {
  561. font-weight: bold;
  562. margin-bottom: 10px;
  563. }
  564. .risk-options {
  565. display: flex;
  566. flex-wrap: wrap;
  567. gap: 15px;
  568. }
  569. .risk-option {
  570. display: inline-block;
  571. }
  572. .measures-section {
  573. margin: 15px 0;
  574. border: 1px solid #999;
  575. }
  576. .measures-title {
  577. font-weight: bold;
  578. background: #e8e8e8;
  579. padding: 8px 12px;
  580. border-bottom: 1px solid #999;
  581. }
  582. .measures-content {
  583. padding: 10px 12px;
  584. }
  585. .measure-item {
  586. margin-bottom: 8px;
  587. font-size: 10pt;
  588. }
  589. .measure-other {
  590. margin-left: 10px;
  591. border-bottom: 1px solid #333;
  592. min-width: 200px;
  593. display: inline-block;
  594. }
  595. .signature-section {
  596. margin-top: 30px;
  597. padding: 15px;
  598. border: 1px solid #999;
  599. }
  600. .signature-row {
  601. display: flex;
  602. justify-content: space-between;
  603. align-items: center;
  604. }
  605. .signature-item {
  606. display: flex;
  607. align-items: center;
  608. gap: 10px;
  609. }
  610. .signature-label {
  611. font-weight: bold;
  612. }
  613. .signature-value {
  614. border-bottom: 1px solid #333;
  615. min-width: 150px;
  616. height: 25px;
  617. }
  618. .note-section {
  619. margin-top: 20px;
  620. padding: 15px;
  621. border: 1px solid #999;
  622. background: #fafafa;
  623. }
  624. .note-title {
  625. font-weight: bold;
  626. margin-bottom: 10px;
  627. }
  628. .note-content {
  629. font-size: 10pt;
  630. line-height: 1.8;
  631. }
  632. .note-content p {
  633. margin: 5px 0;
  634. }
  635. .note-content .indent {
  636. margin-left: 20px;
  637. }
  638. </style>
  639. </head>
  640. <body>
  641. <div class="header">
  642. <h1>自杀风险评估量表(NGASR)</h1>
  643. </div>
  644. <div class="info-section">
  645. <div class="info-row">
  646. <div class="info-item">
  647. <span class="label">长者姓名:</span>
  648. <span class="value">${dataForm.value.elderName || ''}</span>
  649. </div>
  650. <div class="info-item">
  651. <span class="label">档案号:</span>
  652. <span class="value">${dataForm.value.contractNumber || ''}</span>
  653. </div>
  654. <div class="info-item">
  655. <span class="label">床位号:</span>
  656. <span class="value">${dataForm.value.bedName || ''}</span>
  657. </div>
  658. </div>
  659. <div class="info-row" style="margin-top: 10px;">
  660. <div class="info-item">
  661. <span class="label">评估日期:</span>
  662. <span class="value">${form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : ''}</span>
  663. </div>
  664. <div class="info-item">
  665. <span class="label">评估人:</span>
  666. <span class="value">${form.assessor || ''}</span>
  667. </div>
  668. </div>
  669. </div>
  670. <div class="score-summary">
  671. <div class="total-score">
  672. 总得分:<span class="score-value">${totalScore.value}</span> 分
  673. </div>
  674. </div>
  675. <!-- 评估表格 -->
  676. <table class="assessment-table">
  677. <thead>
  678. <tr>
  679. <th class="risk-factor-col">危险因素</th>
  680. <th class="score-yes-col">是</th>
  681. <th class="score-no-col">否</th>
  682. <th class="select-col">选择</th>
  683. </tr>
  684. </thead>
  685. <tbody>
  686. ${riskFactorRows}
  687. </tbody>
  688. </table>
  689. <!-- 风险程度判断 -->
  690. <div class="risk-judgment-section">
  691. <div class="risk-judgment-title">风险程度判断:</div>
  692. <div class="risk-options">
  693. <span class="risk-option">${form.riskLevel === 'none' ? '☑' : '☐'} 无风险:0分</span>
  694. <span class="risk-option">${form.riskLevel === 'low' ? '☑' : '☐'} 低风险:1-5分</span>
  695. <span class="risk-option">${form.riskLevel === 'medium' ? '☑' : '☐'} 中风险:6-8分</span>
  696. <span class="risk-option">${form.riskLevel === 'high' ? '☑' : '☐'} 高风险:≥9分</span>
  697. </div>
  698. </div>
  699. <!-- 预防措施 -->
  700. <div class="measures-section">
  701. <div class="measures-title">预防措施</div>
  702. <div class="measures-content">
  703. <div class="measure-item">${form.preventiveMeasures?.includes('patrol') ? '☑' : '☐'} 加强巡视</div>
  704. <div class="measure-item">${form.preventiveMeasures?.includes('handover') ? '☑' : '☐'} 严格交接班</div>
  705. <div class="measure-item">${form.preventiveMeasures?.includes('checkItems') ? '☑' : '☐'} 检查有无危险物品</div>
  706. <div class="measure-item">${form.preventiveMeasures?.includes('emotion') ? '☑' : '☐'} 注重长者情绪行为</div>
  707. <div class="measure-item">
  708. ${form.preventiveMeasures?.includes('other') ? '☑' : '☐'} 其他
  709. ${form.preventiveMeasures?.includes('other') ? '<span class="measure-other">' + (form.preventiveMeasuresOther || '') + '</span>' : ''}
  710. </div>
  711. </div>
  712. </div>
  713. <!-- 签名区域 -->
  714. <div class="signature-section">
  715. <div class="signature-row">
  716. <div class="signature-item">
  717. <span class="signature-label">家属/监护人签名:</span>
  718. <span class="signature-value">${form.familySignature || ''}</span>
  719. </div>
  720. </div>
  721. </div>
  722. <!-- 说明 -->
  723. <div class="note-section">
  724. <div class="note-title">说明:</div>
  725. <div class="note-content">
  726. <p>1. 新入住长者应在长者入住24小时内完成首次评估;</p>
  727. <p>2. 定期评估:</p>
  728. <p class="indent">(1)认知照护专区:高风险1个月评估一次,中风险、低风险3个月评估一次;</p>
  729. <p class="indent">(2)非认知照护专区:高风险1个月评估一次,中风险3个月评估一次,低风险6个月评估一次;</p>
  730. <p>3. 当长者身体发生变化者,应及时进行动态评估。</p>
  731. </div>
  732. </div>
  733. </body>
  734. </html>
  735. `
  736. // 写入内容并打印
  737. printWindow.document.write(printContent)
  738. printWindow.document.close()
  739. // 延迟打印,确保样式加载完成
  740. setTimeout(() => {
  741. printWindow.print()
  742. }, 500)
  743. }
  744. </script>
  745. <style scoped lang="scss">
  746. .form-title {
  747. text-align: center;
  748. font-size: 20px;
  749. width: 100%;
  750. margin-bottom: 20px;
  751. }
  752. .mmse-form {
  753. max-width: 1200px;
  754. margin: 0 auto;
  755. background: #fff;
  756. .info-row {
  757. display: flex;
  758. gap: 40px;
  759. width: 100%;
  760. flex-direction: row;
  761. align-items: center;
  762. margin-bottom: 10px;
  763. .info-item {
  764. display: flex;
  765. align-items: center;
  766. gap: 8px;
  767. .label {
  768. width: 82px;
  769. text-align: right;
  770. margin-right: 4px;
  771. white-space: nowrap;
  772. }
  773. }
  774. }
  775. .form-body {
  776. border: 1px solid #333;
  777. padding: 15px;
  778. }
  779. // 调整 Element Plus 组件样式
  780. :deep(.el-input__inner) {
  781. height: 28px;
  782. line-height: 28px;
  783. border-top: none;
  784. border-left: none;
  785. border-right: none;
  786. border-radius: 0;
  787. padding: 0 4px;
  788. &:focus {
  789. border-color: #409eff;
  790. }
  791. }
  792. :deep(.el-checkbox__label),
  793. :deep(.el-radio__label) {
  794. padding-left: 4px;
  795. }
  796. }
  797. .row{
  798. margin-bottom: 12px;
  799. display: flex;
  800. flex-direction: row;
  801. align-items: center;
  802. text{
  803. text-align: right;
  804. margin-right: 4px;
  805. width: 82px;
  806. }
  807. }
  808. // NGASR自杀风险评估量表 特有样式
  809. .total-score-section {
  810. display: flex;
  811. justify-content: space-between;
  812. align-items: center;
  813. padding: 15px;
  814. background: #f5f7fa;
  815. border-radius: 4px;
  816. margin-bottom: 20px;
  817. .total-score {
  818. display: flex;
  819. align-items: baseline;
  820. gap: 4px;
  821. .score-label {
  822. font-size: 16px;
  823. font-weight: bold;
  824. }
  825. .score-value {
  826. font-size: 28px;
  827. font-weight: bold;
  828. color: #409eff;
  829. }
  830. .score-max {
  831. font-size: 14px;
  832. color: #909399;
  833. }
  834. }
  835. .risk-level {
  836. font-size: 16px;
  837. font-weight: bold;
  838. padding: 8px 16px;
  839. border-radius: 4px;
  840. &.risk-none {
  841. color: #67c23a;
  842. background: #f0f9eb;
  843. }
  844. &.risk-low {
  845. color: #e6a23c;
  846. background: #fdf6ec;
  847. }
  848. &.risk-medium {
  849. color: #f56c6c;
  850. background: #fef0f0;
  851. }
  852. &.risk-high {
  853. color: #f56c6c;
  854. background: #fef0f0;
  855. border: 1px solid #f56c6c;
  856. }
  857. }
  858. }
  859. .assessment-table {
  860. width: 100%;
  861. border-collapse: collapse;
  862. margin-bottom: 20px;
  863. table {
  864. width: 100%;
  865. border: 1px solid #333;
  866. th, td {
  867. border: 1px solid #333;
  868. padding: 12px;
  869. text-align: left;
  870. }
  871. th {
  872. background: #f5f7fa;
  873. font-weight: bold;
  874. text-align: center;
  875. }
  876. .criteria-col {
  877. width: 60%;
  878. }
  879. .score-col {
  880. width: 15%;
  881. text-align: center;
  882. }
  883. .select-col {
  884. width: 25%;
  885. text-align: center;
  886. }
  887. .criteria {
  888. text-align: left;
  889. }
  890. .score {
  891. text-align: center;
  892. font-weight: bold;
  893. }
  894. .select {
  895. text-align: center;
  896. :deep(.el-radio) {
  897. margin-right: 0;
  898. }
  899. }
  900. }
  901. }
  902. .remark-section {
  903. margin: 15px 0;
  904. padding: 12px;
  905. background: #f5f7fa;
  906. border-radius: 4px;
  907. border: 1px solid #e4e7ed;
  908. .remark-label {
  909. font-weight: bold;
  910. color: #606266;
  911. }
  912. .remark-text {
  913. color: #606266;
  914. }
  915. }
  916. .risk-judgment-section {
  917. margin: 20px 0;
  918. padding: 15px;
  919. background: #f5f7fa;
  920. border-radius: 4px;
  921. border: 1px solid #e4e7ed;
  922. .risk-judgment-title {
  923. font-weight: bold;
  924. font-size: 16px;
  925. margin-bottom: 12px;
  926. color: #303133;
  927. }
  928. .risk-options {
  929. display: flex;
  930. flex-wrap: wrap;
  931. gap: 20px;
  932. :deep(.el-radio) {
  933. margin-right: 0;
  934. }
  935. }
  936. }
  937. .preventive-section {
  938. margin: 20px 0;
  939. padding: 15px;
  940. background: #f5f7fa;
  941. border-radius: 4px;
  942. border: 1px solid #e4e7ed;
  943. .preventive-title {
  944. font-weight: bold;
  945. font-size: 16px;
  946. margin-bottom: 12px;
  947. color: #303133;
  948. }
  949. .preventive-options {
  950. display: flex;
  951. flex-wrap: wrap;
  952. gap: 15px;
  953. :deep(.el-checkbox) {
  954. margin-right: 20px;
  955. margin-bottom: 8px;
  956. }
  957. .other-input {
  958. width: 200px;
  959. margin-left: 10px;
  960. }
  961. }
  962. }
  963. .signature-section {
  964. margin: 20px 0;
  965. padding: 15px;
  966. background: #f5f7fa;
  967. border-radius: 4px;
  968. border: 1px solid #e4e7ed;
  969. .signature-row {
  970. display: flex;
  971. justify-content: space-between;
  972. align-items: center;
  973. gap: 20px;
  974. }
  975. .signature-item {
  976. display: flex;
  977. align-items: center;
  978. gap: 10px;
  979. &.date-item {
  980. :deep(.el-date-picker) {
  981. width: 150px;
  982. }
  983. }
  984. }
  985. .signature-label {
  986. font-weight: bold;
  987. white-space: nowrap;
  988. }
  989. .signature-input {
  990. width: 150px;
  991. }
  992. .date-picker {
  993. width: 150px;
  994. }
  995. }
  996. .note-section {
  997. margin-top: 20px;
  998. padding: 15px;
  999. background: #f5f7fa;
  1000. border-radius: 4px;
  1001. border: 1px solid #e4e7ed;
  1002. .note-title {
  1003. font-weight: bold;
  1004. font-size: 16px;
  1005. margin-bottom: 12px;
  1006. color: #303133;
  1007. }
  1008. .note-content {
  1009. font-size: 13px;
  1010. line-height: 1.8;
  1011. color: #606266;
  1012. p {
  1013. margin: 5px 0;
  1014. }
  1015. .indent {
  1016. margin-left: 20px;
  1017. }
  1018. }
  1019. }
  1020. </style>