diff --git a/src/views/HosInformation.vue b/src/views/HosInformation.vue index 7c50569..6272813 100644 --- a/src/views/HosInformation.vue +++ b/src/views/HosInformation.vue @@ -365,8 +365,9 @@ -
+
{{ getDayNumber(data.day) }} @@ -389,7 +390,7 @@ class="schedule-item" :class="getScheduleItemClass(data.day, key)"> {{ - shiftType }} + shiftType }}
-
+
{{ getDayNumber(data.day) }} @@ -624,17 +625,23 @@
- {{ morningSelectedNames }} + +
+ 冲突 +
{{ morningText }}
+
- - + +
- {{ item.name }} + {{ item.name }}{{ item.morning_plan }}
- +
@@ -647,18 +654,25 @@ 下午班
- - {{ afternoonSelectedNames }} +
+ 冲突 +
{{ afterText }}
+ + +
- - + + +
{{ item.name }}
- +
@@ -691,6 +705,20 @@ + @@ -950,7 +978,7 @@ export default { singleHosTitle: '出诊日历',//单个医院弹框标题 temp_plans: null,//临时调诊 hosList: [],//医院信息 - hosListCopy:[],//医院信息备份 + hosListCopy: [],//医院信息备份 currentDay: new Date(), calendarList1: [], calendarList: {}, // 用于存储格式化后的排班数据 @@ -981,11 +1009,19 @@ export default { }], morningSelectedHospitals: [], // 上午班选中的医院ID数组 afternoonSelectedHospitals: [], // 下午班选中的医院ID数组 - // morningSelectedHospitals: [], // 上午班选中的医院ID数组 - // afternoonSelectedHospitals: [], // 下午班选中的医院ID数组 - isAfternoonDropdownOpen: false, - isMornDropdownOpen: false, - + morningSelectedHospitals1: [], // 上午班选中的医院ID数组备份 + afternoonSelectedHospitals1: [], // 下午班选中的医院ID数组备份 + isAfternoonDropdownOpen: false,//下午班下拉是否展开 + isMornDropdownOpen: false,//上午班下拉是否展开 + visitDialogTitle: '出诊安排重叠,请确认',//出诊冲突框标题 + visitDialogVisible: true,//出诊冲突提示框 + visitShowCancelBtn: false,//出诊冲突框是否显示取消按钮 + visitConfirmText: '确定',//出诊冲突框确认按钮文字 + hasConflictresult: [], + hasConflict: false, // 控制冲突提示显示 + originalMorningSelected: [], // 保存原始上午选中状态 + originalAfternoonSelected: [], // 保存原始下午选中状态 + forceTime: Date.now(), } }, created() { @@ -1003,7 +1039,7 @@ export default { this.depart_id = depart_id; this.doctor_id = doctor_id; await this.fetchDoctorData() - console.log(this.doctor_id) + // console.log(this.doctor_id) await this.getAreaData() this.fetchPackData() this.fetchProjectData() @@ -1075,11 +1111,39 @@ export default { }); return configs; }, - morningSelectedNames() { - return this.getSelectedNames(this.morningSelectedHospitals); + morningCheckboxVisibility() { + if (this.is_allow_coincide) return 'all'; // 允许重合时显示所有 + + if (this.morningSelectedHospitals.length === 0) { + return 'all'; // 没有选中时显示所有 + } else if (this.morningSelectedHospitals.length === 1) { + return 'selectedOnly'; // 有一个选中时只显示选中的 + } + return 'all'; // 多个选中时显示所有(冲突情况) }, - afternoonSelectedNames() { - return this.getSelectedNames(this.afternoonSelectedHospitals); + + // 控制下午班checkbox显示状态 + afternoonCheckboxVisibility() { + if (this.is_allow_coincide) return 'all'; + + if (this.afternoonSelectedHospitals.length === 0) { + return 'all'; + } else if (this.afternoonSelectedHospitals.length === 1) { + return 'selectedOnly'; + } + return 'all'; + }, + + // 检查上午班是否有冲突 + isMorningConflict() { + if (this.is_allow_coincide) return false; + return this.morningSelectedHospitals.length > 1; + }, + + // 检查下午班是否有冲突 + isAfternoonConflict() { + if (this.is_allow_coincide) return false; + return this.afternoonSelectedHospitals.length > 1; }, selectedCount() { @@ -1088,8 +1152,55 @@ export default { ...mapState(['hosMenuData']) // 从Vuex映射showSidebar状态到组件的计算属性中 }, methods: { + // 出诊冲突提示-确认 + handleVisitConfirm(){ + + }, + // 出诊冲突提示框-取消 + handleVisitCancel(){ + + }, + // 出诊冲突提示框-关闭 + handleVisitClose(){ + + }, + isMorningCheckboxVisible(hospitalId) { + if (this.is_allow_coincide) return true; + + if (this.morningCheckboxVisibility === 'all') { + return true; + } else if (this.morningCheckboxVisibility === 'selectedOnly') { + return this.morningSelectedHospitals.includes(hospitalId); + } + return true; + }, + + // 控制下午班checkbox显示 + isAfternoonCheckboxVisible(hospitalId) { + if (this.is_allow_coincide) return true; + + if (this.afternoonCheckboxVisibility === 'all') { + return true; + } else if (this.afternoonCheckboxVisibility === 'selectedOnly') { + return this.afternoonSelectedHospitals.includes(hospitalId); + } + return true; + }, + morningSelectedNames() { + // console.log('执行了1次', this.morningSelectedHospitals); + return this.getSelectedNames(this.morningSelectedHospitals); + }, + afternoonSelectedNames() { + return this.getSelectedNames(this.afternoonSelectedHospitals); + }, + isFutureOrToday(dateString) { + const date = new Date(dateString); + const today = new Date(); + today.setHours(0, 0, 0, 0); + return date >= today; + }, getSelectedNames(selectedList) { - console.log(selectedList,'getSelectedNames----selectedList===='); + // console.log(selectedList, 'getSelectedNames----selectedList===='); if (selectedList.length === 0) { return '不出诊'; } @@ -1098,11 +1209,11 @@ export default { const hospital = this.hosList.find(item => item.hid === hid); return hospital ? hospital.name : ''; }).filter(name => name); -console.log(selectedNames,'getSelectedNames--selectedNames'); + // console.log(selectedNames, 'getSelectedNames--selectedNames'); return selectedNames.join('、') || '休息'; }, toggleAfternoonDropdown() { - console.log('----09999',this.afternoonSelectedHospitals); + // console.log('----09999', this.afternoonSelectedHospitals); if (this.isAfternoonDropdownOpen) { this.$refs.afternoonSelect.blur(); } else { @@ -1146,7 +1257,7 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); getDateCellClass(dateString) { const schedule = this.getDateSchedule(dateString); - console.log(schedule, 'getDateCellClass-schedule'); + // console.log(schedule, 'getDateCellClass-schedule'); if (!schedule) return ''; for (const key in schedule) { if (key !== '0' && schedule[key] && schedule[key].length > 0) { @@ -1162,91 +1273,178 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); return ''; }, - // 处理上午班checkbox直接变化 - handleWorkCheckDirect(item, checked,workHos) { + handleWorkCheckDirect(item, checked, workHosType) { + // console.log('checkbox变化:', { + // item: item.name, + // checked, + // workHosType, + // currentMorning: [...this.morningSelectedHospitals], + // currentAfternoon: [...this.afternoonSelectedHospitals] + // }); + if (checked) { - if(workHos == 'afternoonSelectedHospitals'){ - item.afternoon_plan = '1' - }else{ - item.morning_plan = '1' + this.selectMorningHospital(item.hid, workHosType); + } else { + this.deselectMorningHospital(item.hid, workHosType); + } + this.forceTime = Date.now(); // 强制更新时间,触发视图重新渲染 + }, + + + selectMorningHospital(hospitalId, workHosType) { + // console.log('selectMorningHospital 开始:', { + // hospitalId, + // workHosType, + // morningSelected: [...this.morningSelectedHospitals], + // afternoonSelected: [...this.afternoonSelectedHospitals] + // }); + + // 如果不允许重合,实现互斥选择 + if (!this.is_allow_coincide) { + if (workHosType === 'morningSelectedHospitals') { + // 清空上午班所有选中状态 + this.morningSelectedHospitals = []; + // 更新所有医院的上午班状态为0 + this.hosList.forEach(hospital => { + hospital.morning_plan = '0'; + }); + + // 选中当前医院 + this.morningSelectedHospitals = [hospitalId]; + // 更新当前医院的上午班状态为1 + this.hosList.forEach(hospital => { + if (hospital.hid === hospitalId) { + hospital.morning_plan = '1'; + } + }); + } else { + // 清空下午班所有选中状态 + this.afternoonSelectedHospitals = []; + // 更新所有医院的下午班状态为0 + this.hosList.forEach(hospital => { + hospital.afternoon_plan = '0'; + }); + + // 选中当前医院 + this.afternoonSelectedHospitals = [hospitalId]; + // 更新当前医院的下午班状态为1 + this.hosList.forEach(hospital => { + if (hospital.hid === hospitalId) { + hospital.afternoon_plan = '1'; + } + }); } - this.selectMorningHospital(item.hid,workHos); } else { - if(workHos == 'afternoonSelectedHospitals'){ - item.afternoon_plan = '0' - }else{ - item.morning_plan = '0' + // 允许重合,正常多选 + const targetList = workHosType === 'morningSelectedHospitals' + ? this.morningSelectedHospitals + : this.afternoonSelectedHospitals; + + if (!targetList.includes(hospitalId)) { + if (workHosType === 'morningSelectedHospitals') { + this.morningSelectedHospitals = [...targetList, hospitalId]; + } else { + this.afternoonSelectedHospitals = [...targetList, hospitalId]; + } + + // 更新医院状态 + this.hosList.forEach(hospital => { + if (hospital.hid === hospitalId) { + if (workHosType === 'morningSelectedHospitals') { + hospital.morning_plan = '1'; + } else { + hospital.afternoon_plan = '1'; + } + } + }); } - this.deselectMorningHospital(item.hid,workHos); - } - // this.hosList = this.hosList.map(item1 => { - // if(item1.hid == item.hid){ - // return { - // ...item1, - // morning_plan:checked ? '1' : '0' - // } - // } - // }); // 触发视图更新 + } + + // console.log('selectMorningHospital 结束:', { + // morningSelected: [...this.morningSelectedHospitals], + // afternoonSelected: [...this.afternoonSelectedHospitals], + // hosList: this.hosList.map(h => ({ + // name: h.name, + // morning_plan: h.morning_plan, + // afternoon_plan: h.afternoon_plan + // })) + // }); + + this.updateSelectedText(); + this.checkConflicts(); }, - // 选中上午班医院 - selectMorningHospital(hospitalId,workHos) { - if (!this.is_allow_coincide && this[workHos].length >= 1) { - // 不允许重合时,只能选一个,先清空再添加 - this[workHos] = [hospitalId]; + + + clearAllSelections(workHosType) { + if (workHosType === 'morningSelectedHospitals') { + this.morningSelectedHospitals = []; + // 更新医院状态 + this.hosList.forEach(hospital => { + hospital.morning_plan = '0'; + }); + } else { + this.afternoonSelectedHospitals = []; + // 更新医院状态 + this.hosList.forEach(hospital => { + hospital.afternoon_plan = '0'; + }); + } + }, + // 修改取消选中的方法 + deselectMorningHospital(hospitalId, workHosType) { + if (workHosType === 'morningSelectedHospitals') { + this.morningSelectedHospitals = this.morningSelectedHospitals.filter(id => id !== hospitalId); } else { - // 允许重合或还没有选中任何项 - if (!this[workHos].includes(hospitalId)) { - console.log(workHos,this[workHos],'workHos00000'); + this.afternoonSelectedHospitals = this.afternoonSelectedHospitals.filter(id => id !== hospitalId); + } - this[workHos].push(hospitalId); + // 更新医院状态 + this.hosList.forEach(hospital => { + if (hospital.hid === hospitalId) { + if (workHosType === 'morningSelectedHospitals') { + hospital.morning_plan = '0'; + } else { + hospital.afternoon_plan = '0'; + } } - } - console.log(this.hosList,this['afternoonSelectedHospitals'],'hos===this.hosList'); + }); + this.updateSelectedText(); + this.checkConflicts(); // 取消选中后检查冲突 }, - // 取消选中上午班医院 - deselectMorningHospital(hospitalId,workHos) { - this[workHos] = this[workHos].filter(id => id !== hospitalId); + // 添加更新文本的方法 + updateSelectedText() { + this.morningText = this.morningSelectedNames() + this.afterText = this.afternoonSelectedNames() }, - // 日历点击 handleDateClick(dateString, event) { event.stopPropagation(); - // 可修改今天及之后的数据 + // isConflictDate() const clickedDate = new Date(dateString); const today = new Date(); - today.setHours(0, 0, 0, 0); // 清除时间部分,只比较日期 - + today.setHours(0, 0, 0, 0); + if (clickedDate < today) { this.$Message.warning('无法调整过去的日期'); return; } - - // // 检查是否有排班数据 - // if (!this.hasScheduleData(dateString)) { - // console.log('该日期无排班数据'); - // return; - // } - // 获取当天对应的周几信息 - const date1 = new Date(dateString); - const day = date1.getDay() - const dayText = day == 0 ? '周日' : this.weekPlan[day] - this.currentEditingDate = this.formatMonth(dateString, true) + ` ${dayText}` - this.isShowDialogDate = this.hasTempAdjustments(dateString) - // console.log('点击日期:000', this.isShowDialogDate, '999998888888', date1, this.currentEditingDate, dayText, dateString); + + this.currentEditingDate = this.formatMonth(dateString, true) + ` ${this.weekDaysDesc[clickedDate.getDay()]}`; + this.isShowDialogDate = this.hasTempAdjustments(dateString); + if (this.isShowDialogDate) { - this.singleHosTitle = dayText + '出诊规则' + this.singleHosTitle = this.weekDaysDesc[clickedDate.getDay()] + '出诊规则'; } - // 获取该日期的排班信息 - // const schedule = this.getDateSchedule(dateString); - // if (!schedule) return; // 获取该日期涉及的所有医院 const hospitals = this.getHospitalsByDate(dateString); - // console.log(this.hosListCopy,this.hosList,'=====测试一下两组数据源'); - // 重构一下医院数据,增加上下午出诊状态 + + // console.log('点击日期获取到的医院数据:', hospitals); + + // 重构医院数据,确保正确设置上下午出诊状态 this.hosList = this.hosListCopy.map(item => { let hospitalInfo = { hid: item.hid, @@ -1254,75 +1452,119 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); workTime: '休息', originalPlan: '0', currentPlan: '0', - isCancelled: false // 明确标记为取消 - }; - if(hospitals.length > 0){ - hospitals.forEach(hospital => { - if (hospital.hid === item.hid) { - hospitalInfo = { ...hospital } - if (hospital.currentPlan == '1') { - hospitalInfo.morning_plan = '1' - hospitalInfo.afternoon_plan = '0' - } else if (hospital.currentPlan == '2') { - hospitalInfo.afternoon_plan = '1' - hospitalInfo.morning_plan = '0' - } else if (hospital.currentPlan == '3') { - hospitalInfo.morning_plan = '1' - hospitalInfo.afternoon_plan = '1' - }else{ - hospitalInfo.morning_plan = '0' - hospitalInfo.afternoon_plan = '0' - } - } - }) - } - // console.log(hospitalInfo, ' ...hospitalInfo'); - return { + isCancelled: false, morning_plan: '0', - afternoon_plan: '0', - ...item, - ...hospitalInfo, + afternoon_plan: '0' + }; + + // 查找该医院在当前日期的排班信息 + const hospitalSchedule = hospitals.find(h => h.hid === item.hid); + if (hospitalSchedule) { + hospitalInfo = { ...hospitalInfo, ...hospitalSchedule }; + + // 根据 currentPlan 设置上下午状态 + switch (hospitalSchedule.currentPlan) { + case '1': // 上午班 + hospitalInfo.morning_plan = '1'; + hospitalInfo.afternoon_plan = '0'; + break; + case '2': // 下午班 + hospitalInfo.morning_plan = '0'; + hospitalInfo.afternoon_plan = '1'; + break; + case '3': // 全天班 + hospitalInfo.morning_plan = '1'; + hospitalInfo.afternoon_plan = '1'; + break; + default: // 休息或其他 + hospitalInfo.morning_plan = '0'; + hospitalInfo.afternoon_plan = '0'; + break; + } } - }) - // console.log(hospitals, this.hosList, 'hospitals==='); + + console.log(`医院 ${item.h_depart_name} 排班状态:`, { + currentPlan: hospitalInfo.currentPlan, + morning_plan: hospitalInfo.morning_plan, + afternoon_plan: hospitalInfo.afternoon_plan + }); + + return hospitalInfo; + }); + + // console.log('处理后的医院列表:', this.hosList); // 根据医院数量决定弹出哪种对话框 if (this.hosList.length === 1) { - // 单医院 this.currentEditingHospital = hospitals[0]; this.singleHosVisiable = true; } else { this.initSelectedHospitals(this.hosList); - // 多医院 + this.moreHosVisiable = true; } - }, - // 初始化选中医院 initSelectedHospitals(hospitals) { - - this.morningSelectedHospitals = []; - this.afternoonSelectedHospitals = []; + // console.log('开始初始化选中医院:', hospitals); + + // 保存原始选中状态 + this.originalMorningSelected = [...this.morningSelectedHospitals]; + this.originalAfternoonSelected = [...this.afternoonSelectedHospitals]; + + this.$set(this, 'morningSelectedHospitals', []); + this.$set(this, 'afternoonSelectedHospitals', []); hospitals.forEach(hospital => { const { hid, morning_plan, afternoon_plan } = hospital; + console.log(`医院 ${hospital.name} 状态:`, { + hid, + morning_plan, + afternoon_plan + }); + if (morning_plan === '1') { - this.morningSelectedHospitals.push(hid); + this.morningSelectedHospitals = [...this.morningSelectedHospitals, hid]; } if (afternoon_plan === '1') { - this.afternoonSelectedHospitals.push(hid); + this.afternoonSelectedHospitals = [...this.afternoonSelectedHospitals, hid]; } }); - console.log(hospitals,this.morningSelectedHospitals, this.afternoonSelectedHospitals, 'initSelectedHospitals-初始化的喧哗走ing'); - this.moreHosVisiable = true; + + this.updateSelectedText(); + this.checkConflicts(); // 初始化时检查冲突 + // console.log('初始化完成:', this.morningText, this.afternoonSelectedHospitals); + }, + checkConflicts() { + if (this.is_allow_coincide) { + this.hasConflict = false; + return; + } + + // 检查上午班和下午班是否有冲突 + const morningConflict = this.morningSelectedHospitals.length > 1; + const afternoonConflict = this.afternoonSelectedHospitals.length > 1; + + this.hasConflict = morningConflict || afternoonConflict; + + console.log('冲突检查结果:', { + morningConflict, + afternoonConflict, + hasConflict: this.hasConflict + }); }, - // 确认多医院临时调诊 + // 修改确认多医院临时调诊的方法 async moreTempConfirm() { try { + // 检查冲突 + if (this.hasConflict && !this.is_allow_coincide) { + this.$message.error('存在时段冲突,请调整出诊安排后再保存'); + return; + } + const plans = []; - console.log('moreTempConfirm:',this.hosList); + // console.log('moreTempConfirm:', this.hosList); // 处理所有医院,为每个医院生成对应的排班计划 this.hosList.forEach(hospital => { const { hid } = hospital; @@ -1349,19 +1591,28 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); }); }); - console.log('保存的排班数据:', plans); + // console.log('保存的排班数据:', plans); - await this.saveTempAdjustment(this.currentEditingDate, plans); + // await this.saveTempAdjustment(this.currentEditingDate, plans); this.moreHosVisiable = false; + + // 重置选中状态 + this.$nextTick(() => { + this.morningSelectedHospitals = []; + this.afternoonSelectedHospitals = []; + this.hasConflict = false; + }); + } catch (error) { console.error('保存多医院调诊失败:', error); this.$message.error('保存失败'); } }, + // 设置临时调诊数据---- async saveTempAdjustment(dateString, newPlan) { - console.log(newPlan, 'newPlan===='); + // console.log(newPlan, 'newPlan===='); try { const response = await this.$http('POST', '/api/admin/set_visit_change', { doctor_id: this.doctor_id, @@ -1371,8 +1622,12 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); if (response.code === 0) { this.$message.success('临时调整保存成功'); - this.afternoonSelectedHospitals = []; - this.morningSelectedHospitals = []; + // this.afternoonSelectedHospitals = []; + // this.morningSelectedHospitals = []; + this.$nextTick(() => { + this.morningSelectedHospitals = []; + this.afternoonSelectedHospitals = []; + }); // 重新加载排班数据 this.getDoctorHosPreview(); } else { @@ -1383,20 +1638,25 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); this.$message.error('保存失败'); } }, - // 获取指定日期涉及的所有医院 getHospitalsByDate(dateString) { const schedule = this.getDateSchedule(dateString); - if (!schedule) return []; + if (!schedule) { + console.log(`日期 ${dateString} 无排班数据`); + return []; + } const hospitals = []; + // console.log(`日期 ${dateString} 的排班数据:`, schedule); // 遍历所有班次类型收集医院 Object.keys(schedule).forEach(shiftType => { - const list = schedule[shiftType] - console.log(schedule, list, 'schedule----'); if (['_isTempAdjust', '_conflicts', '0'].includes(shiftType)) return; + + const list = schedule[shiftType]; + // console.log(`班次 ${shiftType} 的医院列表:`, list); + if (Array.isArray(list) && list.length > 0) { - list.map(hospital => { + list.forEach(hospital => { // 检查是否已存在 const exists = hospitals.some(h => h.hid === hospital.hid); if (!exists) { @@ -1408,40 +1668,49 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); isCancelled: hospital.isCancelled, workTime: hospital.workTime }); + // console.log(`添加医院到列表: ${hospital.hospital_name}`, hospital); } }); } }); - console.log(hospitals, 'hospitals==='); + // console.log(`最终获取到的医院列表:`, hospitals); return hospitals; }, + // forceUpdateSelection() { + // this.$nextTick(() => { + // console.log('强制刷新选中状态'); + // this.morningSelectedHospitals = [...this.morningSelectedHospitals]; + // this.afternoonSelectedHospitals = [...this.afternoonSelectedHospitals]; + // }); + // }, // 形成出诊文案 getWorkTimeDisplayText(hospital, dateStr, hospitalId) { const hospitalData = this.rawScheduleData[hospitalId]; - if (!hospitalData) return hospital.workTime; - // console.log(hospitalData,hospital,'hospitalData===='); const { morning_worktime, afternoon_worktime, temp_change_worktime } = hospitalData; - // console.log(morning_worktime, 'morning_worktime==='); let allDay_worktime = ''; + if ((hospital.currentPlan == 3 || hospital.originalPlan == 3) && (morning_worktime && afternoon_worktime)) { allDay_worktime = morning_worktime.slice(0, 5) + '-' + afternoon_worktime.slice(-5); } - // console.log(allDay_worktime,'allDay_worktime==='); - // 检查是否有临时调整 - const hasTempAdjustment = temp_change_worktime && temp_change_worktime[dateStr]; - // 获取班次类型对应的中文 + // 检查是否有冲突 + const schedule = this.getDateSchedule(dateStr); + const hasConflict = schedule && schedule._conflicts && schedule._conflicts.length > 0; + const isInConflict = hasConflict && schedule._conflicts.some(conflict => + conflict.hospitals.some(h => h.startsWith(`${hospitalId}_`)) + ); + const planTextMap = { '1': '上午班', '2': '下午班', '3': '全天班', '0': '休息' }; - // 对应的班次时间映射表 + const workTimeTextMap = { '1': morning_worktime, '2': afternoon_worktime, @@ -1452,23 +1721,23 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); let planText = planTextMap[hospital.currentPlan] || '休息'; let workTimeText = workTimeTextMap[hospital.currentPlan]; - // 如果是临时取消了,那就显示原来的出诊时间 if (hospital.currentPlan != hospital.originalPlan && hospital.currentPlan == 0) { workTimeText = workTimeTextMap[hospital.originalPlan] || '休息'; } - // 如果是取消状态 + // 添加冲突标识 + const conflictMark = isInConflict ? ' ⚠️' : ''; + if (hospital.isCancelled) { - return `${workTimeText} (固定${planTextMap[hospital.originalPlan] || ''})`; + return `${workTimeText} (固定${planTextMap[hospital.originalPlan] || ''})${conflictMark}`; } - // 如果有临时调整 + const hasTempAdjustment = temp_change_worktime && temp_change_worktime[dateStr]; if (hasTempAdjustment) { - return `${workTimeText} (临时${planText})`; + return `${workTimeText} (临时${planText})${conflictMark}`; } - // 固定排班 - return `${workTimeText} (固定${planText})`; + return `${workTimeText} (固定${planText})${conflictMark}`; }, getColorTagClass(dateStr, hospitalId, shiftType) { @@ -1507,6 +1776,7 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); } }, + // 获取颜色标签配置 // getColorTagConfig(dateStr, hospitalId, shiftType) { // const key = `${dateStr}_${hospitalId}_${shiftType}`; @@ -1531,9 +1801,9 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); // 其他状态的班次(保持原有逻辑) const status = this.getTempAdjustmentStatus(dateStr, hospitalId, hospital.originalPlan); - if (dateStr == '2025-11-12') { - console.log(status, 'getColorTagConfig:status==='); - } + // if (dateStr == '2025-11-12') { + // // console.log(status, 'getColorTagConfig:status==='); + // } switch (status) { case 'cancelled': @@ -1607,9 +1877,9 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); const adjustment = this.tempAdjustments[dateStr][hospitalId]; const newPlan = adjustment.newPlan.toString(); const originalPlanStr = originalPlan.toString(); - if (dateStr == '2025-11-12' && hospitalId == 7) { - console.log(`getTempAdjustmentStatus: ${dateStr}, 医院=${hospitalId}, 原计划=${originalPlanStr}, 新计划=${newPlan}`); - } + // if (dateStr == '2025-11-12' && hospitalId == 7) { + // console.log(`getTempAdjustmentStatus: ${dateStr}, 医院=${hospitalId}, 原计划=${originalPlanStr}, 新计划=${newPlan}`); + // } if (newPlan === "0" && originalPlanStr !== "0") { // console.log(` - 状态: cancelled (班次取消)`); return 'cancelled'; @@ -1678,6 +1948,8 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); }, // 统计本月多医院出诊冲突 countMonthlyConflicts() { + // console.log('=== 开始月度冲突统计 ==='); + const monthStart = new Date(this.currentDay.getFullYear(), this.currentDay.getMonth(), 1); const monthEnd = new Date(this.currentDay.getFullYear(), this.currentDay.getMonth() + 1, 0); const today = new Date(); @@ -1686,44 +1958,93 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); const conflicts = []; let conflictCount = 0; - // 遍历本月每一天 const currentDate = new Date(monthStart); while (currentDate <= monthEnd) { - // 只统计今天及之后的日期 if (currentDate >= today) { const dateStr = this.formatDate(currentDate); - const schedule = this.getDateSchedule(dateStr); - - if (schedule && this.hasScheduleConflict(schedule)) { - conflicts.push(dateStr); - conflictCount++; + const schedule = this.calendarList[dateStr]; + + if (schedule) { + const hasConflict = this.hasScheduleConflict(schedule); + if (hasConflict) { + conflicts.push(dateStr); + conflictCount++; + console.log(`统计到冲突: ${dateStr}`); + } + } else { + console.log(`无排班数据: ${dateStr}`); } } - currentDate.setDate(currentDate.getDate() + 1); } this.conflictDates = conflicts; this.conflictCount = conflictCount; - }, - // 检查某一天的排班是否有冲突(同班次多个医院) + // console.log('=== 月度冲突统计结果 ===', { + // 冲突天数: conflictCount, + // 冲突日期: conflicts, + // 日历数据: this.calendarList + // }); + }, + // 检查排班是否存在冲突(不允许时段重合时) hasScheduleConflict(schedule) { - // 遍历所有班次类型(上午班、下午班、全天班) + if (this.is_allow_coincide) return false; // 如果允许重合,直接返回无冲突 + + // console.log('=== 开始冲突检测 ===', schedule._dateStr); + + const timeSlots = { + morning: new Set(), // 上午时段 + afternoon: new Set() // 下午时段 + }; + + // 遍历所有班次 for (const shiftType in schedule) { - // 跳过标记字段和非班次类型 - if (shiftType === '_isTempAdjust' || shiftType === '0') continue; + if (['_isTempAdjust', '_conflicts', '_dateStr', '0'].includes(shiftType)) continue; const hospitals = schedule[shiftType]; - // 如果同一班次有超过1家医院,则认为有冲突 - if (hospitals && hospitals.length > 1) { - return true; - } + if (!hospitals || hospitals.length === 0) continue; + + console.log(`班次 ${shiftType}:`, hospitals); + + hospitals.forEach(hospital => { + if (hospital.isCancelled) return; // 跳过已取消的 + + const hospitalKey = `${hospital.hid}_${hospital.hospital_name}`; + + switch (shiftType) { + case '1': // 上午班 + timeSlots.morning.add(hospitalKey); + break; + case '2': // 下午班 + timeSlots.afternoon.add(hospitalKey); + break; + case '3': // 全天班 + timeSlots.morning.add(hospitalKey); + timeSlots.afternoon.add(hospitalKey); + break; + } + }); } - return false; + + const hasMorningConflict = timeSlots.morning.size > 1; + const hasAfternoonConflict = timeSlots.afternoon.size > 1; + const hasConflict = hasMorningConflict || hasAfternoonConflict; + + if (hasConflict) { + console.log(`冲突检测结果 ${schedule._dateStr}:`, { + 上午时段医院: Array.from(timeSlots.morning), + 下午时段医院: Array.from(timeSlots.afternoon), + 上午冲突: hasMorningConflict, + 下午冲突: hasAfternoonConflict + }); + } + + return hasConflict; }, // 判断是否为冲突日期 isConflictDate(dateString) { + // console.log(this.conflictDates, dateString, '冲突日期'); return this.conflictDates.includes(dateString); }, // 添加月份变化监听方法 @@ -1929,6 +2250,12 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); this.generateMonthSchedule(this.currentDay); this.hosLength = Object.keys(list).length; + + // 立即生成排班并检测冲突 + await this.$nextTick(); + this.generateMonthSchedule(this.currentDay); + this.countMonthlyConflicts(); + // } // }).catch(error => { // console.error(error, 'error') @@ -1938,25 +2265,33 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); generateMonthSchedule(date) { if (!this.rawScheduleData) return; - const monthStart = new Date(date.getFullYear(), date.getMonth(), 1); - const monthEnd = new Date(date.getFullYear(), date.getMonth() + 1, 0); + const calendar = new Date(date); + const currentMonth = calendar.getMonth(); + const currentYear = calendar.getFullYear(); + + // 获取日历可见范围(通常包含上个月末、当前月、下个月初) + const visibleStart = new Date(currentYear, currentMonth, 1); + visibleStart.setDate(1); // 当月第一天 + + // 计算当月最后一天 + // const monthEnd = new Date(currentYear, currentMonth + 1, 0); + + // 计算下个月的前几天(通常日历显示6周,约42天) + const visibleEnd = new Date(currentYear, currentMonth, 1); + visibleEnd.setDate(42); // 显示6周的数据 + const today = new Date(); - // 如果整个月份都在今天之前,则不生成排班 - if (monthEnd < today) { - this.calendarList = {}; - this.conflictDates = []; // 清空冲突数据 - this.conflictCount = 0; - return; - } + today.setHours(0, 0, 0, 0); + // 只生成今天及之后的排班 - const startDate = today > monthStart ? today : monthStart; + const startDate = today > visibleStart ? today : visibleStart; - this.generateScheduleForDateRange(startDate, monthEnd); - this.countMonthlyConflicts(); // 添加统计 + this.generateScheduleForDateRange(startDate, visibleEnd); + this.countMonthlyConflicts(); }, // 为日期范围生成排班 generateScheduleForDateRange(startDate, endDate) { - const tempCalendarData = { ...this.calendarList }; + const tempCalendarData = {}; const currentDate = new Date(startDate); // 清空临时调整数据 @@ -1964,20 +2299,23 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); while (currentDate <= endDate) { const dateStr = this.formatDate(currentDate); - - // 重新生成排班数据,确保临时调整信息正确设置 const daySchedule = this.getScheduleForDate(currentDate); if (daySchedule && Object.keys(daySchedule).length > 1) { tempCalendarData[dateStr] = daySchedule; - } else { - delete tempCalendarData[dateStr]; + + // 立即检查冲突 + const hasConflict = this.hasScheduleConflict(daySchedule); + if (hasConflict) { + console.log(`日期 ${dateStr} 存在冲突`); + } } currentDate.setDate(currentDate.getDate() + 1); } this.calendarList = tempCalendarData; + console.log('最终排班数据:', this.calendarList); }, isTempAdjustDate(dateString) { @@ -1997,12 +2335,8 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); const dateStr = daySchedule._dateStr; const originalPlan = this.getOriginalPlan(dateStr, hospitalId); - // console.log(` - addHospitalToSchedule: 医院=${hospitalId}, 当前计划=${shiftType}, 原计划=${originalPlan}`); - // 处理临时取消的班次 if (shiftType === "0" && originalPlan !== "0") { - // console.log(` - 检测到临时取消: 医院=${hospitalId}, 原班次=${originalPlan}`); - if (!daySchedule[originalPlan]) { daySchedule[originalPlan] = []; } @@ -2013,7 +2347,7 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); workTime: '已取消', originalPlan: originalPlan, currentPlan: shiftType, - isCancelled: true // 明确标记为取消 + isCancelled: true }; const existingIndex = daySchedule[originalPlan].findIndex(item => item.hid === hospitalId); @@ -2027,6 +2361,7 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); // 正常班次 if (shiftType !== "0") { + // 对于全天班,不需要特殊处理,就按全天班显示 if (!daySchedule[shiftType]) { daySchedule[shiftType] = []; } @@ -2131,21 +2466,61 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); return Object.keys(daySchedule).length > 1 ? daySchedule : null; }, // 检查排班冲突 - checkScheduleConflicts(daySchedule, dateStr) { - console.log(dateStr); + checkScheduleConflicts(daySchedule) { + if (!this.is_allow_coincide) return; + daySchedule._conflicts = []; + + const timeSlotConflicts = { + 'morning': new Set(), + 'afternoon': new Set() + }; + + // 收集每个时间段的医院 for (const shiftType in daySchedule) { - if (shiftType === '_isTempAdjust' || shiftType === '_conflicts' || shiftType === '0') continue; + if (shiftType === '_isTempAdjust' || shiftType === '_conflicts' || shiftType === '_dateStr' || shiftType === '0') continue; const hospitals = daySchedule[shiftType]; - if (hospitals && hospitals.length > 1) { - daySchedule._conflicts.push({ - shiftType: shiftType, - hospitals: hospitals + if (hospitals && hospitals.length > 0) { + const activeHospitals = hospitals.filter(hospital => + !hospital.isCancelled && hospital.currentPlan !== "0" + ); + + activeHospitals.forEach(hospital => { + switch (shiftType) { + case '1': // 上午班 + timeSlotConflicts.morning.add(`${hospital.hid}_${hospital.hospital_name}`); + break; + case '2': // 下午班 + timeSlotConflicts.afternoon.add(`${hospital.hid}_${hospital.hospital_name}`); + break; + case '3': // 全天班 + timeSlotConflicts.morning.add(`${hospital.hid}_${hospital.hospital_name}`); + timeSlotConflicts.afternoon.add(`${hospital.hid}_${hospital.hospital_name}`); + break; + } }); } } + + // 记录冲突详情 + if (timeSlotConflicts.morning.size > 1) { + daySchedule._conflicts.push({ + timeSlot: 'morning', + hospitals: Array.from(timeSlotConflicts.morning), + message: `上午班冲突: ${Array.from(timeSlotConflicts.morning).map(h => h.split('_')[1]).join('、')}` + }); + } + + if (timeSlotConflicts.afternoon.size > 1) { + daySchedule._conflicts.push({ + timeSlot: 'afternoon', + hospitals: Array.from(timeSlotConflicts.afternoon), + message: `下午班冲突: ${Array.from(timeSlotConflicts.afternoon).map(h => h.split('_')[1]).join('、')}` + }); + } + console.log(daySchedule,'daySchedule===='); }, @@ -2213,9 +2588,14 @@ console.log(selectedNames,'getSelectedNames--selectedNames'); // 取消多医院临时调诊 moreTempCancel() { this.moreHosVisiable = false; - this.afternoonSelectedHospitals = []; - this.morningSelectedHospitals = []; + this.$nextTick(() => { + this.morningSelectedHospitals = []; + this.afternoonSelectedHospitals = []; + }); + // this.afternoonSelectedHospitals = []; + // this.morningSelectedHospitals = []; }, + // 判断是否是当月 isCurrentMonth(date) { const current = new Date(); const target = new Date(date); @@ -3206,6 +3586,14 @@ console.log(selectedNames,'getSelectedNames--selectedNames');