You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
588 lines
22 KiB
588 lines
22 KiB
<template>
|
|
|
|
<GuipDialog :dialogVisible="visitDialogVisible" :title="visitDialogTitle" :show-close-button="true" width="699px"
|
|
:show-cancel-button="visitShowCancelBtn" @confirm="handleVisitConfirm" :confirmText="visitConfirmText"
|
|
@cancel="handleVisitCancel" @close="handleVisitClose">
|
|
<div class="flex conflictTitle" v-if="is_allow_coincide && !isDoctorSet">
|
|
您设置的 <b>{{ h_realname }} </b>【每周排班】,与以下现有出诊安排重叠,请确定是否正确。
|
|
</div>
|
|
<div class="flex conflictTitle" v-if="!is_allow_coincide && !isDoctorSet">
|
|
您设置的 <b>{{ h_realname }} </b>【每周排班】,与以下现有出诊安排冲突,请调整后再保存:
|
|
</div>
|
|
<div class="visitContent mt24">
|
|
<div class="hosPlanItem mb24" v-for="(conflict, index) in hasConflictresult" :key="index">
|
|
<p>{{ conflict.date }} {{ conflict.dayOfWeek ? `(${conflict.dayOfWeek})` : '' }}{{ conflict.conflictShift }}</p>
|
|
<div class="flex">
|
|
<span class="conflictTip">{{!is_allow_coincide ?'冲突':'重叠' }}</span>
|
|
<div>{{ conflict.hospital }}({{ conflict.type === 'fixed' ?
|
|
'固定排班' :
|
|
'临时出诊' }})</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<p v-if="hasConflictresultLength > 3" style="color: #FF4D4F;">等共{{hasConflictresultLength}}条出诊安排冲突,请修改后再进行设置</p>
|
|
</GuipDialog>
|
|
</template>
|
|
<script>
|
|
import GuipDialog from '@/components/GuipDialog.vue';
|
|
|
|
export default {
|
|
props: {
|
|
is_allow_coincide: [Boolean, Number],
|
|
oldWorktimes: Object,
|
|
h_realname: String,
|
|
doctor_id: [Number, String],
|
|
depart_id: [Number, String],
|
|
houseCallSettingForm: Object,
|
|
rawScheduleDataProp: Object,
|
|
isDoctorSet:Boolean,
|
|
cancelText: String,
|
|
confirmText: String,
|
|
cancelBtnShow: String,
|
|
title: String,
|
|
// houseCallSettingForm: Object,
|
|
// getDoctorHosPreview: Function,
|
|
// formatWorktimesArray: Function,
|
|
},
|
|
components: {
|
|
GuipDialog,
|
|
},
|
|
data(){
|
|
return {
|
|
visitDialogTitle: '出诊安排重叠,请确认',//出诊冲突框标题
|
|
visitDialogVisible: false,//出诊冲突提示框
|
|
visitShowCancelBtn: true,//出诊冲突框是否显示取消按钮
|
|
visitConfirmText: '确定并保存',//出诊冲突框确认按钮文字
|
|
hasConflictresult: [],
|
|
rawScheduleData1:null,
|
|
weekPlan: {
|
|
'1': '周一',
|
|
'2': '周二',
|
|
'3': '周三',
|
|
'4': '周四',
|
|
'5': '周五',
|
|
'6': '周六',
|
|
'7': '周日',
|
|
},
|
|
weekDaysDesc: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
|
|
hasConflictresultLength:0
|
|
|
|
}
|
|
},
|
|
created() {
|
|
console.log(this.rawScheduleDataProp,'-----t111his.rawScheduleDataProp===');
|
|
this.rawScheduleData1 = this.rawScheduleDataProp;
|
|
|
|
},
|
|
watch: {
|
|
// 监听 props 变化
|
|
rawScheduleDataProp(newVal) {
|
|
this.rawScheduleData1 = newVal
|
|
console.log(newVal,'===----00999');
|
|
},
|
|
|
|
} ,
|
|
mounted() {
|
|
if(this.cancelBtnShow == '0'){
|
|
this.visitShowCancelBtn = false;
|
|
}
|
|
// console.log(this.rawScheduleDataProp,'this.rawScheduleDataProp===');
|
|
// if(this.rawScheduleDataProp){
|
|
// this.rawScheduleData1 = this.rawScheduleDataProp;
|
|
// }
|
|
if(this.cancelText){
|
|
this.visitConfirmText = this.cancelText;
|
|
}
|
|
if(this.confirmText){
|
|
this.visitConfirmText = this.confirmText;
|
|
}
|
|
if(this.title){
|
|
this.visitDialogTitle = this.title;
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
open(){
|
|
this.visitDialogVisible = true;
|
|
this.getDoctorHosPreview();
|
|
},
|
|
handleVisitClose() {
|
|
this.visitDialogVisible = false;
|
|
},
|
|
handleVisitCancel() {
|
|
this.visitDialogVisible = false;
|
|
},
|
|
handleVisitConfirm() {
|
|
if (this.is_allow_coincide) {
|
|
this.saveWorkTimeDirect();
|
|
}
|
|
this.visitDialogVisible = false;
|
|
},
|
|
// ...start
|
|
async getDoctorHosPreview() {
|
|
await this.$http('POST', '/api/admin/get_departs_worktimes', {
|
|
doctor_id: this.doctor_id,
|
|
}).then(response => {
|
|
const list = response.msg;
|
|
if (response.code == 0) {
|
|
// 保存原始数据
|
|
this.rawScheduleData1 = JSON.parse(JSON.stringify(list));
|
|
const data = this.analyzeCurrentMonthConflicts();
|
|
this.hasConflictresultLength = data.length;
|
|
this.hasConflictresult = data.length > 3 ? data.slice(0, 3) : data;
|
|
console.log(this.hasConflictresult, 'this.hasConflictresult');
|
|
}
|
|
}).catch(error => {
|
|
console.error(error, 'error')
|
|
})
|
|
},
|
|
// 格式化日期为 YYYY-MM-DD
|
|
formatDate(date) {
|
|
const year = date.getFullYear();
|
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
const day = String(date.getDate()).padStart(2, '0');
|
|
return `${year}-${month}-${day}`;
|
|
},
|
|
// 分析当月剩余天数的冲突(区分固定排班和临时出诊)
|
|
analyzeCurrentMonthConflicts() {
|
|
const conflicts = [];
|
|
const today = new Date();
|
|
const currentYear = today.getFullYear();
|
|
const currentMonth = today.getMonth();
|
|
|
|
// 获取当月最后一天
|
|
const lastDay = new Date(currentYear, currentMonth + 1, 0).getDate();
|
|
|
|
// 分析从今天到月底的每一天
|
|
for (let day = today.getDate(); day <= lastDay; day++) {
|
|
const date = new Date(currentYear, currentMonth, day);
|
|
const dateStr = this.formatDate(date);
|
|
const dayOfWeek = date.getDay() === 0 ? 7 : date.getDay();
|
|
|
|
const dayConflicts = this.checkDayConflictsWithType(dateStr, dayOfWeek, this.rawScheduleData1, Object.keys(this.rawScheduleData1));
|
|
if (dayConflicts.length > 0) {
|
|
conflicts.push(...dayConflicts);
|
|
}
|
|
}
|
|
|
|
return conflicts;
|
|
},
|
|
|
|
// 检查单日冲突(区分固定和临时)
|
|
checkDayConflictsWithType(dateStr, dayOfWeek, hospitals, hospitalIds) {
|
|
const conflicts = [];
|
|
const timeSlots = {
|
|
morning: [],
|
|
afternoon: []
|
|
};
|
|
|
|
// 收集这一天的所有医院排班
|
|
hospitalIds.forEach(hid => {
|
|
const hospital = hospitals[hid];
|
|
let plan = "0";
|
|
let isTempAdjust = false;
|
|
let originalPlan = "0";
|
|
|
|
// 获取原始排班
|
|
if (hospital.worktime_no_fixed === 0) {
|
|
// 固定排班
|
|
const weeklyPlan = hospital.worktime_list && hospital.worktime_list[dayOfWeek];
|
|
originalPlan = weeklyPlan ? weeklyPlan.plan.toString() : "0";
|
|
} else {
|
|
// 非固定排班
|
|
const datePlan = hospital.worktime_list && hospital.worktime_list[dateStr];
|
|
originalPlan = datePlan ? datePlan.plan.toString() : "0";
|
|
}
|
|
|
|
// 检查临时调整
|
|
if (hospital.temp_change_worktime && hospital.temp_change_worktime[dateStr]) {
|
|
const tempPlan = hospital.temp_change_worktime[dateStr];
|
|
plan = tempPlan.plan.toString();
|
|
isTempAdjust = true;
|
|
} else {
|
|
plan = originalPlan;
|
|
}
|
|
|
|
if (plan !== "0") {
|
|
const hospitalInfo = {
|
|
hid,
|
|
name: hospital.h_depart_name,
|
|
plan,
|
|
originalPlan,
|
|
isTempAdjust,
|
|
scheduleType: isTempAdjust ? '临时出诊' : '固定排班'
|
|
};
|
|
|
|
if (plan === "1" || plan === "3") {
|
|
timeSlots.morning.push(hospitalInfo);
|
|
}
|
|
if (plan === "2" || plan === "3") {
|
|
timeSlots.afternoon.push(hospitalInfo);
|
|
}
|
|
}
|
|
});
|
|
|
|
// 检查冲突
|
|
if (timeSlots.morning.length > 1) {
|
|
conflicts.push(this.createConflictInfoWithType(
|
|
dateStr,
|
|
timeSlots.morning,
|
|
'上午'
|
|
));
|
|
}
|
|
|
|
if (timeSlots.afternoon.length > 1) {
|
|
conflicts.push(this.createConflictInfoWithType(
|
|
dateStr,
|
|
timeSlots.afternoon,
|
|
'下午'
|
|
));
|
|
}
|
|
|
|
return conflicts;
|
|
},
|
|
|
|
// 创建冲突信息(区分固定和临时)
|
|
createConflictInfoWithType(date, hospitals, timeSlot) {
|
|
const dateObj = new Date(date);
|
|
const dayOfWeek = this.weekDaysDesc[dateObj.getDay()];
|
|
|
|
// 格式化医院信息,区分固定排班和临时出诊
|
|
const hospitalGroups = {
|
|
fixed: hospitals.filter(h => !h.isTempAdjust).map(h => h.name),
|
|
temp: hospitals.filter(h => h.isTempAdjust).map(h => h.name)
|
|
};
|
|
|
|
let hospitalDisplay = '';
|
|
if (hospitalGroups.fixed.length > 0) {
|
|
hospitalDisplay += hospitalGroups.fixed.join('、') + '固定排班';
|
|
}
|
|
if (hospitalGroups.temp.length > 0) {
|
|
if (hospitalDisplay) hospitalDisplay += '、';
|
|
hospitalDisplay += hospitalGroups.temp.join('、') + '临时出诊';
|
|
}
|
|
|
|
return {
|
|
date: date,
|
|
hospital: hospitalDisplay,
|
|
conflictShift: timeSlot,
|
|
type: hospitalGroups.temp.length > 0 ? 'mixed' : 'fixed',
|
|
dayOfWeek: dayOfWeek,
|
|
hospitals: hospitals,
|
|
displayText: `${date}(${dayOfWeek})${timeSlot}班:${hospitalDisplay}`
|
|
};
|
|
},
|
|
// ..end
|
|
async setDepartWorkTime() {
|
|
const { display_work_days, planDays, worktime_no_fixed,worktimes } = this.houseCallSettingForm;
|
|
|
|
const params = {
|
|
doctor_id: this.doctor_id,
|
|
depart_id: this.depart_id,
|
|
worktime_no_fixed: worktime_no_fixed,
|
|
week_visit_plan: JSON.stringify(this.formatWorktimesArray(worktimes))
|
|
}
|
|
|
|
if (display_work_days == 1 && planDays > 0) {
|
|
params.display_work_days = planDays
|
|
}
|
|
|
|
// 检查冲突:当前设置医院的新排班 vs 其他医院的现有排班
|
|
const conflictResults = this.checkScheduleConflict(worktimes, worktime_no_fixed);
|
|
|
|
console.log('冲突检测结果:', conflictResults);
|
|
|
|
// 为固定出诊并且存在冲突时展示弹出框
|
|
if (conflictResults.hasConflict && worktime_no_fixed == 0) {
|
|
this.visitDialogVisible = true;
|
|
this.hasConflictresult = conflictResults.conflicts;
|
|
if(this.is_allow_coincide){
|
|
this.visitDialogTitle = '出诊安排重叠,请确认';
|
|
this.visitConfirmText = '确定并保存';
|
|
this.visitShowCancelBtn = true;
|
|
}else{
|
|
this.visitDialogTitle = '出诊安排冲突,请确认';
|
|
this.visitConfirmText = '知道了';
|
|
this.visitShowCancelBtn = false;
|
|
}
|
|
return;
|
|
}
|
|
},
|
|
async saveWorkTimeDirect() {
|
|
const { display_work_days, planDays, worktime_no_fixed, worktimes } = this.houseCallSettingForm;
|
|
var worktimesArray = this.formatWorktimesArray(worktimes)
|
|
console.log(worktimesArray,'worktimesArray===');
|
|
const params = {
|
|
doctor_id: this.doctor_id,
|
|
depart_id: this.depart_id,
|
|
worktime_no_fixed: worktime_no_fixed,
|
|
week_visit_plan: JSON.stringify(worktimesArray)
|
|
}
|
|
|
|
if (display_work_days == 1 && planDays > 0) {
|
|
params.display_work_days = planDays
|
|
}
|
|
|
|
await this.$http('POST', '/api/admin/set_depart_worktime', {
|
|
...params
|
|
}).then(response => {
|
|
if (response.code == 0) {
|
|
this.$Message.success(response.msg || '设置成功')
|
|
// this.form.worktimes = worktimes;
|
|
this.getDoctorHosPreview();
|
|
}
|
|
}).catch(error => {
|
|
console.error(error, 'error')
|
|
})
|
|
},
|
|
|
|
// 检查排班冲突
|
|
checkScheduleConflict(newWorktimes, worktime_no_fixed) {
|
|
console.log(newWorktimes, worktime_no_fixed,this.rawScheduleData1, 'newWorktimes, worktime_no_fixed');
|
|
debugger
|
|
const conflicts = [];
|
|
let hasConflict = false;
|
|
|
|
if (!this.rawScheduleData1) {
|
|
return { hasConflict: false, conflicts: [] };
|
|
}
|
|
|
|
// console.log('开始冲突检测,当前设置医院:', this.depart_id);
|
|
// console.log('新排班设置:', newWorktimes);
|
|
// console.log('所有医院数据:', this.rawScheduleData1);
|
|
|
|
// 遍历所有其他医院的排班数据
|
|
Object.keys(this.rawScheduleData1).forEach(hospitalId => {
|
|
// 跳过当前正在设置的医院 (depart_id=4)
|
|
if (hospitalId === this.depart_id.toString()) {
|
|
console.log('跳过当前医院:', hospitalId);
|
|
return;
|
|
}
|
|
|
|
const hospital = this.rawScheduleData1[hospitalId];
|
|
console.log(`检查医院 ${hospitalId}: ${hospital.h_depart_name}`, hospital);
|
|
|
|
// 根据排班类型检查冲突
|
|
const hospitalConflicts = this.checkHospitalConflict(newWorktimes, hospital, worktime_no_fixed);
|
|
console.log(`医院 ${hospitalId} 的冲突:`, hospitalConflicts);
|
|
|
|
if (hospitalConflicts.length > 0) {
|
|
conflicts.push(...hospitalConflicts);
|
|
hasConflict = true;
|
|
}
|
|
});
|
|
|
|
console.log('最终冲突结果:', { hasConflict, conflicts });
|
|
return { hasConflict, conflicts };
|
|
},
|
|
// 检查单个医院的冲突
|
|
checkHospitalConflict(newWorktimes, hospital) {
|
|
debugger
|
|
const conflicts = [];
|
|
|
|
if (hospital.worktime_no_fixed === 0) {
|
|
// 对方是固定排班
|
|
conflicts.push(...this.checkVsFixedHospital(newWorktimes, hospital));
|
|
} else {
|
|
// 对方是非固定排班
|
|
conflicts.push(...this.checkVsNonFixedHospital(newWorktimes, hospital));
|
|
}
|
|
|
|
return conflicts;
|
|
},
|
|
// 检查与固定排班医院的冲突
|
|
checkVsFixedHospital(newWorktimes, hospital) {
|
|
const conflicts = [];
|
|
|
|
console.log('检查固定排班医院冲突:', hospital.h_depart_name, hospital.worktime_list);
|
|
|
|
// 遍历新设置的每周排班
|
|
Object.keys(newWorktimes).forEach(weekDay => {
|
|
const newPlan = newWorktimes[weekDay].plan;
|
|
if (newPlan === '0') {
|
|
return; // 休息不检查冲突
|
|
}
|
|
|
|
// 检查医院在该工作日的排班
|
|
const hospitalPlan = hospital.worktime_list && hospital.worktime_list[weekDay];
|
|
console.log(`周${weekDay}: 新排班=${newPlan}, 医院排班=`, hospitalPlan);
|
|
|
|
if (hospitalPlan && hospitalPlan.plan !== '0') {
|
|
// 获取冲突的具体时段
|
|
const conflictShift = this.getConflictShift(newPlan, hospitalPlan.plan);
|
|
if (conflictShift) {
|
|
console.log(`发现冲突: 周${weekDay} 新${newPlan} vs 医院${hospitalPlan.plan}, 冲突时段: ${conflictShift}`);
|
|
conflicts.push(this.createConflictInfo(
|
|
`每${this.getWeekDayName(parseInt(weekDay))}`,
|
|
hospital.h_depart_name,
|
|
newPlan,
|
|
conflictShift, // 这里改为冲突时段而不是医院排班
|
|
'固定排班',
|
|
hospitalPlan.work_paln_desc,
|
|
));
|
|
}
|
|
}
|
|
});
|
|
|
|
return conflicts;
|
|
},
|
|
// 检查与非固定排班医院的冲突
|
|
checkVsNonFixedHospital(newWorktimes, hospital) {
|
|
const conflicts = [];
|
|
|
|
console.log('检查非固定排班医院冲突:', hospital.h_depart_name, hospital.worktime_list);
|
|
|
|
if (!hospital.worktime_list) return conflicts;
|
|
|
|
// 遍历非固定排班医院的所有具体日期排班
|
|
Object.keys(hospital.worktime_list).forEach(dateStr => {
|
|
const hospitalPlan = hospital.worktime_list[dateStr];
|
|
if (!hospitalPlan || hospitalPlan.plan === '0') return;
|
|
|
|
// 获取该日期是星期几
|
|
const date = new Date(dateStr);
|
|
const dayOfWeek = date.getDay() === 0 ? 7 : date.getDay();
|
|
const weekDayKey = dayOfWeek.toString();
|
|
|
|
// 找到对应的新排班
|
|
const newSchedule = newWorktimes[weekDayKey];
|
|
if (!newSchedule || newSchedule.plan === '0') return;
|
|
|
|
// console.log(`日期${dateStr}(周${dayOfWeek}): 新排班=${newSchedule.plan}, 医院排班=${hospitalPlan.plan}`);
|
|
|
|
// 获取冲突的具体时段
|
|
const conflictShift = this.getConflictShift(newSchedule.plan, hospitalPlan.plan);
|
|
if (conflictShift) {
|
|
// console.log(`发现冲突: ${dateStr} 新${newSchedule.plan} vs 医院${hospitalPlan.plan}, 冲突时段: ${conflictShift}`);
|
|
conflicts.push(this.createConflictInfo(
|
|
dateStr,
|
|
hospital.h_depart_name,
|
|
newSchedule.plan,
|
|
conflictShift, // 这里改为冲突时段而不是医院排班
|
|
'非固定排班',
|
|
hospitalPlan.work_paln_desc,
|
|
this.weekPlan[dayOfWeek],//这个还需呀修改
|
|
|
|
));
|
|
}
|
|
});
|
|
|
|
return conflicts;
|
|
},
|
|
createConflictInfo(date, hospitalName, newPlan, conflictShift, scheduleType, workDesc, dayOfWeek) {
|
|
// console.log(dayOfWeek,this.getWeekDayName(1),'createConflictInfo:dayOfWeek');
|
|
const planMap = {
|
|
'0': '休息',
|
|
'1': '上午班',
|
|
'2': '下午班',
|
|
'3': '全天班'
|
|
};
|
|
|
|
const conflict = {
|
|
date: date,
|
|
hospital: hospitalName,
|
|
newPlan: planMap[newPlan],
|
|
conflictShift: conflictShift, // 改为冲突时段
|
|
scheduleType: scheduleType,
|
|
workDesc: workDesc,
|
|
dayOfWeek
|
|
// displayText: `${date} ${planMap[newPlan]} 与 ${hospitalName} ${conflictShift} 冲突`
|
|
};
|
|
|
|
console.log('创建冲突信息:', conflict);
|
|
return conflict;
|
|
},
|
|
getWeekDayName(weekDay) {
|
|
const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
|
|
return weekDays[weekDay - 1] || `周${weekDay}`;
|
|
},
|
|
getConflictShift(newPlan, existingPlan) {
|
|
const planMap = {
|
|
'0': '休息',
|
|
'1': '上午',
|
|
'2': '下午',
|
|
'3': '全天班'
|
|
};
|
|
|
|
// 如果一方是全天班,冲突时段就是另一方的班次
|
|
if (newPlan === '3') {
|
|
return planMap[existingPlan]; // 当前设置全天,冲突时段就是对方医院的班次
|
|
}
|
|
if (existingPlan === '3') {
|
|
return planMap[newPlan]; // 对方医院全天,冲突时段就是当前设置的班次
|
|
}
|
|
|
|
// 相同班次冲突
|
|
if (newPlan === existingPlan) {
|
|
return planMap[newPlan];
|
|
}
|
|
|
|
return null; // 无冲突
|
|
},
|
|
formatWorktimesArray(worktimes) {
|
|
return Object.entries(worktimes).map(([key, value]) => ({
|
|
type: parseInt(key),
|
|
plan: value.plan
|
|
}));
|
|
},
|
|
|
|
}
|
|
}
|
|
</script>
|
|
<style scoped lang="scss">
|
|
|
|
.visitContent {
|
|
max-height: 300px;
|
|
overflow-y: auto;
|
|
}
|
|
.conflictTitle {
|
|
display: flex;
|
|
margin-bottom: 24px;
|
|
font-size: 14px;
|
|
color: #333;
|
|
line-height: 1.5;
|
|
flex-wrap: wrap;
|
|
word-wrap: break-word;
|
|
word-break: break-word;
|
|
white-space: normal;
|
|
}
|
|
|
|
.conflictTitle b {
|
|
color: #1890ff;
|
|
font-weight: 600;
|
|
margin: 0 4px;
|
|
word-break: break-all;
|
|
}
|
|
.hosPlanItem {
|
|
p {
|
|
color: #1E2226;
|
|
margin-bottom: 14px;
|
|
}
|
|
|
|
div {
|
|
color: #8A9099;
|
|
}
|
|
}
|
|
|
|
.conflictTip {
|
|
height: 22px;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
padding: 2px 10px;
|
|
gap: 6px;
|
|
border-radius: 4px;
|
|
background: #FFF1F0;
|
|
box-sizing: border-box;
|
|
border: 1px solid #FFA39E;
|
|
font-size: 14px;
|
|
font-weight: normal;
|
|
line-height: normal;
|
|
text-align: center;
|
|
letter-spacing: 0.08em;
|
|
color: #FF4D4F;
|
|
box-sizing: border-box;
|
|
margin-right: 6px;
|
|
}
|
|
|
|
</style>
|