AddForm.vue 11 KB

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