|
|
@@ -0,0 +1,306 @@
|
|
|
+<template>
|
|
|
+ <Dialog
|
|
|
+ v-model="dialogVisible"
|
|
|
+ :title="itemTitle"
|
|
|
+ width="70%"
|
|
|
+ class="form-tag-dialog life-care-plan-form special-nursing-plan-form"
|
|
|
+ @close="handleClosed"
|
|
|
+ scroll
|
|
|
+ >
|
|
|
+ <el-form
|
|
|
+ ref="formRef"
|
|
|
+ :model="dataForm"
|
|
|
+ :rules="dataRule"
|
|
|
+ label-width="80px"
|
|
|
+ :toggleType="isDetail"
|
|
|
+ >
|
|
|
+ <div class="info-title">基本信息</div>
|
|
|
+ <div class="info-wrap">
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="12" :xs="24">
|
|
|
+ <el-form-item label="长者姓名" prop="elderId">
|
|
|
+ <SelectElder
|
|
|
+ v-model="dataForm.elderId"
|
|
|
+ @elder="handleElder"
|
|
|
+ :style="[{ width: dataForm.id ? '30%' : '100%' }]"
|
|
|
+ :toggleType="!!dataForm.id"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12" :xs="24">
|
|
|
+ <el-form-item label="床位号" prop="bedName">
|
|
|
+ <el-input v-if="!isDetail" v-model="dataForm.bedName" disabled />
|
|
|
+ <el-text v-else>{{ dataForm.bedName }}</el-text>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="12" :xs="24">
|
|
|
+ <el-form-item label="护理等级" prop="nurseLevelName">
|
|
|
+ <el-input v-if="!isDetail" v-model="dataForm.nurseLevelName" disabled />
|
|
|
+ <el-text v-else>{{ dataForm.nurseLevelName }}</el-text>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
+ <div class="info">
|
|
|
+ <div class="info-title">护理项目</div>
|
|
|
+ <span v-show="dataForm.elderId">
|
|
|
+ <el-button type="primary" class="left" @click="handleAdd" v-if="!isDetail">
|
|
|
+ <Icon icon="ep:zoom-in" class="mr-5px" />添加项目
|
|
|
+ </el-button>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <div class="info-wrap">
|
|
|
+ <el-row>
|
|
|
+ <el-col
|
|
|
+ :xs="24"
|
|
|
+ :sm="24"
|
|
|
+ :md="24"
|
|
|
+ :lg="24"
|
|
|
+ class="mb5"
|
|
|
+ v-for="(p, i) in dataForm.items"
|
|
|
+ :key="i"
|
|
|
+ >
|
|
|
+ <div class="border item-row">
|
|
|
+ <div class="item-left">
|
|
|
+ <el-checkbox
|
|
|
+ :label="p.nurseItemName"
|
|
|
+ v-model="p.checked"
|
|
|
+ @change="(v) => handleChangeCheckBox(!!v, p)"
|
|
|
+ v-if="!isDetail"
|
|
|
+ />
|
|
|
+ <div v-else class="itemName">{{ p.nurseItemName }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="handleClosed">取消</el-button>
|
|
|
+ <el-button v-loading="formLoading" type="primary" @click="submitForm" v-if="!isDetail"
|
|
|
+ >确定</el-button
|
|
|
+ >
|
|
|
+ </template>
|
|
|
+ </Dialog>
|
|
|
+ <lifeItem ref="itemRef" category-type-name="生活护理" @success="getItemList" />
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import {
|
|
|
+ createSpecialNursingPlan,
|
|
|
+ updateSpecialNursingPlan,
|
|
|
+ getSpecialNursingPlan
|
|
|
+} from '@/api/elderly/nursing/special-plan'
|
|
|
+import type {
|
|
|
+ SpecialNursingPlanItemRespVO,
|
|
|
+ SpecialNursingPlanItemSaveReqVO,
|
|
|
+ SpecialNursingPlanSaveReqVO
|
|
|
+} from '@/api/elderly/nursing/special-plan'
|
|
|
+import { getTenantId } from '@/utils/auth'
|
|
|
+import { getElderInfoById } from '@/api/elderly/elder/elderly-Info'
|
|
|
+import lifeItem from './life-item-dialog.vue'
|
|
|
+
|
|
|
+defineOptions({ name: 'SpecialNursingPlanForm' })
|
|
|
+
|
|
|
+interface PlanItemRow {
|
|
|
+ /** 明细表主键,编辑时回填 */
|
|
|
+ id?: number
|
|
|
+ nurseItemId: number | string
|
|
|
+ nurseItemName: string
|
|
|
+ checked?: boolean
|
|
|
+}
|
|
|
+
|
|
|
+const { t } = useI18n()
|
|
|
+const message = useMessage()
|
|
|
+const dialogVisible = ref(false)
|
|
|
+const dataForm = ref({
|
|
|
+ id: '' as number | string | '',
|
|
|
+ elderId: '' as number | string | '',
|
|
|
+ elderName: '',
|
|
|
+ bedName: '',
|
|
|
+ nurseLevelName: '',
|
|
|
+ items: [] as PlanItemRow[],
|
|
|
+ tenantId: undefined as number | undefined
|
|
|
+})
|
|
|
+const resetSnapshot = reactive({
|
|
|
+ id: '',
|
|
|
+ elderId: '',
|
|
|
+ elderName: '',
|
|
|
+ bedName: '',
|
|
|
+ nurseLevelName: '',
|
|
|
+ items: [] as PlanItemRow[],
|
|
|
+ tenantId: undefined as number | undefined
|
|
|
+})
|
|
|
+const dataRule = ref({
|
|
|
+ elderId: [{ required: true, message: '长者姓名不能为空', trigger: 'blur' }]
|
|
|
+})
|
|
|
+const formLoading = ref(false)
|
|
|
+const isDetail = ref(false)
|
|
|
+
|
|
|
+const itemTitle = computed(() => {
|
|
|
+ return isDetail.value ? '详情' : !dataForm.value.id ? '新增' : '修改'
|
|
|
+})
|
|
|
+
|
|
|
+const normalizeItemsFromDetail = (list?: SpecialNursingPlanItemRespVO[]): PlanItemRow[] =>
|
|
|
+ (list || []).map((row) => ({
|
|
|
+ id: row.id != null ? Number(row.id) : undefined,
|
|
|
+ nurseItemId: row.nurseItemId as number | string,
|
|
|
+ nurseItemName: row.nurseItemName || '',
|
|
|
+ checked: true
|
|
|
+ }))
|
|
|
+
|
|
|
+/** 编辑/详情时计划接口不包含床位与护理等级,根据长者详情补全 */
|
|
|
+const fillElderBedAndNurseLevel = async (elderId?: number | string) => {
|
|
|
+ if (elderId == null || elderId === '') return
|
|
|
+ try {
|
|
|
+ const elder = (await getElderInfoById(elderId)) as Recordable
|
|
|
+ if (!elder) return
|
|
|
+ const bed = elder.bedName ?? elder.bed
|
|
|
+ const level = elder.nurseLevelName ?? elder.nursingLevelName ?? elder.nursingLevel ?? ''
|
|
|
+ if (bed !== undefined && bed !== null && bed !== '') {
|
|
|
+ dataForm.value.bedName = String(bed)
|
|
|
+ }
|
|
|
+ if (level !== undefined && level !== null && String(level).length) {
|
|
|
+ dataForm.value.nurseLevelName = String(level)
|
|
|
+ }
|
|
|
+ } catch {
|
|
|
+ // 静默:仍展示计划中已有或空白
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const open = async (id?: number | string, detail?: boolean, prefetch?: Recordable) => {
|
|
|
+ dataForm.value = JSON.parse(JSON.stringify(resetSnapshot))
|
|
|
+ dataForm.value.id = ''
|
|
|
+ isDetail.value = !!detail
|
|
|
+ dialogVisible.value = true
|
|
|
+ if (!id) return
|
|
|
+ try {
|
|
|
+ const res = await getSpecialNursingPlan(id)
|
|
|
+ dataForm.value.id = res.id ?? id
|
|
|
+ dataForm.value.elderId = res.elderId ?? ''
|
|
|
+ dataForm.value.elderName = res.elderName ?? ''
|
|
|
+ dataForm.value.tenantId = res.tenantId
|
|
|
+ dataForm.value.bedName = res.bedName ?? prefetch?.bedName ?? ''
|
|
|
+ dataForm.value.nurseLevelName = res.nurseLevelName ?? prefetch?.nurseLevelName ?? ''
|
|
|
+ await fillElderBedAndNurseLevel(res.elderId)
|
|
|
+ dataForm.value.items = normalizeItemsFromDetail(res.items || [])
|
|
|
+ if (!dataForm.value.items.length && prefetch?.elderId) {
|
|
|
+ message.warning('该计划暂未返回明细,请补充护理项目后保存')
|
|
|
+ }
|
|
|
+ } catch {
|
|
|
+ dialogVisible.value = false
|
|
|
+ message.error('获取特殊护理计划详情失败')
|
|
|
+ }
|
|
|
+}
|
|
|
+defineExpose({ open })
|
|
|
+
|
|
|
+const handleClosed = () => {
|
|
|
+ dataForm.value = JSON.parse(JSON.stringify(resetSnapshot))
|
|
|
+ dialogVisible.value = false
|
|
|
+}
|
|
|
+
|
|
|
+const itemRef = ref()
|
|
|
+const handleAdd = () => {
|
|
|
+ itemRef.value.open(dataForm.value.items)
|
|
|
+}
|
|
|
+
|
|
|
+const getItemList = (val: Recordable[]) => {
|
|
|
+ val.forEach((item) => {
|
|
|
+ dataForm.value.items.push({
|
|
|
+ nurseItemId: item.id,
|
|
|
+ nurseItemName: item.itemName,
|
|
|
+ checked: true
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const handleElder = (item: Recordable) => {
|
|
|
+ dataForm.value.elderName = item.elderName
|
|
|
+ dataForm.value.bedName = item.bedName
|
|
|
+ dataForm.value.nurseLevelName = item.nurseLevelName
|
|
|
+}
|
|
|
+
|
|
|
+const handleChangeCheckBox = (val: boolean, item: PlanItemRow) => {
|
|
|
+ if (!val) {
|
|
|
+ const index = dataForm.value.items.findIndex((p) => p.nurseItemId == item.nurseItemId)
|
|
|
+ if (index > -1) dataForm.value.items.splice(index, 1)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const formRef = ref()
|
|
|
+const emit = defineEmits(['success'])
|
|
|
+
|
|
|
+const buildTenantId = () => Number(getTenantId())
|
|
|
+
|
|
|
+const submitForm = async () => {
|
|
|
+ if (!formRef.value) return
|
|
|
+ try {
|
|
|
+ await formRef.value.validate()
|
|
|
+ } catch {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const tenantId = buildTenantId()
|
|
|
+ const planId = dataForm.value.id ? Number(dataForm.value.id) : undefined
|
|
|
+ const itemsPayload: SpecialNursingPlanItemSaveReqVO[] = []
|
|
|
+ ;(dataForm.value.items || []).forEach((row) => {
|
|
|
+ if (!row.checked && row.checked !== undefined) return
|
|
|
+ const one: SpecialNursingPlanItemSaveReqVO = {
|
|
|
+ nurseItemId: Number(row.nurseItemId),
|
|
|
+ nurseItemName: row.nurseItemName,
|
|
|
+ tenantId
|
|
|
+ }
|
|
|
+ if (planId) {
|
|
|
+ one.specialNursingPlanId = planId
|
|
|
+ if (row.id != null) one.id = row.id
|
|
|
+ }
|
|
|
+ itemsPayload.push(one)
|
|
|
+ })
|
|
|
+ const payload: SpecialNursingPlanSaveReqVO = {
|
|
|
+ elderId: Number(dataForm.value.elderId),
|
|
|
+ elderName: dataForm.value.elderName || undefined,
|
|
|
+ tenantId,
|
|
|
+ items: itemsPayload
|
|
|
+ }
|
|
|
+ if (planId) payload.id = planId
|
|
|
+
|
|
|
+ try {
|
|
|
+ formLoading.value = true
|
|
|
+ await (planId ? updateSpecialNursingPlan(payload) : createSpecialNursingPlan(payload))
|
|
|
+ message.success(planId ? t('common.updateSuccess') : t('common.createSuccess'))
|
|
|
+ handleClosed()
|
|
|
+ emit('success')
|
|
|
+ } finally {
|
|
|
+ formLoading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+<style lang="scss" scoped>
|
|
|
+.special-nursing-plan-form {
|
|
|
+ .item-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+ .item-left {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ min-height: 32px;
|
|
|
+ padding: 1px 11px;
|
|
|
+ flex: 1;
|
|
|
+ box-shadow: 0 0 0 1px var(--el-input-border-color, var(--el-border-color)) inset;
|
|
|
+ border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
|
|
|
+ }
|
|
|
+ .itemName {
|
|
|
+ line-height: 30px;
|
|
|
+ }
|
|
|
+ .info {
|
|
|
+ position: relative;
|
|
|
+ .left {
|
|
|
+ position: absolute;
|
|
|
+ left: 150px;
|
|
|
+ top: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|