| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397 |
- <template>
- <Dialog
- v-model="dialogVisible"
- :title="itemTitle"
- width="70%"
- class="form-tag-dialog life-care-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"
- />
- <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-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-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"
- >
- <el-row :gutter="20">
- <el-col :span="16">
- <div class="item-left">
- <el-checkbox
- :label="`${p.nurseItemName}(${p.frequencyCategory})`"
- v-model="p.checked"
- @change="(arg) => handleChangeCheckBox(arg, p)"
- v-if="!isDetail"
- />
- <div v-else class="itemName"
- >{{ p.nurseItemName }}({{ p.frequencyCategory }})</div
- >
- </div>
- </el-col>
- <el-col :span="8">
- <div class="item-time" v-if="!isDetail">
- <span class="time-label required" v-if="p.frequencyCategoryType == 1"
- >护理开始时间</span
- >
- <el-time-picker
- v-if="p.frequencyCategoryType == 1"
- v-model="p.beginTime"
- value-format="HH:mm:ss"
- placeholder="请选择开始时间"
- />
- </div>
- <div v-else class="item-time detail-time">
- <span class="time-label" v-if="p.frequencyCategoryType == 1">护理开始时间</span>
- <span v-if="p.frequencyCategoryType == 1">{{
- formatBeginTimeDetail(p.beginTime)
- }}</span>
- </div>
- </el-col>
- </el-row>
- </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" @success="getItemList" />
- </template>
- <script setup lang="ts">
- import {
- createNursingPlan,
- updateNursingPlan,
- getNursingPlanById,
- findNurseItemListByName
- } from '@/api/elderly/nursing'
- import lifeItem from './life-item-dialog.vue'
- import { planType } from '../types'
- defineOptions({ name: 'LifeCarePlanForm' })
- 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, 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 ? '新增' : '修改'
- })
- /** 详情接口可能返回时间戳或整段日期时间,转为时间选择器用的 HH:mm:ss */
- const toTimePickerValue = (beginTime: unknown): string => {
- if (beginTime == null || beginTime === '') return ''
- if (typeof beginTime === 'number') {
- const d = new Date(beginTime)
- if (Number.isNaN(d.getTime())) return ''
- const pad = (n: number) => String(n).padStart(2, '0')
- return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
- }
- if (typeof beginTime === 'string') {
- if (/^\d+$/.test(beginTime)) return toTimePickerValue(Number(beginTime))
- if (beginTime.includes(' ')) return beginTime.split(' ')[1] || ''
- }
- return String(beginTime)
- }
- /** 详情展示:时间戳或日期时间转为可读时间 */
- const formatBeginTimeDetail = (beginTime: unknown): string => {
- if (beginTime == null || beginTime === '') return '-'
- if (typeof beginTime === 'number' || (typeof beginTime === 'string' && /^\d+$/.test(beginTime))) {
- const d = new Date(Number(beginTime))
- if (Number.isNaN(d.getTime())) return '-'
- const pad = (n: number) => String(n).padStart(2, '0')
- return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
- }
- if (typeof beginTime === 'string' && beginTime.includes(' ')) {
- return beginTime.split(' ')[1] || '-'
- }
- return String(beginTime)
- }
- /** 打开弹窗 */
- 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
- dataForm.value.items?.forEach((item) => {
- if (item.frequencyCategoryType === 1 && item.beginTime != null && item.beginTime !== '') {
- item.beginTime = toTimePickerValue(item.beginTime)
- }
- })
- }
- }
- 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 handleClosed = () => {
- dataForm.value = { ...resetFormField }
- dialogVisible.value = false
- }
- const itemRef = ref()
- const handleAdd = () => {
- itemRef.value.open(dataForm.value.items)
- }
- const getItemList = (val) => {
- console.log('val', val)
- // 添加的内容放到护理项目中
- val.map((item) => {
- dataForm.value.items.push({
- nurseItemId: item.id,
- nurseItemName: item.itemName,
- frequencyType: item.frequencyType,
- frequency: item.frequency,
- frequencyCategory: item.frequencyCategory,
- frequencyCategoryType: item.frequencyCategoryType,
- checked: true,
- price: item.price,
- isExtra: item.type == 1 ? 1 : 0,
- beginTime: ''
- })
- })
- }
- // 选择长者
- const handleElder = async (item) => {
- dataForm.value.elderName = item.elderName
- dataForm.value.bedName = item.bedName
- dataForm.value.nurseLevelName = item.nurseLevelName
- }
- const handleChangeCheckBox = (val, item) => {
- if (!val) {
- const index = dataForm.value.items.findIndex((p) => item.nurseItemId == p.nurseItemId)
- 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 missingTime = dataForm.value.items.find(
- (item) => item.checked && !item.beginTime && item.frequencyCategoryType == 1
- )
- if (missingTime) {
- message.warning(`请先选择【${missingTime.nurseItemName}】的护理开始时间`)
- return
- }
- try {
- formLoading.value = true
- let params = JSON.parse(JSON.stringify(dataForm.value))
- ;(params.type = route.path.indexOf('medical-care-plan') > -1 ? 2 : 1), // 2:医疗护理 1 生活护理,
- params.items.forEach((item) => {
- if (item.frequencyCategoryType == 1 && item.beginTime) {
- item.beginTime = new Date(`${params.effectiveDate} ${item.beginTime}`).getTime()
- }
- })
- const res = params.id ? await updateNursingPlan(params) : await createNursingPlan(params)
- if (res) {
- message.success(t('common.updateSuccess'))
- 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;
- }
- .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));
- }
- .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;
- }
- .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>
|