AddForm.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  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="attack-risk-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. <RiskDisclosureBody
  51. v-model="riskDisclosureForm"
  52. :is-text-mode="isDetail"
  53. />
  54. </div>
  55. </div>
  56. <template #footer>
  57. <el-button @click="handleClosed">关闭</el-button>
  58. <el-button style="margin-left: 22px;margin-right: 30px" v-loading="formLoading" type="primary" v-show="!isDetail" @click="submitForm">确定</el-button>
  59. </template>
  60. </el-drawer>
  61. </template>
  62. <script lang="ts" setup>
  63. import { computed, ref, watch, reactive } from 'vue'
  64. import dayjs from 'dayjs'
  65. import RiskDisclosureBody from '../components/RiskDisclosureBody.vue'
  66. import { attackRiskCreate, attackRiskUpdate } from "@/api/social-work";
  67. const message = useMessage() // 消息弹窗
  68. const { t } = useI18n() // 国际化
  69. const title = ref('')
  70. const dialogVisible = ref(false) // 弹窗
  71. const formRef = ref() // 表单 Ref
  72. const riskDisclosureForm = ref() // 表单 Ref
  73. const isDetail = ref(false) // 是否详情打开
  74. const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
  75. let dataForm = ref({
  76. // 表单字段
  77. id: undefined,
  78. idCard: '',
  79. contractNumber: '', //档案号
  80. elderName: '',//长者姓名
  81. bedName: '', //床位号
  82. elderAge: '', //年龄
  83. elderSex: '', //性别
  84. checkInTime: '', //入院日期
  85. elderId: '',
  86. tenantId: undefined
  87. })
  88. const elderUp = (e) => {
  89. dataForm.value.elderName = e.elderName
  90. dataForm.value.elderId = e.id
  91. dataForm.value.elderSex = e.elderSex === 1 ? '男' : '女'
  92. dataForm.value.bedName = e.bedName || ''
  93. dataForm.value.checkInTime = e.checkInTime
  94. dataForm.value.contractNumber = e.contractNumber||e.fileNumber
  95. dataForm.value.elderAge = e.elderAge
  96. }
  97. // ========== 攻击风险因素评估量表 表单序列化方法 ==========
  98. defineExpose({ open }) // 提供 open 方法,用于打开弹窗
  99. /** 提交表单 */
  100. const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
  101. const submitForm = async () => {
  102. if (formLoading.value) {
  103. return
  104. }
  105. formLoading.value = true
  106. // 提交请求
  107. try {
  108. const assessData = serializeFormData()
  109. const tempParams = {
  110. ...dataForm.value,
  111. assessData: JSON.stringify(assessData),
  112. attackLevel: form.attackLevel,
  113. riskLevel: form.riskLevel,
  114. assessor: form.assessor,
  115. assessScore: form.attackLevel,
  116. assessDate: form.assessDate ? dayjs(form.assessDate).format('YYYY-MM-DD') : ''
  117. }
  118. if (dataForm.value.id) {
  119. const res = await attackRiskUpdate(tempParams)
  120. if (res) {
  121. message.success(t('common.updateSuccess'))
  122. dialogVisible.value = false
  123. // 发送操作成功的事件
  124. emit('success')
  125. }
  126. } else {
  127. const res = await attackRiskCreate(tempParams)
  128. if (res) {
  129. message.success(t('common.createSuccess'))
  130. dialogVisible.value = false
  131. // 发送操作成功的事件
  132. emit('success')
  133. }
  134. }
  135. } finally {
  136. setTimeout(() => {
  137. formLoading.value = false
  138. }, 500)
  139. }
  140. }
  141. /** 重置表单 */
  142. const resetForm = () => {
  143. formRef.value?.resetFields()
  144. }
  145. // 关闭表单
  146. const handleClosed = () => {
  147. dialogVisible.value = false
  148. resetForm()
  149. }
  150. </script>
  151. <style scoped lang="scss">
  152. .form-title {
  153. text-align: center;
  154. font-size: 20px;
  155. width: 100%;
  156. margin-bottom: 20px;
  157. }
  158. .attack-risk-form {
  159. max-width: 1200px;
  160. margin: 0 auto;
  161. background: #fff;
  162. .info-row {
  163. display: flex;
  164. gap: 40px;
  165. width: 100%;
  166. flex-direction: row;
  167. align-items: center;
  168. margin-bottom: 10px;
  169. .info-item {
  170. display: flex;
  171. align-items: center;
  172. gap: 8px;
  173. .label {
  174. width: 82px;
  175. text-align: right;
  176. margin-right: 4px;
  177. white-space: nowrap;
  178. }
  179. }
  180. }
  181. .form-body {
  182. border: 1px solid #333;
  183. padding: 15px;
  184. }
  185. // 调整 Element Plus 组件样式
  186. :deep(.el-input__inner) {
  187. height: 28px;
  188. line-height: 28px;
  189. border-top: none;
  190. border-left: none;
  191. border-right: none;
  192. border-radius: 0;
  193. padding: 0 4px;
  194. &:focus {
  195. border-color: #409eff;
  196. }
  197. }
  198. :deep(.el-checkbox__label),
  199. :deep(.el-radio__label) {
  200. padding-left: 4px;
  201. }
  202. }
  203. .row{
  204. margin-bottom: 12px;
  205. display: flex;
  206. flex-direction: row;
  207. align-items: center;
  208. text{
  209. text-align: right;
  210. margin-right: 4px;
  211. width: 82px;
  212. }
  213. }
  214. // NGASR自杀风险评估量表 特有样式
  215. .total-score-section {
  216. display: flex;
  217. justify-content: space-between;
  218. align-items: center;
  219. padding: 15px;
  220. background: #f5f7fa;
  221. border-radius: 4px;
  222. margin-bottom: 20px;
  223. .total-score {
  224. display: flex;
  225. align-items: baseline;
  226. gap: 4px;
  227. .score-label {
  228. font-size: 16px;
  229. font-weight: bold;
  230. }
  231. .score-value {
  232. font-size: 28px;
  233. font-weight: bold;
  234. color: #409eff;
  235. }
  236. .score-max {
  237. font-size: 14px;
  238. color: #909399;
  239. }
  240. }
  241. .risk-level {
  242. font-size: 16px;
  243. font-weight: bold;
  244. padding: 8px 16px;
  245. border-radius: 4px;
  246. &.risk-none {
  247. color: #67c23a;
  248. background: #f0f9eb;
  249. }
  250. &.risk-low {
  251. color: #e6a23c;
  252. background: #fdf6ec;
  253. }
  254. &.risk-medium {
  255. color: #f56c6c;
  256. background: #fef0f0;
  257. }
  258. &.risk-high {
  259. color: #f56c6c;
  260. background: #fef0f0;
  261. border: 1px solid #f56c6c;
  262. }
  263. }
  264. }
  265. .assessment-table {
  266. width: 100%;
  267. border-collapse: collapse;
  268. margin-bottom: 20px;
  269. table {
  270. width: 100%;
  271. border: 1px solid #333;
  272. th, td {
  273. border: 1px solid #333;
  274. padding: 12px;
  275. text-align: left;
  276. vertical-align: top;
  277. }
  278. th {
  279. background: #f5f7fa;
  280. font-weight: bold;
  281. text-align: center;
  282. }
  283. .content-col {
  284. width: 65%;
  285. }
  286. .level-col {
  287. width: 10%;
  288. text-align: center;
  289. }
  290. .select-col {
  291. width: 25%;
  292. text-align: center;
  293. }
  294. .content {
  295. text-align: left;
  296. .content-title {
  297. font-weight: bold;
  298. margin-bottom: 8px;
  299. }
  300. .content-item {
  301. margin-left: 15px;
  302. margin-bottom: 4px;
  303. font-size: 13px;
  304. }
  305. }
  306. .level {
  307. text-align: center;
  308. font-weight: bold;
  309. }
  310. .select {
  311. text-align: center;
  312. :deep(.el-radio) {
  313. margin-right: 0;
  314. }
  315. }
  316. }
  317. }
  318. .risk-judgment-section {
  319. margin: 20px 0;
  320. padding: 15px;
  321. background: #f5f7fa;
  322. border-radius: 4px;
  323. border: 1px solid #e4e7ed;
  324. .risk-judgment-title {
  325. font-weight: bold;
  326. font-size: 16px;
  327. margin-bottom: 12px;
  328. color: #303133;
  329. }
  330. .risk-options {
  331. display: flex;
  332. flex-wrap: wrap;
  333. gap: 20px;
  334. :deep(.el-radio) {
  335. margin-right: 0;
  336. }
  337. }
  338. }
  339. .preventive-section {
  340. margin: 20px 0;
  341. padding: 15px;
  342. background: #f5f7fa;
  343. border-radius: 4px;
  344. border: 1px solid #e4e7ed;
  345. .preventive-title {
  346. font-weight: bold;
  347. font-size: 16px;
  348. margin-bottom: 12px;
  349. color: #303133;
  350. }
  351. .preventive-options {
  352. display: flex;
  353. flex-wrap: wrap;
  354. gap: 15px;
  355. :deep(.el-checkbox) {
  356. margin-right: 20px;
  357. margin-bottom: 8px;
  358. }
  359. .other-input {
  360. width: 200px;
  361. margin-left: 10px;
  362. }
  363. }
  364. }
  365. .signature-section {
  366. margin: 20px 0;
  367. padding: 15px;
  368. background: #f5f7fa;
  369. border-radius: 4px;
  370. border: 1px solid #e4e7ed;
  371. .signature-row {
  372. display: flex;
  373. justify-content: space-between;
  374. align-items: center;
  375. gap: 20px;
  376. }
  377. .signature-item {
  378. display: flex;
  379. align-items: center;
  380. gap: 10px;
  381. &.date-item {
  382. :deep(.el-date-picker) {
  383. width: 150px;
  384. }
  385. }
  386. }
  387. .signature-label {
  388. font-weight: bold;
  389. white-space: nowrap;
  390. }
  391. .signature-input {
  392. width: 150px;
  393. }
  394. .date-picker {
  395. width: 150px;
  396. }
  397. }
  398. .note-section {
  399. margin-top: 20px;
  400. padding: 15px;
  401. background: #f5f7fa;
  402. border-radius: 4px;
  403. border: 1px solid #e4e7ed;
  404. .note-title {
  405. font-weight: bold;
  406. font-size: 16px;
  407. margin-bottom: 12px;
  408. color: #303133;
  409. }
  410. .note-content {
  411. font-size: 13px;
  412. line-height: 1.8;
  413. color: #606266;
  414. p {
  415. margin: 5px 0;
  416. }
  417. .indent {
  418. margin-left: 20px;
  419. }
  420. }
  421. }
  422. </style>