3 changed files with 647 additions and 513 deletions
@ -0,0 +1,588 @@ |
|||
<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> |
|||
Loading…
Reference in new issue