门诊医生预约科室管理功能的完善
This commit is contained in:
@@ -3,6 +3,7 @@ package com.openhis.web.appointmentmanage.appservice.impl;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.core.common.core.domain.R;
|
||||
import com.openhis.appointmentmanage.domain.DoctorSchedule;
|
||||
import com.openhis.appointmentmanage.mapper.DoctorScheduleMapper;
|
||||
import com.openhis.appointmentmanage.service.IDoctorScheduleService;
|
||||
import com.openhis.web.appointmentmanage.appservice.IDoctorScheduleAppService;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -14,6 +15,9 @@ import java.util.List;
|
||||
public class DoctorScheduleAppServiceImpl implements IDoctorScheduleAppService {
|
||||
@Resource
|
||||
private IDoctorScheduleService doctorScheduleService;
|
||||
|
||||
@Resource
|
||||
private DoctorScheduleMapper doctorScheduleMapper;
|
||||
|
||||
|
||||
@Override
|
||||
@@ -27,8 +31,35 @@ public class DoctorScheduleAppServiceImpl implements IDoctorScheduleAppService {
|
||||
if (ObjectUtil.isEmpty(doctorSchedule)) {
|
||||
return R.fail("医生排班不能为空");
|
||||
}
|
||||
boolean save = doctorScheduleService.save(doctorSchedule);
|
||||
return R.ok(save);
|
||||
// 创建新对象,排除id字段(数据库id列是GENERATED ALWAYS,由数据库自动生成)
|
||||
DoctorSchedule newSchedule = new DoctorSchedule();
|
||||
newSchedule.setWeekday(doctorSchedule.getWeekday());
|
||||
newSchedule.setTimePeriod(doctorSchedule.getTimePeriod());
|
||||
newSchedule.setDoctor(doctorSchedule.getDoctor());
|
||||
newSchedule.setClinic(doctorSchedule.getClinic());
|
||||
newSchedule.setStartTime(doctorSchedule.getStartTime());
|
||||
newSchedule.setEndTime(doctorSchedule.getEndTime());
|
||||
newSchedule.setLimitNumber(doctorSchedule.getLimitNumber());
|
||||
// call_sign_record 字段不能为null,设置默认值为空字符串
|
||||
newSchedule.setCallSignRecord(doctorSchedule.getCallSignRecord() != null ? doctorSchedule.getCallSignRecord() : "");
|
||||
newSchedule.setRegisterItem(doctorSchedule.getRegisterItem() != null ? doctorSchedule.getRegisterItem() : "");
|
||||
newSchedule.setRegisterFee(doctorSchedule.getRegisterFee() != null ? doctorSchedule.getRegisterFee() : 0);
|
||||
newSchedule.setDiagnosisItem(doctorSchedule.getDiagnosisItem() != null ? doctorSchedule.getDiagnosisItem() : "");
|
||||
newSchedule.setDiagnosisFee(doctorSchedule.getDiagnosisFee() != null ? doctorSchedule.getDiagnosisFee() : 0);
|
||||
newSchedule.setIsOnline(doctorSchedule.getIsOnline() != null ? doctorSchedule.getIsOnline() : false);
|
||||
newSchedule.setIsStopped(doctorSchedule.getIsStopped() != null ? doctorSchedule.getIsStopped() : false);
|
||||
newSchedule.setStopReason(doctorSchedule.getStopReason() != null ? doctorSchedule.getStopReason() : "");
|
||||
newSchedule.setDeptId(doctorSchedule.getDeptId());
|
||||
// 不设置id字段,让数据库自动生成
|
||||
// 使用自定义的insertWithoutId方法,确保INSERT语句不包含id字段
|
||||
int result = doctorScheduleMapper.insertWithoutId(newSchedule);
|
||||
boolean save = result > 0;
|
||||
if (save) {
|
||||
// 返回保存后的实体对象,包含数据库生成的ID
|
||||
return R.ok(newSchedule);
|
||||
} else {
|
||||
return R.fail("保存失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.openhis.appointmentmanage.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
@@ -15,7 +17,8 @@ import java.time.LocalTime;
|
||||
@TableName(value = "adm_doctor_schedule")
|
||||
@Accessors(chain = true)
|
||||
public class DoctorSchedule {
|
||||
/** id */
|
||||
/** id - 数据库GENERATED ALWAYS,由数据库自动生成,插入时不应包含此字段 */
|
||||
@TableId(type = IdType.NONE)
|
||||
private Integer id;
|
||||
|
||||
/** 星期 */
|
||||
|
||||
@@ -2,8 +2,12 @@ package com.openhis.appointmentmanage.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.openhis.appointmentmanage.domain.DoctorSchedule;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Repository
|
||||
@Mapper
|
||||
public interface DoctorScheduleMapper extends BaseMapper<DoctorSchedule> {
|
||||
/**
|
||||
* 自定义插入方法,排除id字段(数据库GENERATED ALWAYS)
|
||||
*/
|
||||
int insertWithoutId(DoctorSchedule doctorSchedule);
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
|
||||
<span class="filter-label">排班类型</span>
|
||||
<div class="radio-group">
|
||||
<el-radio v-model="filterParams.appointmentType" label="普通">普通</el-radio>
|
||||
<el-radio v-model="filterParams.appointmentType" label="专家">专家</el-radio>
|
||||
<el-radio v-model="filterParams.appointmentType" label="普通" @change="handleAppointmentTypeChange">普通</el-radio>
|
||||
<el-radio v-model="filterParams.appointmentType" label="专家" @change="handleAppointmentTypeChange">专家</el-radio>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
</div>
|
||||
<el-table :data="dateGroup.items" border style="width: 100%" class="schedule-table">
|
||||
<el-table-column prop="timeSlot" label="时段" width="100"></el-table-column>
|
||||
<el-table-column prop="doctorName" label="医生" width="120">
|
||||
<el-table-column prop="doctorName" :label="filterParams.appointmentType === '专家' ? '专家' : '医生'" width="150">
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
v-model="scope.row.doctorName"
|
||||
@@ -50,10 +50,12 @@
|
||||
class="inline-select"
|
||||
:disabled="!isEditMode"
|
||||
>
|
||||
<el-option label="张医生" value="张医生"></el-option>
|
||||
<el-option label="李医生" value="李医生"></el-option>
|
||||
<el-option label="王医生" value="王医生"></el-option>
|
||||
<el-option label="赵医生" value="赵医生"></el-option>
|
||||
<el-option
|
||||
v-for="doctor in getDoctorOptions(filterParams.appointmentType)"
|
||||
:key="doctor.value"
|
||||
:label="doctor.label"
|
||||
:value="doctor.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -125,6 +127,7 @@
|
||||
placeholder="请选"
|
||||
class="inline-select"
|
||||
:disabled="!isEditMode"
|
||||
@change="handleAppointmentItemChange(scope.row)"
|
||||
>
|
||||
<el-option label="挂号费 50" value="挂号费 50"></el-option>
|
||||
<el-option label="一般诊疗费 10" value="一般诊疗费 10"></el-option>
|
||||
@@ -133,7 +136,11 @@
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="registrationFee" label="挂号费(元)" width="100"></el-table-column>
|
||||
<el-table-column prop="registrationFee" label="挂号费(元)" width="100">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.registrationFee || '0' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="clinicItem" label="诊查项目" width="150">
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
@@ -141,6 +148,7 @@
|
||||
placeholder="请选择诊查项目"
|
||||
class="inline-select"
|
||||
:disabled="!isEditMode"
|
||||
@change="handleClinicItemChange(scope.row)"
|
||||
>
|
||||
<el-option label="常规诊查" value="常规诊查"></el-option>
|
||||
<el-option label="专科诊查" value="专科诊查"></el-option>
|
||||
@@ -149,7 +157,11 @@
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="treatmentFee" label="诊疗费(元)" width="100"></el-table-column>
|
||||
<el-table-column prop="treatmentFee" label="诊疗费(元)" width="100">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.treatmentFee || '0' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="online" label="线上" width="60">
|
||||
<template #default="scope">
|
||||
<el-checkbox v-model="scope.row.online" :disabled="!isEditMode"></el-checkbox>
|
||||
@@ -227,6 +239,7 @@ import { ref, onMounted, computed, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox, ElDialog } from 'element-plus'
|
||||
import { View } from '@element-plus/icons-vue'
|
||||
import { addDoctorSchedule, deleteDoctorSchedule } from '../api'
|
||||
|
||||
// 路由和导航
|
||||
const route = useRoute()
|
||||
@@ -240,6 +253,28 @@ const filterParams = ref({
|
||||
appointmentType: '普通'
|
||||
})
|
||||
|
||||
// 医生列表数据
|
||||
const doctorOptions = ref({
|
||||
'普通': [
|
||||
{ label: '张医生', value: '张医生' },
|
||||
{ label: '李医生', value: '李医生' },
|
||||
{ label: '王医生', value: '王医生' },
|
||||
{ label: '赵医生', value: '赵医生' }
|
||||
],
|
||||
'专家': [
|
||||
{ label: '请选择专家', value: '' },
|
||||
{ label: '王教授', value: '王教授' },
|
||||
{ label: '李主任', value: '李主任' },
|
||||
{ label: '赵教授', value: '赵教授' },
|
||||
{ label: '张主任', value: '张主任' }
|
||||
]
|
||||
})
|
||||
|
||||
// 根据排班类型获取医生选项
|
||||
const getDoctorOptions = (appointmentType) => {
|
||||
return doctorOptions.value[appointmentType] || doctorOptions.value['普通']
|
||||
}
|
||||
|
||||
// 编辑模式控制
|
||||
const isEditMode = computed(() => {
|
||||
return route.query.mode === 'edit'
|
||||
@@ -248,6 +283,9 @@ const isEditMode = computed(() => {
|
||||
// 排班列表数据
|
||||
const scheduleList = ref([])
|
||||
|
||||
// 当前科室信息
|
||||
const currentDept = ref(null)
|
||||
|
||||
// 按日期分组的排班数据
|
||||
const groupedSchedule = computed(() => {
|
||||
// 按日期分组
|
||||
@@ -299,9 +337,9 @@ const generateWeekSchedule = (startDate) => {
|
||||
room: '',
|
||||
maxNumber: '',
|
||||
appointmentItem: '',
|
||||
registrationFee: '',
|
||||
registrationFee: 0,
|
||||
clinicItem: '',
|
||||
treatmentFee: '',
|
||||
treatmentFee: 0,
|
||||
online: true,
|
||||
stopClinic: false,
|
||||
stopReason: ''
|
||||
@@ -318,18 +356,130 @@ const initData = () => {
|
||||
const deptId = route.query.deptId
|
||||
console.log('科室ID:', deptId)
|
||||
|
||||
// 设置当前科室信息
|
||||
if (deptId) {
|
||||
currentDept.value = { id: deptId }
|
||||
}
|
||||
|
||||
// 生成排班数据
|
||||
scheduleList.value = generateWeekSchedule(filterParams.value.startDate)
|
||||
}
|
||||
|
||||
// 排班类型变化处理
|
||||
const handleAppointmentTypeChange = () => {
|
||||
// 当排班类型改变时,清空所有排班记录的医生选择
|
||||
scheduleList.value.forEach(item => {
|
||||
// 如果当前选择的医生不在新类型对应的医生列表中,则清空
|
||||
const currentDoctors = getDoctorOptions(filterParams.value.appointmentType)
|
||||
const doctorExists = currentDoctors.some(doctor => doctor.value === item.doctorName)
|
||||
if (!doctorExists) {
|
||||
item.doctorName = ''
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 挂号项目变化处理
|
||||
const handleAppointmentItemChange = (row) => {
|
||||
if (row.appointmentItem) {
|
||||
// 从挂号项目中提取费用数字,例如 "挂号费 50" -> 50
|
||||
const feeMatch = row.appointmentItem.match(/(\d+)/)
|
||||
if (feeMatch) {
|
||||
row.registrationFee = parseInt(feeMatch[1])
|
||||
} else {
|
||||
row.registrationFee = 0
|
||||
}
|
||||
} else {
|
||||
row.registrationFee = 0
|
||||
}
|
||||
}
|
||||
|
||||
// 诊查项目变化处理
|
||||
const handleClinicItemChange = (row) => {
|
||||
// 诊查项目费用映射表
|
||||
const clinicFeeMap = {
|
||||
'常规诊查': 10,
|
||||
'专科诊查': 20,
|
||||
'特殊诊查': 30,
|
||||
'专家诊查': 50
|
||||
}
|
||||
|
||||
if (row.clinicItem && clinicFeeMap[row.clinicItem]) {
|
||||
row.treatmentFee = clinicFeeMap[row.clinicItem]
|
||||
} else {
|
||||
row.treatmentFee = 0
|
||||
}
|
||||
}
|
||||
|
||||
// 添加排班
|
||||
const handleAddSchedule = (row) => {
|
||||
ElMessage.info('添加排班功能待实现')
|
||||
// 创建新的排班记录,基于当前行的日期和时段
|
||||
const newSchedule = {
|
||||
id: `new-${Date.now()}-${Math.random()}`,
|
||||
date: row.date,
|
||||
weekday: row.weekday,
|
||||
timeSlot: row.timeSlot,
|
||||
startTime: row.startTime || '08:00',
|
||||
endTime: row.endTime || '12:00',
|
||||
doctorName: '',
|
||||
room: '',
|
||||
maxNumber: '',
|
||||
appointmentItem: '',
|
||||
registrationFee: '',
|
||||
clinicItem: '',
|
||||
treatmentFee: '',
|
||||
online: true,
|
||||
stopClinic: false,
|
||||
stopReason: '',
|
||||
isNew: true // 标记为新添加的记录
|
||||
}
|
||||
|
||||
// 找到当前行在列表中的位置,在其后插入新记录
|
||||
const currentIndex = scheduleList.value.findIndex(item => item.id === row.id)
|
||||
if (currentIndex !== -1) {
|
||||
scheduleList.value.splice(currentIndex + 1, 0, newSchedule)
|
||||
ElMessage.success('添加排班成功')
|
||||
} else {
|
||||
// 如果找不到,添加到对应日期组的末尾
|
||||
scheduleList.value.push(newSchedule)
|
||||
ElMessage.success('添加排班成功')
|
||||
}
|
||||
}
|
||||
|
||||
// 删除排班
|
||||
const handleDeleteSchedule = (row) => {
|
||||
ElMessage.info('删除排班功能待实现')
|
||||
ElMessageBox.confirm('确定要删除这条排班记录吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
// 如果是已保存的记录(有后端ID),调用删除接口
|
||||
if (row.backendId && !row.isNew) {
|
||||
deleteDoctorSchedule(row.backendId).then(res => {
|
||||
if (res.code === 200) {
|
||||
// 从列表中移除
|
||||
const index = scheduleList.value.findIndex(item => item.id === row.id)
|
||||
if (index !== -1) {
|
||||
scheduleList.value.splice(index, 1)
|
||||
}
|
||||
ElMessage.success('删除成功')
|
||||
} else {
|
||||
ElMessage.error(res.msg || '删除失败')
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('删除排班失败:', error)
|
||||
ElMessage.error('删除失败,请稍后重试')
|
||||
})
|
||||
} else {
|
||||
// 如果是新添加的记录(未保存),直接从列表中移除
|
||||
const index = scheduleList.value.findIndex(item => item.id === row.id)
|
||||
if (index !== -1) {
|
||||
scheduleList.value.splice(index, 1)
|
||||
ElMessage.success('删除成功')
|
||||
}
|
||||
}
|
||||
}).catch(() => {
|
||||
// 用户取消删除
|
||||
})
|
||||
}
|
||||
|
||||
// 号源记录对话框相关
|
||||
@@ -386,10 +536,139 @@ const handleViewRecord = (row) => {
|
||||
}
|
||||
|
||||
// 保存排班
|
||||
const handleSave = () => {
|
||||
ElMessage.success('排班保存成功')
|
||||
// 返回上一页
|
||||
router.back()
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
// 验证必填字段
|
||||
const invalidSchedules = scheduleList.value.filter(item => {
|
||||
// 检查是否有必填字段为空
|
||||
return !item.doctorName || !item.room || !item.startTime || !item.endTime || !item.maxNumber
|
||||
})
|
||||
|
||||
if (invalidSchedules.length > 0) {
|
||||
ElMessage.warning('请完善所有排班记录的必填信息(医生、诊室、开始时间、结束时间、限号数量)')
|
||||
return
|
||||
}
|
||||
|
||||
// 转换数据格式以匹配后端实体,并建立映射关系
|
||||
const schedulesToSave = scheduleList.value.map((item, index) => {
|
||||
// 解析挂号项目和诊查项目,提取费用
|
||||
let registrationFee = 0
|
||||
let diagnosisFee = 0
|
||||
|
||||
if (item.appointmentItem) {
|
||||
const feeMatch = item.appointmentItem.match(/(\d+)/)
|
||||
if (feeMatch) {
|
||||
registrationFee = parseInt(feeMatch[1])
|
||||
}
|
||||
}
|
||||
|
||||
if (item.clinicItem) {
|
||||
// 这里可以根据诊查项目设置诊疗费,暂时设为0或从其他字段获取
|
||||
diagnosisFee = item.treatmentFee ? parseInt(item.treatmentFee) : 0
|
||||
}
|
||||
|
||||
return {
|
||||
localIndex: index, // 保存本地索引,用于更新
|
||||
localId: item.id, // 保存本地ID
|
||||
scheduleData: {
|
||||
id: item.backendId || null, // 如果是新记录,id为null
|
||||
weekday: item.weekday,
|
||||
timePeriod: item.timeSlot,
|
||||
doctor: item.doctorName,
|
||||
clinic: item.room,
|
||||
startTime: item.startTime,
|
||||
endTime: item.endTime,
|
||||
limitNumber: parseInt(item.maxNumber) || 0,
|
||||
registerItem: item.appointmentItem || '',
|
||||
registerFee: registrationFee,
|
||||
diagnosisItem: item.clinicItem || '',
|
||||
diagnosisFee: diagnosisFee,
|
||||
isOnline: item.online || false,
|
||||
isStopped: item.stopClinic || false,
|
||||
stopReason: item.stopClinic ? (item.stopReason || '') : '',
|
||||
deptId: currentDept.value?.id || route.query.deptId || null,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 只保存新添加的记录(isNew: true)或没有backendId的记录
|
||||
const newSchedulesToSave = schedulesToSave.filter(({ localIndex }) => {
|
||||
const item = scheduleList.value[localIndex]
|
||||
return item.isNew || !item.backendId // 只保存新记录或没有backendId的记录
|
||||
})
|
||||
|
||||
if (newSchedulesToSave.length === 0) {
|
||||
ElMessage.info('没有需要保存的新排班记录')
|
||||
// 返回上一页
|
||||
router.back()
|
||||
return
|
||||
}
|
||||
|
||||
// 批量保存排班
|
||||
let successCount = 0
|
||||
let failCount = 0
|
||||
const errors = []
|
||||
|
||||
for (const { localIndex, localId, scheduleData } of newSchedulesToSave) {
|
||||
try {
|
||||
// 确保新记录的id为null
|
||||
scheduleData.id = null
|
||||
|
||||
const res = await addDoctorSchedule(scheduleData)
|
||||
if (res.code === 200 && res.data) {
|
||||
successCount++
|
||||
// 更新本地记录的backendId
|
||||
const localItem = scheduleList.value[localIndex]
|
||||
if (localItem) {
|
||||
// 从响应中获取保存后的ID
|
||||
if (res.data && typeof res.data === 'object' && res.data.id) {
|
||||
localItem.backendId = res.data.id
|
||||
localItem.isNew = false
|
||||
} else if (res.data && typeof res.data === 'number') {
|
||||
localItem.backendId = res.data
|
||||
localItem.isNew = false
|
||||
} else if (res.data === true) {
|
||||
// 如果后端返回的是boolean true,标记为已保存
|
||||
localItem.isNew = false
|
||||
localItem.saved = true
|
||||
} else {
|
||||
// 其他情况,标记为已保存
|
||||
localItem.isNew = false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
failCount++
|
||||
const errorMsg = res.msg || '保存失败'
|
||||
errors.push(errorMsg)
|
||||
console.error('保存排班失败:', errorMsg, res)
|
||||
}
|
||||
} catch (error) {
|
||||
failCount++
|
||||
const errorMsg = error.message || '保存异常'
|
||||
errors.push(errorMsg)
|
||||
console.error('保存排班异常:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 如果有错误,显示详细错误信息
|
||||
if (errors.length > 0) {
|
||||
console.error('保存错误详情:', errors)
|
||||
}
|
||||
|
||||
if (failCount === 0) {
|
||||
ElMessage.success(`排班保存成功,共保存 ${successCount} 条记录`)
|
||||
// 返回上一页
|
||||
router.back()
|
||||
} else {
|
||||
ElMessage.warning(`部分排班保存失败,成功 ${successCount} 条,失败 ${failCount} 条`)
|
||||
if (errors.length > 0) {
|
||||
console.error('错误详情:', errors.join('; '))
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('保存排班失败:', error)
|
||||
ElMessage.error('保存失败,请稍后重试')
|
||||
}
|
||||
}
|
||||
|
||||
// 取消操作
|
||||
|
||||
@@ -153,8 +153,8 @@
|
||||
|
||||
<span class="filter-label">排班类型</span>
|
||||
<div class="radio-group">
|
||||
<el-radio v-model="filterParams.appointmentType" label="普通">普通</el-radio>
|
||||
<el-radio v-model="filterParams.appointmentType" label="专家">专家</el-radio>
|
||||
<el-radio v-model="filterParams.appointmentType" label="普通" @change="handleAppointmentTypeChange">普通</el-radio>
|
||||
<el-radio v-model="filterParams.appointmentType" label="专家" @change="handleAppointmentTypeChange">专家</el-radio>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -168,18 +168,21 @@
|
||||
</div>
|
||||
<el-table :data="dateGroup.items" border style="width: 100%" class="schedule-table">
|
||||
<el-table-column prop="timeSlot" label="时段" width="100"></el-table-column>
|
||||
<el-table-column prop="doctorName" label="医生" width="120">
|
||||
<el-table-column prop="doctorName" :label="filterParams.appointmentType === '专家' ? '专家' : '医生'" width="150">
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
v-model="scope.row.doctorName"
|
||||
placeholder="请选"
|
||||
class="inline-select"
|
||||
:disabled="!isEditMode"
|
||||
:key="`doctor-${filterParams.appointmentType}-${scope.row.id}`"
|
||||
>
|
||||
<el-option label="张医生" value="张医生"></el-option>
|
||||
<el-option label="李医生" value="李医生"></el-option>
|
||||
<el-option label="王医生" value="王医生"></el-option>
|
||||
<el-option label="赵医生" value="赵医生"></el-option>
|
||||
<el-option
|
||||
v-for="doctor in getDoctorOptions(filterParams.appointmentType)"
|
||||
:key="doctor.value"
|
||||
:label="doctor.label"
|
||||
:value="doctor.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -251,6 +254,7 @@
|
||||
placeholder="请选"
|
||||
class="inline-select"
|
||||
:disabled="!isEditMode"
|
||||
@change="handleAppointmentItemChange(scope.row)"
|
||||
>
|
||||
<el-option label="挂号费 50" value="挂号费 50"></el-option>
|
||||
<el-option label="一般诊疗费 10" value="一般诊疗费 10"></el-option>
|
||||
@@ -259,7 +263,11 @@
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="registrationFee" label="挂号费(元)" width="100"></el-table-column>
|
||||
<el-table-column prop="registrationFee" label="挂号费(元)" width="100">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.registrationFee || '0' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="clinicItem" label="诊查项目" width="150">
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
@@ -267,6 +275,7 @@
|
||||
placeholder="请选择诊查项目"
|
||||
class="inline-select"
|
||||
:disabled="!isEditMode"
|
||||
@change="handleClinicItemChange(scope.row)"
|
||||
>
|
||||
<el-option label="常规诊查" value="常规诊查"></el-option>
|
||||
<el-option label="专科诊查" value="专科诊查"></el-option>
|
||||
@@ -275,7 +284,11 @@
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="treatmentFee" label="诊疗费(元)" width="100"></el-table-column>
|
||||
<el-table-column prop="treatmentFee" label="诊疗费(元)" width="100">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.treatmentFee || '0' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="online" label="线上" width="60">
|
||||
<template #default="scope">
|
||||
<el-checkbox v-model="scope.row.online" :disabled="!isEditMode"></el-checkbox>
|
||||
@@ -355,6 +368,7 @@ import { ElMessage, ElDialog, ElSelect, ElOption, ElInput, ElForm, ElFormItem, E
|
||||
import { EditPen, View, DocumentRemove } from '@element-plus/icons-vue'
|
||||
import { listDept, searchDept } from '@/api/appoinmentmanage/dept'
|
||||
import { getLocationTree } from '@/views/charge/outpatientregistration/components/outpatientregistration'
|
||||
import { addDoctorSchedule, deleteDoctorSchedule, batchSaveDoctorSchedule } from './api'
|
||||
|
||||
// 查询参数
|
||||
const queryParams = ref({
|
||||
@@ -402,6 +416,28 @@ const filterParams = ref({
|
||||
appointmentType: '普通'
|
||||
})
|
||||
|
||||
// 医生列表数据
|
||||
const doctorOptions = ref({
|
||||
'普通': [
|
||||
{ label: '张医生', value: '张医生' },
|
||||
{ label: '李医生', value: '李医生' },
|
||||
{ label: '王医生', value: '王医生' },
|
||||
{ label: '赵医生', value: '赵医生' }
|
||||
],
|
||||
'专家': [
|
||||
{ label: '请选择专家', value: '' },
|
||||
{ label: '王教授', value: '王教授' },
|
||||
{ label: '李主任', value: '李主任' },
|
||||
{ label: '赵教授', value: '赵教授' },
|
||||
{ label: '张主任', value: '张主任' }
|
||||
]
|
||||
})
|
||||
|
||||
// 根据排班类型获取医生选项
|
||||
const getDoctorOptions = (appointmentType) => {
|
||||
return doctorOptions.value[appointmentType] || doctorOptions.value['普通']
|
||||
}
|
||||
|
||||
// 排班列表数据
|
||||
const scheduleList = ref([])
|
||||
|
||||
@@ -566,9 +602,9 @@ const generateWeekSchedule = (startDate) => {
|
||||
room: '',
|
||||
maxNumber: '',
|
||||
appointmentItem: '',
|
||||
registrationFee: '',
|
||||
registrationFee: 0,
|
||||
clinicItem: '',
|
||||
treatmentFee: '',
|
||||
treatmentFee: 0,
|
||||
online: true,
|
||||
stopClinic: false,
|
||||
stopReason: ''
|
||||
@@ -615,14 +651,145 @@ const handleView = (row) => {
|
||||
scheduleDialogVisible.value = true
|
||||
}
|
||||
|
||||
// 医生映射关系(普通医生 -> 专家医生)
|
||||
const doctorMapping = {
|
||||
'张医生': '张主任',
|
||||
'李医生': '李主任',
|
||||
'王医生': '王教授',
|
||||
'赵医生': '赵教授',
|
||||
'张主任': '张医生',
|
||||
'李主任': '李医生',
|
||||
'王教授': '王医生',
|
||||
'赵教授': '赵医生'
|
||||
}
|
||||
|
||||
// 排班类型变化处理
|
||||
const handleAppointmentTypeChange = () => {
|
||||
// 当排班类型改变时,自动匹配对应的医生
|
||||
scheduleList.value.forEach(item => {
|
||||
if (item.doctorName) {
|
||||
// 获取新类型对应的医生列表
|
||||
const newTypeDoctors = getDoctorOptions(filterParams.value.appointmentType)
|
||||
// 检查当前医生是否在新类型的医生列表中
|
||||
const doctorExists = newTypeDoctors.some(doctor => doctor.value === item.doctorName)
|
||||
|
||||
if (!doctorExists) {
|
||||
// 如果当前医生不在新类型列表中,尝试通过映射关系找到对应的医生
|
||||
const mappedDoctor = doctorMapping[item.doctorName]
|
||||
if (mappedDoctor && newTypeDoctors.some(doctor => doctor.value === mappedDoctor)) {
|
||||
// 如果找到对应的医生,则更新
|
||||
item.doctorName = mappedDoctor
|
||||
} else {
|
||||
// 如果找不到对应的医生,则清空
|
||||
item.doctorName = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 挂号项目变化处理
|
||||
const handleAppointmentItemChange = (row) => {
|
||||
if (row.appointmentItem) {
|
||||
// 从挂号项目中提取费用数字,例如 "挂号费 50" -> 50
|
||||
const feeMatch = row.appointmentItem.match(/(\d+)/)
|
||||
if (feeMatch) {
|
||||
row.registrationFee = parseInt(feeMatch[1])
|
||||
} else {
|
||||
row.registrationFee = 0
|
||||
}
|
||||
} else {
|
||||
row.registrationFee = 0
|
||||
}
|
||||
}
|
||||
|
||||
// 诊查项目变化处理
|
||||
const handleClinicItemChange = (row) => {
|
||||
// 诊查项目费用映射表
|
||||
const clinicFeeMap = {
|
||||
'常规诊查': 10,
|
||||
'专科诊查': 20,
|
||||
'特殊诊查': 30,
|
||||
'专家诊查': 50
|
||||
}
|
||||
|
||||
if (row.clinicItem && clinicFeeMap[row.clinicItem]) {
|
||||
row.treatmentFee = clinicFeeMap[row.clinicItem]
|
||||
} else {
|
||||
row.treatmentFee = 0
|
||||
}
|
||||
}
|
||||
|
||||
// 添加排班
|
||||
const handleAddSchedule = (row) => {
|
||||
ElMessage.info('添加排班功能待实现')
|
||||
// 创建新的排班记录,基于当前行的日期和时段
|
||||
const newSchedule = {
|
||||
id: `new-${Date.now()}-${Math.random()}`,
|
||||
date: row.date,
|
||||
weekday: row.weekday,
|
||||
timeSlot: row.timeSlot,
|
||||
startTime: row.startTime || '08:00',
|
||||
endTime: row.endTime || '12:00',
|
||||
doctorName: '',
|
||||
room: '',
|
||||
maxNumber: '',
|
||||
appointmentItem: '',
|
||||
registrationFee: 0,
|
||||
clinicItem: '',
|
||||
treatmentFee: 0,
|
||||
online: true,
|
||||
stopClinic: false,
|
||||
stopReason: '',
|
||||
isNew: true // 标记为新添加的记录
|
||||
}
|
||||
|
||||
// 找到当前行在列表中的位置,在其后插入新记录
|
||||
const currentIndex = scheduleList.value.findIndex(item => item.id === row.id)
|
||||
if (currentIndex !== -1) {
|
||||
scheduleList.value.splice(currentIndex + 1, 0, newSchedule)
|
||||
ElMessage.success('添加排班成功')
|
||||
} else {
|
||||
// 如果找不到,添加到对应日期组的末尾
|
||||
scheduleList.value.push(newSchedule)
|
||||
ElMessage.success('添加排班成功')
|
||||
}
|
||||
}
|
||||
|
||||
// 删除排班
|
||||
const handleDeleteSchedule = (row) => {
|
||||
ElMessage.info('删除排班功能待实现')
|
||||
ElMessageBox.confirm('确定要删除这条排班记录吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
// 如果是已保存的记录(有后端ID),调用删除接口
|
||||
if (row.backendId && !row.isNew) {
|
||||
deleteDoctorSchedule(row.backendId).then(res => {
|
||||
if (res.code === 200) {
|
||||
// 从列表中移除
|
||||
const index = scheduleList.value.findIndex(item => item.id === row.id)
|
||||
if (index !== -1) {
|
||||
scheduleList.value.splice(index, 1)
|
||||
}
|
||||
ElMessage.success('删除成功')
|
||||
} else {
|
||||
ElMessage.error(res.msg || '删除失败')
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('删除排班失败:', error)
|
||||
ElMessage.error('删除失败,请稍后重试')
|
||||
})
|
||||
} else {
|
||||
// 如果是新添加的记录(未保存),直接从列表中移除
|
||||
const index = scheduleList.value.findIndex(item => item.id === row.id)
|
||||
if (index !== -1) {
|
||||
scheduleList.value.splice(index, 1)
|
||||
ElMessage.success('删除成功')
|
||||
}
|
||||
}
|
||||
}).catch(() => {
|
||||
// 用户取消删除
|
||||
})
|
||||
}
|
||||
|
||||
// 计算号源记录
|
||||
@@ -674,9 +841,150 @@ const handleViewRecord = (row) => {
|
||||
}
|
||||
|
||||
// 保存排班
|
||||
const handleSave = () => {
|
||||
ElMessage.success('排班保存成功')
|
||||
scheduleDialogVisible.value = false
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
// 验证必填字段
|
||||
const invalidSchedules = scheduleList.value.filter(item => {
|
||||
// 检查是否有必填字段为空
|
||||
return !item.doctorName || !item.room || !item.startTime || !item.endTime || !item.maxNumber
|
||||
})
|
||||
|
||||
if (invalidSchedules.length > 0) {
|
||||
ElMessage.warning('请完善所有排班记录的必填信息(医生、诊室、开始时间、结束时间、限号数量)')
|
||||
return
|
||||
}
|
||||
|
||||
// 转换数据格式以匹配后端实体,并建立映射关系
|
||||
const schedulesToSave = scheduleList.value.map((item, index) => {
|
||||
// 解析挂号项目和诊查项目,提取费用
|
||||
let registrationFee = 0
|
||||
let diagnosisFee = 0
|
||||
|
||||
if (item.appointmentItem) {
|
||||
const feeMatch = item.appointmentItem.match(/(\d+)/)
|
||||
if (feeMatch) {
|
||||
registrationFee = parseInt(feeMatch[1])
|
||||
}
|
||||
}
|
||||
|
||||
if (item.clinicItem) {
|
||||
// 这里可以根据诊查项目设置诊疗费,暂时设为0或从其他字段获取
|
||||
diagnosisFee = item.treatmentFee ? parseInt(item.treatmentFee) : 0
|
||||
}
|
||||
|
||||
// 构建排班数据对象
|
||||
const scheduleData = {
|
||||
weekday: item.weekday,
|
||||
timePeriod: item.timeSlot,
|
||||
doctor: item.doctorName,
|
||||
clinic: item.room,
|
||||
startTime: item.startTime,
|
||||
endTime: item.endTime,
|
||||
limitNumber: parseInt(item.maxNumber) || 0,
|
||||
registerItem: item.appointmentItem || '',
|
||||
registerFee: registrationFee,
|
||||
diagnosisItem: item.clinicItem || '',
|
||||
diagnosisFee: diagnosisFee,
|
||||
isOnline: item.online || false,
|
||||
isStopped: item.stopClinic || false,
|
||||
stopReason: item.stopClinic ? (item.stopReason || '') : '',
|
||||
deptId: currentDept.value?.id || null,
|
||||
}
|
||||
|
||||
// 只有已存在的记录才包含id字段(用于更新)
|
||||
if (item.backendId) {
|
||||
scheduleData.id = item.backendId
|
||||
}
|
||||
|
||||
return {
|
||||
localIndex: index, // 保存本地索引,用于更新
|
||||
localId: item.id, // 保存本地ID
|
||||
scheduleData: scheduleData
|
||||
}
|
||||
})
|
||||
|
||||
// 只保存新添加的记录(isNew: true)或已修改的记录
|
||||
const newSchedulesToSave = schedulesToSave.filter(({ localIndex }) => {
|
||||
const item = scheduleList.value[localIndex]
|
||||
return item.isNew || !item.backendId // 只保存新记录或没有backendId的记录
|
||||
})
|
||||
|
||||
if (newSchedulesToSave.length === 0) {
|
||||
ElMessage.info('没有需要保存的新排班记录')
|
||||
scheduleDialogVisible.value = false
|
||||
return
|
||||
}
|
||||
|
||||
// 批量保存排班
|
||||
let successCount = 0
|
||||
let failCount = 0
|
||||
const errors = []
|
||||
|
||||
for (const { localIndex, localId, scheduleData } of newSchedulesToSave) {
|
||||
try {
|
||||
// 新记录不包含id字段(数据库id列是GENERATED ALWAYS,由数据库自动生成)
|
||||
// 创建新对象,明确排除id字段,确保JSON序列化时不包含id
|
||||
const dataToSave = {}
|
||||
Object.keys(scheduleData).forEach(key => {
|
||||
// 排除id字段,只复制其他字段
|
||||
if (key !== 'id') {
|
||||
dataToSave[key] = scheduleData[key]
|
||||
}
|
||||
})
|
||||
|
||||
const res = await addDoctorSchedule(dataToSave)
|
||||
if (res.code === 200 && res.data) {
|
||||
successCount++
|
||||
// 更新本地记录的backendId
|
||||
const localItem = scheduleList.value[localIndex]
|
||||
if (localItem) {
|
||||
// 从响应中获取保存后的ID
|
||||
if (res.data && typeof res.data === 'object' && res.data.id) {
|
||||
// 后端返回了实体对象,包含ID
|
||||
localItem.backendId = res.data.id
|
||||
localItem.isNew = false
|
||||
} else if (res.data && typeof res.data === 'number') {
|
||||
// 如果返回的是数字ID
|
||||
localItem.backendId = res.data
|
||||
localItem.isNew = false
|
||||
} else if (res.data === true) {
|
||||
// 如果后端返回的是boolean true,标记为已保存
|
||||
localItem.isNew = false
|
||||
localItem.saved = true
|
||||
} else {
|
||||
// 其他情况,标记为已保存
|
||||
localItem.isNew = false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
failCount++
|
||||
const errorMsg = res.msg || '保存失败'
|
||||
errors.push(errorMsg)
|
||||
console.error('保存排班失败:', errorMsg, res)
|
||||
}
|
||||
} catch (error) {
|
||||
failCount++
|
||||
const errorMsg = error.message || '保存异常'
|
||||
errors.push(errorMsg)
|
||||
console.error('保存排班异常:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 如果有错误,显示详细错误信息
|
||||
if (errors.length > 0) {
|
||||
console.error('保存错误详情:', errors)
|
||||
}
|
||||
|
||||
if (failCount === 0) {
|
||||
ElMessage.success(`排班保存成功,共保存 ${successCount} 条记录`)
|
||||
scheduleDialogVisible.value = false
|
||||
} else {
|
||||
ElMessage.warning(`部分排班保存失败,成功 ${successCount} 条,失败 ${failCount} 条`)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('保存排班失败:', error)
|
||||
ElMessage.error('保存失败,请稍后重试')
|
||||
}
|
||||
}
|
||||
|
||||
// 取消操作
|
||||
|
||||
Reference in New Issue
Block a user