|
|
@@ -3,7 +3,7 @@
|
|
|
v-model="dialogVisible"
|
|
|
:title="itemTitle"
|
|
|
width="70%"
|
|
|
- class="form-tag-dialog life-care-plan-form"
|
|
|
+ class="form-tag-dialog life-care-plan-form special-nursing-plan-form"
|
|
|
@close="handleClosed"
|
|
|
scroll
|
|
|
>
|
|
|
@@ -25,28 +25,20 @@
|
|
|
:style="[{ width: dataForm.id ? '30%' : '100%' }]"
|
|
|
:toggleType="!!dataForm.id"
|
|
|
/>
|
|
|
- <span v-show="dataForm.id">
|
|
|
- {{ dataForm.bedName }} {{ dataForm.nurseLevelName }}
|
|
|
- </span>
|
|
|
</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-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-col :span="12" :xs="24">
|
|
|
- <el-form-item label="生效日期" prop="effectiveDate">
|
|
|
- <TgDatePicker v-model="dataForm.effectiveDate" />
|
|
|
+ <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>
|
|
|
@@ -75,7 +67,7 @@
|
|
|
<el-checkbox
|
|
|
:label="p.nurseItemName"
|
|
|
v-model="p.checked"
|
|
|
- @change="(arg) => handleChangeCheckBox(arg, p)"
|
|
|
+ @change="(v) => handleChangeCheckBox(!!v, p)"
|
|
|
v-if="!isDetail"
|
|
|
/>
|
|
|
<div v-else class="itemName">{{ p.nurseItemName }}</div>
|
|
|
@@ -92,92 +84,120 @@
|
|
|
>
|
|
|
</template>
|
|
|
</Dialog>
|
|
|
- <lifeItem ref="itemRef" @success="getItemList" />
|
|
|
+ <lifeItem ref="itemRef" category-type-name="生活护理" @success="getItemList" />
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
import {
|
|
|
- createNursingPlan,
|
|
|
- updateNursingPlan,
|
|
|
- getNursingPlanById,
|
|
|
- findNurseItemListByName
|
|
|
-} from '@/api/elderly/nursing'
|
|
|
+ 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'
|
|
|
-import { planType } from '../types'
|
|
|
|
|
|
-defineOptions({ name: 'LifeCarePlanForm' })
|
|
|
+defineOptions({ name: 'SpecialNursingPlanForm' })
|
|
|
+
|
|
|
+interface PlanItemRow {
|
|
|
+ /** 明细表主键,编辑时回填 */
|
|
|
+ id?: number
|
|
|
+ nurseItemId: number | string
|
|
|
+ nurseItemName: string
|
|
|
+ checked?: boolean
|
|
|
+}
|
|
|
|
|
|
-const { t } = useI18n() // 国际化
|
|
|
-const message = useMessage() // 消息弹窗
|
|
|
+const { t } = useI18n()
|
|
|
+const message = useMessage()
|
|
|
const dialogVisible = ref(false)
|
|
|
-const state = reactive<planType>({
|
|
|
- dataForm: {
|
|
|
- id: '',
|
|
|
- elderId: '',
|
|
|
- elderName: '',
|
|
|
- bedName: '',
|
|
|
- nurseLevelName: '',
|
|
|
- effectiveDate: '',
|
|
|
- items: [],
|
|
|
- extraItems: [],
|
|
|
- },
|
|
|
- dataRule: {
|
|
|
- elderId: [{ required: true, message: '长者姓名不能为空', trigger: 'blur' }],
|
|
|
- effectiveDate: [{ required: true, message: '生效日期不能为空', trigger: 'blur' }]
|
|
|
- },
|
|
|
+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 { dataForm, dataRule } = toRefs(state)
|
|
|
-const resetFormField = reactive({ ...dataForm.value })
|
|
|
-const route = useRoute()
|
|
|
const formLoading = ref(false)
|
|
|
const isDetail = ref(false)
|
|
|
|
|
|
-// 弹窗标题
|
|
|
const itemTitle = computed(() => {
|
|
|
return isDetail.value ? '详情' : !dataForm.value.id ? '新增' : '修改'
|
|
|
})
|
|
|
|
|
|
-/** 打开弹窗 */
|
|
|
-const open = async (id, detail) => {
|
|
|
- dataForm.value.id=''
|
|
|
- dialogVisible.value = true
|
|
|
- isDetail.value = detail
|
|
|
- if (id) {
|
|
|
- const res = await getNursingPlanById(id)
|
|
|
- // 默认勾选护理项目
|
|
|
- res.items.map((item) => {
|
|
|
- item.checked = true
|
|
|
- })
|
|
|
- res.extraItems.map((item) => {
|
|
|
- item.checked = true
|
|
|
- })
|
|
|
- // 匹配额外项目价格
|
|
|
- dataForm.value = res
|
|
|
- await formatExtraItem()
|
|
|
- dataForm.value.items = res.items?.length > 0 ? res.items : res.extraItems
|
|
|
- console.log('dataForm.value', dataForm.value)
|
|
|
+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 {
|
|
|
+ // 静默:仍展示计划中已有或空白
|
|
|
}
|
|
|
}
|
|
|
-defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
|
|
|
|
|
-const formatExtraItem = async () => {
|
|
|
- if (dataForm.value.extraItems.length) {
|
|
|
- const res = await findNurseItemListByName({
|
|
|
- categoryTypeName: '生活护理',
|
|
|
- nurseItemName: ''
|
|
|
- })
|
|
|
- dataForm.value.extraItems.map((e) => {
|
|
|
- res.map((r) => {
|
|
|
- if (e.nurseItemId == r.id) {
|
|
|
- e.price = r.price
|
|
|
- }
|
|
|
- })
|
|
|
- })
|
|
|
+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 = {...resetFormField}
|
|
|
+ dataForm.value = JSON.parse(JSON.stringify(resetSnapshot))
|
|
|
dialogVisible.value = false
|
|
|
}
|
|
|
|
|
|
@@ -186,87 +206,81 @@ const handleAdd = () => {
|
|
|
itemRef.value.open(dataForm.value.items)
|
|
|
}
|
|
|
|
|
|
-const getItemList = (val) => {
|
|
|
- // 添加的内容放到护理项目中
|
|
|
- val.map((item) => {
|
|
|
+const getItemList = (val: Recordable[]) => {
|
|
|
+ val.forEach((item) => {
|
|
|
dataForm.value.items.push({
|
|
|
nurseItemId: item.id,
|
|
|
nurseItemName: item.itemName,
|
|
|
- frequency: 1,
|
|
|
- frequencyUnit: item.frequency,
|
|
|
- operatingMode: item.operatingMode,
|
|
|
- checked: true,
|
|
|
- price: item.price,
|
|
|
- isExtra: item.type == 1 ? 1 : 0,
|
|
|
+ checked: true
|
|
|
})
|
|
|
})
|
|
|
}
|
|
|
|
|
|
-// 选择长者
|
|
|
-const handleElder = async (item) => {
|
|
|
+const handleElder = (item: Recordable) => {
|
|
|
dataForm.value.elderName = item.elderName
|
|
|
dataForm.value.bedName = item.bedName
|
|
|
dataForm.value.nurseLevelName = item.nurseLevelName
|
|
|
}
|
|
|
|
|
|
-const handleChangeCheckBox = (val, item) => {
|
|
|
+const handleChangeCheckBox = (val: boolean, item: PlanItemRow) => {
|
|
|
if (!val) {
|
|
|
- const index = dataForm.value.items.findIndex((p) => item.nurseItemId == p.nurseItemId)
|
|
|
- dataForm.value.items.splice(index, 1)
|
|
|
+ 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']) // 定义 success 事件,用于操作成功后的回调
|
|
|
-const submitForm = async () => {
|
|
|
- // 校验表单
|
|
|
- if (!formRef.value) return
|
|
|
- const valid = await formRef.value.validate()
|
|
|
- if (!valid) return
|
|
|
+const emit = defineEmits(['success'])
|
|
|
|
|
|
+const buildTenantId = () => Number(getTenantId())
|
|
|
|
|
|
+const submitForm = async () => {
|
|
|
+ if (!formRef.value) return
|
|
|
try {
|
|
|
- formLoading.value = true
|
|
|
- const params = {
|
|
|
- type: route.path.indexOf('medical-care-plan') > -1 ? 2 : 1, // 2:医疗护理 1 生活护理,
|
|
|
- ...dataForm.value,
|
|
|
+ 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
|
|
|
}
|
|
|
- const res = params.id
|
|
|
- ? await updateNursingPlan(params)
|
|
|
- : await createNursingPlan(params)
|
|
|
- if (res) {
|
|
|
- message.success(t('common.updateSuccess'))
|
|
|
- handleClosed()
|
|
|
- // 发送操作成功的事件
|
|
|
- emit('success')
|
|
|
+ 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>
|
|
|
-.life-care-plan-form {
|
|
|
- .sInput {
|
|
|
- border: none;
|
|
|
- border-bottom: 1px solid #999;
|
|
|
- outline: none;
|
|
|
- background-color: transparent;
|
|
|
- }
|
|
|
- .itemName {
|
|
|
- line-height: 30px;
|
|
|
- }
|
|
|
- // .border {
|
|
|
- // padding: 1px 11px;
|
|
|
- // 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));
|
|
|
- // }
|
|
|
+.special-nursing-plan-form {
|
|
|
.item-row {
|
|
|
display: flex;
|
|
|
- justify-content: space-between;
|
|
|
align-items: center;
|
|
|
- gap: 12px;
|
|
|
- flex-wrap: wrap;
|
|
|
}
|
|
|
.item-left {
|
|
|
display: flex;
|
|
|
@@ -277,67 +291,16 @@ const submitForm = async () => {
|
|
|
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));
|
|
|
}
|
|
|
- .item-meta {
|
|
|
- display: flex;
|
|
|
- gap: 8px;
|
|
|
- }
|
|
|
- .item-time {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 8px;
|
|
|
- }
|
|
|
- .time-label {
|
|
|
- white-space: nowrap;
|
|
|
- color: var(--el-text-color-secondary);
|
|
|
- }
|
|
|
- .detail-time {
|
|
|
- color: var(--el-text-color-regular);
|
|
|
- }
|
|
|
- .border-warning {
|
|
|
- border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
|
|
|
- box-shadow: 0 0 0 1px var(--el-input-border-color, var(--el-color-warning)) inset;
|
|
|
- }
|
|
|
- .warning {
|
|
|
- background-color: var(--el-color-warning-light-9);
|
|
|
- border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
|
|
|
- box-shadow: 0 0 0 1px var(--el-input-border-color, var(--el-color-warning)) inset;
|
|
|
+ .itemName {
|
|
|
+ line-height: 30px;
|
|
|
}
|
|
|
.info {
|
|
|
position: relative;
|
|
|
-
|
|
|
.left {
|
|
|
position: absolute;
|
|
|
left: 150px;
|
|
|
top: 8px;
|
|
|
}
|
|
|
-
|
|
|
- .right {
|
|
|
- position: absolute;
|
|
|
- right: 10px;
|
|
|
- top: 10px;
|
|
|
- }
|
|
|
-
|
|
|
- .el-dropdown-link {
|
|
|
- cursor: pointer;
|
|
|
- color: var(--el-color-primary);
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-</style>
|
|
|
-<style lang="scss">
|
|
|
-.life-care-plan-form {
|
|
|
- .extra {
|
|
|
- .el-select__wrapper {
|
|
|
- box-shadow: 0 0 0 1px var(--el-color-warning) inset;
|
|
|
- background-color: var(--el-color-warning-light-9);
|
|
|
- }
|
|
|
- .el-input-number {
|
|
|
- .el-input__wrapper {
|
|
|
- box-shadow: 0 0 0 1px var(--el-color-warning) inset;
|
|
|
- }
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
</style>
|