You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1325 lines
39 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div>
<div class="head">
<el-row style="display: flex; justify-content: end;">
<!-- <el-form-item>
<el-select :filterable="true" clearable v-model="searchInfo.department_id" placeholder="选择科室"
style="margin-left: 8px;width: 150px;">
<el-option v-for="(item,index) in EnableDepartmentList" :key="index"
:label="item.department_name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item>
<el-select :filterable="true" clearable v-model="searchInfo.resources_id" placeholder="选择资源"
style="margin-left: 8px;width: 150px;">
<el-option v-for="(item,index) in enableResourceList" :key="index"
:label="item.department_resources_name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item>
<el-select :filterable="true" clearable v-model="searchInfo.device_id" placeholder="选择服务组"
style="margin-left: 8px;width: 150px;">
<el-option v-for="(item,index) in EnableDeviceList" :key="index" :label="item.device_name"
:value="item.id" />
</el-select>
</el-form-item>
<el-form-item>
<el-select :filterable="true" clearable v-model="searchInfo.xingqi" placeholder="星期"
style="margin-left: 8px;width: 150px;">
<el-option v-for="(item,index) in xingqi" :key="index" :label="item.label"
:value="item.label" />
</el-select>
</el-form-item>
<el-form-item>
<el-select :filterable="true" clearable v-model="searchInfo.status" placeholder="状态"
style="margin-left: 8px;width: 150px;">
<el-option label="正常" value="1" />
<el-option label="关闭" value="0" />
</el-select>
</el-form-item>
<el-button @click="GetList()" style="margin-left: 10px;">搜索</el-button> -->
<el-button type="primary" @click="Add()" style="margin-left: 10px;">添加</el-button>
<el-button type="danger" @click="Del()" style="margin-left: 10px;">删除</el-button>
<el-button type="success" @click="CreatedPlanClick()" style="margin-left: 20px;">生成选中的计划</el-button>
</el-row>
</div>
<el-row>
<el-radio-group style="margin-bottom: 8px;" v-model="searchInfo.date_type" @change="DateTypeChange()">
<el-radio-button :label="1">工作日</el-radio-button>
<el-radio-button :label="2">节假日</el-radio-button>
</el-radio-group>
<el-radio-group style="margin-bottom: 8px;margin-left: 20px;" text-color="#fff" fill="#62bf68" size="small" v-if="activeZhenShi.time_mode==1 && searchInfo.date_type==1" v-model="searchInfo.type" @change="TypeChange()">
<el-radio-button :label="1">夏令时</el-radio-button>
<el-radio-button :label="2">冬令时</el-radio-button>
</el-radio-group>
</el-row>
<div style="display: flex;" class="planInfo" v-if="searchInfo.date_type==1">
<div style=" border-right: 1px solid #dadada;padding-right: 4px;">
<div v-for="(item,index) in zhenShiList" :key="index" @click="zhenshiClick(item.resources_name,item.resources_id)"
:class="{'zhenshiButton zhenshiButtonActive':item.resources_name===activeZhenShi.department_resources_name,'zhenshiButton':item.resources_name !==activeZhenShi.department_resources_name}">
{{item.resources_name}}
</div>
</div>
<div v-loading="loading" style="border: 1px solid #efefef;width: 100%;">
<table class="planTable" v-if="planTableData.length>0" >
<tr style="background-color: #f1f1f1;position: relative;">
<td style="width: 120px;display: flex;font-size: 12px;">
<div style="margin-left: 30px;margin-right: 6px;">全选</div>
<div :class="{'plan_checkAllbox plan_checkAllbox_active':PlanSelectedAll===1,'plan_checkAllbox ':PlanSelectedAll===0}"
@click="selectedAllPlanFunc()">
<el-icon v-if="PlanSelectedAll===1" color="#ffffff"><Select /></el-icon>
</div>
</td>
<td style="font-weight: 700;" v-for="(item,index) in xingqi">{{item.label}}</td>
</tr>
<tr v-for="(item,index) in planTableData" :key="index">
<td v-for="(item2,index2) in item" :key="index2" @mouseover="showTools(item2.id)"
@mouseleave="hideTools(item2.id)">
<span v-if="index2=='time_range'">{{item2}}</span>
<div v-if="item2.countsInfo && item2.countsInfo.length>0" :class="{'planInfo_k':item2.status==1,'planInfo_k planInfo_k_disabled':item2.status==0}">
<div v-if="hoverIndex==item2.id" class="hoverTools">
<div class="icon_k" @click="Add(item2)">
<el-icon color="#409eff" size="20">
<Edit />
</el-icon>
</div>
<div class="icon_k" @click="OpenZhanWeiDialog(item2)">
<el-icon color="#409eff" size="20">
<Lock />
</el-icon>
</div>
</div>
<div :class="{'plan_checkbox plan_checkbox_active':isSelected(item2.id),'plan_checkbox':!isSelected(item2.id)}"
@click="checkBoxCheckFunc(item2.id)">
<el-icon v-if="isSelected(item2.id)" color="#ffffff"><Select /></el-icon>
</div>
<div class="qudao_count_row">
<div class="qudao_title_zong"><span>总</span>{{item2.countsInfo[0].max_total}}
</div>
<div v-for="(item3,index3) in item2.countsInfo" :key="index3">
<span> {{item3.jiancheng}}</span><span>{{item3.count}} </span>
</div>
</div>
<div class="patient_type_row">
<div class="tps" v-for="(item3,index3) in item2.patient_type_label">
{{item3}}
</div>
</div>
<div v-if="getTotalLocked(item2.countsInfo) > 0" class="locked_count_row">
占:{{getTotalLocked(item2.countsInfo)}}
</div>
</div>
</td>
</tr>
</table>
<div v-if="planTableData.length==0" style="width: 100%;background-color: #fff;">
<el-empty description="暂无" />
</div>
</div>
</div>
<el-table v-if="searchInfo.date_type==2" :data="tableData" border style="width: 100%;" row-key="id"
v-loading="loading" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column prop="id" label="Id" width="70" />
<el-table-column prop="weekname" label="星期" width="80" v-if="searchInfo.date_type==1"/>
<el-table-column prop="resources_id" label="" v-if="false" />
<el-table-column prop="department_resources_name" label="资源" width="150" />
<el-table-column prop="" label="服务组" show-overflow-tooltip width="150">
<template #default="scope">
<div class="type_count" v-if="scope.row.devices.length>0">
<div v-for="(item,index) in scope.row.devices" :key="index"
:class="(item.status==1 && item.is_del==0) ? '':'hongzi'">{{ item.device_name }}</div>
</div>
</template>
</el-table-column>
<el-table-column prop="period_name" label="时段" width="100" />
<el-table-column prop="begin_time" label="开始时间" width="100" />
<el-table-column prop="end_time" label="结束时间" width="100" />
<el-table-column prop="" label="类型数量" show-overflow-tooltip>
<template #default="scope">
<div class="type_count" v-if="scope.row.countsInfo.length>0">
<div style="font-weight: 700">最大数量:{{ scope.row.countsInfo[0].max_total }}</div>
<div v-for="(item,index) in scope.row.countsInfo" :key="index">{{ item.name }}:{{ item.count
}}
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="end_reservation_time" label="预约截止时间" width="120" />
<!-- <el-table-column prop="time_unit" label="可用时长" width="80" /> -->
<el-table-column prop="roster_status" label="状态" width="80">
<template #default="scope">
<el-tag v-if="scope.row.status === 1" class="ml-2" type="success">正常</el-tag>
<el-tag v-if="scope.row.status === 0" class="ml-2" type="danger">关闭</el-tag>
</template>
</el-table-column>
<el-table-column prop="" label="操作" width="80">
<template #default="scope">
<el-button type="primary" @click="Add(scope.row)" size="small" style="margin-left: 10px;">修改
</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog v-model="dialogVisible" :title="'时间段('+date_type_name+')'" width="45%">
<el-form ref="PlanInfoForm" :model="PlanInfo" label-width="100px" v-loading="loading"
style="padding-right: 40px;">
<el-form-item label="星期:" prop="xingqi" v-if="searchInfo.date_type==1">
<el-checkbox :disabled="PlanInfo.id==0?false:true" style="margin-right: 8px;" v-model="CheckedAll"
@change="CheckedAllFunc" label="全选"><span style="font-weight: 700;color: #409eff;">全选</span>
</el-checkbox>
<el-checkbox-group v-model="PlanInfo.xingqi">
<el-checkbox :disabled="PlanInfo.id==0?false:true" v-for="(item, index) in xingqi" :key="index"
:label="item.label">{{ item.label }}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="渠道名额:">
<div style="margin-right: 26px">
<div>
<el-radio-group v-model="CountType" @change="CountTypeChange">
<el-radio label="1">根据总量</el-radio>
<el-radio style="margin-left: -10px;" label="2">根据时长(分钟)</el-radio>
</el-radio-group>
</div>
<div class="qudao_k_input">
<el-input v-if="CountType==1" style="width: 220px;" @input="MaxCountChange" type="number"
v-model="PlanInfo.max_total" :min="1" placeholder="0"
oninput="value=value.replace(/^0|[^0-9]/g, '')" />
<el-input v-if="CountType==2" style="width: 220px;" @input="TimeLongChange" type="number"
v-model="PlanInfo.time_long" :min="1" placeholder="0"
oninput="value=value.replace(/^0|[^0-9]/g, '')" />
</div>
<div style="font-size: 12px;color: #999">设置渠道比例可自动分配</div>
</div>
<div>
<div class="qudao_k" v-for="(item,index) in PlanInfo.qudao_total" :key="index">
<div style="width: 50px">{{ item.name }}</div>
<div class="qudao_k_input" style="display: flex;">
<el-input type="number" v-model="PlanInfo.qudao_total[index].count" :min="1"
placeholder="0" oninput="value=value.replace(/^0|[^0-9]/g, '')" />
<div style="margin-left: 4px; color: #ccc;">{{item.ratio}}%</div>
</div>
</div>
</div>
</el-form-item>
<el-form-item label="时间设置:">
<div>选择时段:
<el-select :filterable="true" clearable v-model="PlanInfo.period_id" @change="timePeriodChange"
placeholder="选择时段" style="width: 200px;margin-left: 8px;margin-bottom: 4px">
<el-option v-for="(item,index) in TimePeriodList" :key="index" :label="item.period_name"
:value="item.id" />
</el-select>
<div style="display:flex;">
<div>
<div style="display:flex;">
<div style="width: 70px">开始时间:</div>
<div class="qudao_k_input">
<el-input v-model="PlanInfo.begin_time" placeholder="开始时间" />
</div>
</div>
<div style="display:flex;">
<div style="width: 70px">结束时间:</div>
<div class="qudao_k_input">
<el-input v-model="PlanInfo.end_time" placeholder="结束时间" />
</div>
</div>
</div>
<div style="margin-left: 8px">
<div style="display:flex;">
<div style="width: 90px">停止预约时间:</div>
<div class="qudao_k_input">
<el-input v-model="PlanInfo.end_reservation_time" placeholder="停止预约时间" />
</div>
</div>
<div style="display:flex;">
<div style="width: 90px">可用时间长度:</div>
<div class="qudao_k_input">
<el-input v-model="PlanInfo.time_unit" placeholder="可用时间长度" />
</div>
</div>
</div>
</div>
</div>
</el-form-item>
<el-form-item label="资源:">
<el-select :filterable="true" clearable v-model="PlanInfo.resources_id" @change="resourceChange"
placeholder="选择资源" style="width: 200px;margin-left: 8px;margin-bottom: 4px">
<el-option v-for="(item,index) in enableResourceList" :key="index"
:label="item.department_resources_name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="时令:" v-if="selectedResourceTimeMode === 1 && searchInfo.date_type === 1">
<el-radio-group v-model="PlanInfo.type">
<el-radio :label="1">
<span style="color: #E6A23C;">夏令时</span>
</el-radio>
<el-radio :label="2">
<span style="color: #409EFF;">冬令时</span>
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="服务组:" v-if="devicesList.length>0">
<div v-if="devicesList.length>1" style="width: 100%;font-size: 12px;color: #999;">
此诊室包含多台设备,如同时勾选多个,被勾选设备将共同占用分配的名额。如需为设备单独分配名额,请单独勾选(推荐)</div>
<el-checkbox-group v-model="PlanInfo.devices">
<el-checkbox v-for="(item,index) in devicesList" :key="index"
:label="item.id">{{ item.device_name }}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="病人类型:">
<el-checkbox-group v-model="PlanInfo.patientType">
<el-checkbox label="0">住院</el-checkbox>
<el-checkbox label="1">门诊</el-checkbox>
<el-checkbox label="2">急诊</el-checkbox>
<el-checkbox label="3">体检</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="状态:">
<el-switch v-model="PlanInfo.status" size="large" active-text="正常" inactive-text="关闭"
:active-value="1" :inactive-value="0" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="Save">
确定
</el-button>
</span>
</template>
</el-dialog>
<!-- 生成时选择时间段-->
<el-dialog v-model="CreatePlanDialogVisible" title="生成计划" width="50%">
<el-form label-width="100px" v-loading="loading" style="padding-right: 40px;">
<el-form-item label="选择时间范围:">
<el-date-picker v-model="dateRange" type="daterange" range-separator="To" start-placeholder="开始时间"
end-placeholder="结束时间" value-format="YYYY-MM-DD" />
</el-form-item>
<el-form-item label="节假日生成:">
<el-switch v-model="HolidayEnable" size="large" active-text="是" inactive-text="否" :active-value="1"
:inactive-value="0" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="CreatePlanDialogVisible = false">取消</el-button>
<el-button type="primary" @click="CreatedPlanAction">
确定
</el-button>
</span>
</template>
</el-dialog>
<el-dialog v-model="ZhanWeiDialogVisible" title="占位设置" width="40%">
<div v-loading="loading">
<el-form v-if="ZhanWeiInfo" label-width="120px" style="padding-right: 40px;">
<el-form-item label="模板ID:">
{{ ZhanWeiInfo.id }}
</el-form-item>
<el-form-item label="资源:">
{{ ZhanWeiInfo.resources_name }}
</el-form-item>
<el-form-item label="时间段:">
{{ ZhanWeiInfo.begin_time ? ZhanWeiInfo.begin_time.substring(0,5) : '' }} - {{ ZhanWeiInfo.end_time ? ZhanWeiInfo.end_time.substring(0,5) : '' }}
</el-form-item>
<el-form-item label="星期:">
{{ ZhanWeiInfo.weekname }}
</el-form-item>
<el-form-item label="渠道占位:">
<div style="display: flex; flex-direction: column; gap: 10px; width: 100%;">
<template v-if="ZhanWeiInfo.qudao_total && ZhanWeiInfo.qudao_total.length > 0">
<template v-for="(item,index) in ZhanWeiInfo.qudao_total" :key="index">
<div v-if="item && !(item.count===0)"
style="display: flex; align-items: center; gap: 10px;">
<div style="width: 80px;">{{ item.name }}</div>
<div style="flex: 1;">
<el-input type="number" v-model="ZhanWeiInfo.qudao_total[index].locked_count" placeholder="占位数量" min="0"
oninput="value=value.replace(/[^0-9]/g,'')" />
</div>
<div style="color: #999; font-size: 12px;">
可用: {{ item.count }}
</div>
</div>
</template>
</template>
<div v-else style="color: #999;">
暂无渠道数据
</div>
</div>
</el-form-item>
</el-form>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="ZhanWeiDialogVisible = false">取消</el-button>
<el-button type="primary" @click="SaveZhanWeiAction">
</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup>
import {
ref,
onMounted
} from 'vue'
import {
PlanModelSave,
PlanModelGetList,
GetEnableDepartmentList,
GetAppointmentRatio,
TimePeriodGetEnableList,
TimePeriodGetDetail,
DepartmentResourceGetEnableList,
ResourceGetBindDeviceList,
GetPlanModelDetailInfo,
PlanModelDel,
GetEnableDeviceList,
CreatePlanList,
GetServiceDateTime,
SavePlanModelLockedCount
} from '@/api/api.js'
import {
ElMessage,
ElMessageBox
} from 'element-plus'
let CountType = ref("1"); //渠道数量设置方式
let loading = ref(false)
let currentPage = ref(1) //当前页码
let pageSize = ref(15) //每页数量
let total = 0 //总数量
let zhenShiList = ref([])
let activeZhenShi = ref({});
let planTableData = ref([])
let selectedPlanArr = ref([]) //选中的号源id数组
let PlanSelectedAll = ref(0)
let tableData=ref([]);
const PageSizeChange = (e) => { // 修改每页数量
pageSize.value = e
GetList()
}
const PageCurrentChange = (e) => { //切换页码
currentPage.value = e
GetList()
}
let dateRange = ref([]) //生成计划明细时,选择的日期范围
let CreatePlanDialogVisible = ref(false)
//占位功能
let ZhanWeiDialogVisible = ref(false)
let ZhanWeiInfo = ref(null)
const CreatedPlanClick = () => { //点击生成计划明细按钮
if (selectedPlanArr.value.length === 0) {
ElMessage.error("请至少勾选1条记录")
return false
}
CreatePlanDialogVisible.value = true;
}
const zhenshiClick = (zhenshi,resources_id) => {
searchInfo.value.type=0
enableResourceList.value.forEach((v,i)=>{
if(v.id===resources_id){
activeZhenShi.value =v
if(v.time_mode==1){
searchInfo.value.type=1
}
}
})
PlanSelectedAll.value = 0
selectedPlanArr.value = []
searchInfo.value.resources_id=resources_id
GetList()
}
const selectedAllPlanFunc = () => {
PlanSelectedAll.value = PlanSelectedAll.value === 0 ? 1 : 0;
if (PlanSelectedAll.value === 0) {
selectedPlanArr.value = []
}
if (PlanSelectedAll.value === 1) {
planTableData.value.forEach((v, i) => {
console.log(v)
for (let key in v) {
if (key != 'time_range') {
selectedPlanArr.value.push(v[key].id)
}
}
})
}
}
let hoverIndex = ref(null)
const showTools = (index) => {
hoverIndex.value = index
}
const hideTools = (index) => {
hoverIndex.value = null
}
const isSelected = (id) => {
return selectedPlanArr.value.includes(id)
}
const checkBoxCheckFunc = (id) => {
const index = selectedPlanArr.value.indexOf(id);
if (index === -1) {
selectedPlanArr.value.push(id);
} else {
selectedPlanArr.value = selectedPlanArr.value.filter(item => item !== id);
}
};
const CreatedPlanAction = () => { //调用生成计划明细接口
if (dateRange.value.length === 0) {
ElMessage.error("请选择日期范围")
return false;
}
CreatePlanList({
dateRange: dateRange.value,
ids: selectedPlanArr.value,
HolidayEnable: HolidayEnable.value,
date_type: searchInfo.value.date_type
}).then(res => {
if (res.status) {
CreatePlanDialogVisible.value = false;
ElMessage({
message: res.msg,
type: 'success',
})
} else {
ElMessageBox.alert(res.msg, '提示', {
// if you want to disable its autofocus
// autofocus: false,
confirmButtonText: '确定',
dangerouslyUseHTMLString: true,
})
}
})
}
let searchInfo = ref({
department_id: null,
resources_id: null,
device_id: null,
xingqi: null,
type: 0, //0默认未开启夏时令 1夏令时 2冬令时
status: null,
})
let HolidayEnable = ref(1)
let date_type_name = ref('工作日')
let dialogVisible = ref(false)
const GetList = () => {
loading.value=true
PlanModelGetList({
page: currentPage.value,
pageSize: pageSize.value,
searchInfo: searchInfo.value
}).then(res => {
loading.value=false
if (res.status) {
planTableData.value = []
selectedPlanArr.value = []
let plans = res.data.list
tableData.value=plans
if (plans.length > 0) {
// if (activeZhenShi.value == '') activeZhenShi.value = plans[0].department_resources_name
const timeSlotsSet = new Set();
//const uniqueMap = new Map();
plans.forEach((v, i) => {
if (v.department_resources_name == activeZhenShi.value.department_resources_name) {
const timeRange =
`${v.begin_time.substring(0,5)}-${v.end_time.substring(0,5)}`;
timeSlotsSet.add(timeRange);
}
const key = v.resources_id; // 按照你要去重的字段
// if (!uniqueMap.has(key)) {
// uniqueMap.set(key, {
// resources_id: v.resources_id,
// resources_name: v.department_resources_name
// });
// }
})
// zhenShiList.value = Array.from(uniqueMap.values());
const timeSlots = Array.from(timeSlotsSet).sort(); // 排序可选
// Step 2: 构建表格数据
timeSlots.forEach(timeRange => {
const row = {
time_range: timeRange
};
xingqi.value.forEach(xingqi => {
const matchingPlan = plans.find(
v =>
`${v.begin_time.substring(0,5)}-${v.end_time.substring(0,5)}` ===
timeRange && v.weekname === xingqi.label && v
.department_resources_name == activeZhenShi.value.department_resources_name
);
let plan_enable = false
if (matchingPlan) {
row[xingqi.label] = {
countsInfo: matchingPlan.countsInfo,
patient_type_label: matchingPlan.patient_type_label,
status: matchingPlan.status,
id: matchingPlan.id,
resources_id:matchingPlan.resources_id
};
}else{
row[xingqi.label] = {
countsInfo: null,
patient_type_label: null,
status: null,
id: null,
resources_id:null
};
}
});
planTableData.value.push(row);
});
}
}
})
}
let xingqi = ref([{
label: '星期一',
value: 1
}, {
label: '星期二',
value: 2
}, {
label: '星期三',
value: 3
}, {
label: '星期四',
value: 4
}, {
label: '星期五',
value: 5
}, {
label: '星期六',
value: 6
}, {
label: '星期日',
value: 7
}])
let PlanInfoForm = ref(null)
const DataDefault = () => {
return {
id: 0,
type: 0, //0默认未开启夏时令 1夏令时 2冬令时
xingqi: [],
max_total: 0,
qudao_total: [],
period_id: null,
begin_time: '',
end_time: '',
end_reservation_time: '',
time_unit: 0, //可用时长
resources_id: null,
devices: [],
patientType: [],
status: 1
}
}
let PlanInfo = ref(DataDefault())
let selectedResourceTimeMode = ref(0) // 选中的资源时令模式0-未开启时令1-开启时令
const Add = (row = null) => {
devicesList.value = []
CheckedAll.value = false
dialogVisible.value = true
PlanInfo.value = DataDefault()
selectedResourceTimeMode.value = 0 // 重置时令模式
GetRatio()
GetEnableTimePeriod()
if (row) {
PlanInfo.value.resources_id = row.resources_id
resourceChange()
setTimeout(() => {
console.log('编辑')
GetDetailInfo(row.id)
}, 500)
}
}
const DateTypeChange = () => {
if (searchInfo.value.date_type == 1){
date_type_name.value = '工作日'
if(zhenShiList.value.length>0){
zhenshiClick(zhenShiList.value[0].resources_name,zhenShiList.value[0].resources_id)
}
}
if (searchInfo.value.date_type == 2){
date_type_name.value = '节假日'
searchInfo.value.type=0
searchInfo.value.resources_id=null
GetList()
}
}
const TypeChange=()=>{
GetList()
}
const Save = () => {
//判断各个渠道和是否等于总数
let tempCount = 0
PlanInfo.value.qudao_total.forEach((item) => {
tempCount = tempCount + Number(item.count)
})
if (tempCount !== Number(PlanInfo.value.max_total)) {
ElMessage.error('各个渠道数量之和与当日总量不符')
return false
}
ElMessageBox.confirm(
'确定保存吗?',
'提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
loading.value = true
PlanModelSave({
date_type: searchInfo.value.date_type,
planInfo: PlanInfo.value
}).then(res => {
loading.value = false
if (res.status) {
dialogVisible.value = false
GetList()
} else {
ElMessage.error(res.msg)
}
})
})
}
const Del = () => {
if (selectedPlanArr.value.length == 0) {
ElMessage.error("请至少勾选1条记录")
return false
}
ElMessageBox.confirm(
'确定删除吗?',
'提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
).then(() => {
loading.value = true
PlanModelDel({
ids: selectedPlanArr.value
}).then(res => {
loading.value = false
if (res.status) {
ElMessage({
message: res.msg,
type: 'success',
})
GetList()
} else {
ElMessage.error(res.msg)
}
})
})
}
//获取可用服务组
let EnableDeviceList = ref([])
const GetEnableDeviceListFunc = () => {
loading.value = true
GetEnableDeviceList().then(res => {
loading.value = false
if (res.status) {
EnableDeviceList.value = res.data
} else {
ElMessage.error(res.msg)
}
})
}
let EnableDepartmentList = ref([])
const GetDepartmentEnableList = () => {
loading.value = true
GetEnableDepartmentList({}).then(res => {
loading.value = false
if (res.status) {
EnableDepartmentList.value = res.data.list
} else {
ElMessage.error(res.msg)
}
})
}
//获取当前科室各个渠道可预约百分比
const GetRatio = () => {
loading.value = true
GetAppointmentRatio({}).then(res => {
loading.value = false
if (res.status) {
PlanInfo.value.qudao_total = res.data
PlanInfo.value.qudao_total.forEach((v, i) => {
PlanInfo.value.qudao_total[i].count = 0
})
// console.log(PlanInfo.value)
} else {
ElMessage.error(res.msg)
}
})
}
//监听最大值输入
const MaxCountChange = (e) => {
if (e === '' || e == null || e === 0) {
PlanInfo.value.max_total = 0
}
let temp = 0
let qudao_count = PlanInfo.value.qudao_total.length
console.log(PlanInfo.value.qudao_total)
for (let i = 0; i < qudao_count; i++) {
if (PlanInfo.value.qudao_total[i].ratio === 0) continue;
PlanInfo.value.qudao_total[i].count = Math.round(PlanInfo.value.max_total * (PlanInfo.value.qudao_total[i]
.ratio / 100))
temp = temp + PlanInfo.value.qudao_total[i].count
//如果各个渠道的总和与设置的总数不一致最后1项适当加减平衡总数
if (i === qudao_count - 1 && temp !== PlanInfo.value.max_total) {
let bodongzhi = temp - PlanInfo.value.max_total;
// PlanInfo.value.qudao_total[i].count = PlanInfo.value.qudao_total[i].count - (temp - PlanInfo.value.max_total)
// if(PlanInfo.value.qudao_total[i].count<0) {
// PlanInfo.value.qudao_total[i].count=0
// }
PlanInfo.value.qudao_total.sort((a, b) => a.ratio - b.ratio);
// 遍历排序后的数组,找到第一个非零项
let minRatioItem = null;
for (let ii = 0; ii < PlanInfo.value.qudao_total.length; ii++) {
if (PlanInfo.value.qudao_total[ii].count !== 0) {
minRatioItem = PlanInfo.value.qudao_total[ii];
break;
}
}
// 获取最小且非零项在原数组中的位置
let index = PlanInfo.value.qudao_total.indexOf(minRatioItem);
console.log("最小且非零项在原数组中的位置:", index);
console.log(bodongzhi);
if (bodongzhi > 0) {
PlanInfo.value.qudao_total[index].count = PlanInfo.value.qudao_total[index].count - bodongzhi
}
if (bodongzhi < 0 && index > 0) {
PlanInfo.value.qudao_total[index - 1].count = PlanInfo.value.qudao_total[index - 1].count -
bodongzhi
}
if (bodongzhi < 0 && index == 0) {
PlanInfo.value.qudao_total[index].count = PlanInfo.value.qudao_total[index].count - bodongzhi
}
PlanInfo.value.qudao_total.sort((a, b) => b.ratio - a.ratio);
}
}
}
//获取可用的时间段
let TimePeriodList = ref([])
const GetEnableTimePeriod = () => {
loading.value = true
TimePeriodGetEnableList({
date_type: searchInfo.value.date_type
}).then(res => {
loading.value = false
if (res.status) {
TimePeriodList.value = res.data
} else {
ElMessage.error(res.msg)
}
})
}
//选择时间段
const timePeriodChange = () => {
loading.value = true
TimePeriodGetDetail({
id: PlanInfo.value.period_id
}).then(res => {
loading.value = false
if (res.status) {
PlanInfo.value.begin_time = res.data.period_begin_time
PlanInfo.value.end_time = res.data.period_end_time
PlanInfo.value.end_reservation_time = res.data.period_deadline
} else {
ElMessage.error(res.msg)
}
})
}
//获取计划详情
const GetDetailInfo = (id) => {
loading.value = true
GetPlanModelDetailInfo({
id: id
}).then(res => {
loading.value = false
if (res.status) {
PlanInfo.value = res.data
PlanInfo.value.max_total = res.data.qudao_total[0].max_total
PlanInfo.value.xingqi = [res.data.weekname]
PlanInfo.value.devices = res.data.devices
// 更新选中资源的时令模式
const selectedResource = enableResourceList.value.find(r => r.id === PlanInfo.value.resources_id);
selectedResourceTimeMode.value = selectedResource ? (selectedResource.time_mode || 0) : 0;
} else {
ElMessage.error(res.msg)
}
})
}
//获取可用资源列表
let enableResourceList = ref([])
const getEnableResource = () => {
zhenShiList.value=[];
loading.value = true
DepartmentResourceGetEnableList().then(res => {
loading.value = false
if (res.status) {
enableResourceList.value = res.data
enableResourceList.value.forEach((v,i)=>{
zhenShiList.value.push({
resources_id: v.id,
resources_name: v.department_resources_name
})
})
if(activeZhenShi.value.department_resources_name==undefined && zhenShiList.value.length>0){
zhenshiClick(zhenShiList.value[0].resources_name,zhenShiList.value[0].resources_id)
}
} else {
ElMessage.error(res.msg)
}
})
}
//切换资源
let devicesList = ref([])
const resourceChange = () => {
PlanInfo.value.devices = [];
// 更新选中资源的时令模式
const selectedResource = enableResourceList.value.find(r => r.id === PlanInfo.value.resources_id);
selectedResourceTimeMode.value = selectedResource ? (selectedResource.time_mode || 0) : 0;
loading.value = true
ResourceGetBindDeviceList({
resource_id: PlanInfo.value.resources_id
}).then(res => {
loading.value = false
if (res.status) {
devicesList.value = res.data
} else {
ElMessage.error(res.msg)
}
})
}
//获取当月日期范围
const setMonthRange = () => {
GetServiceDateTime().then(res => {
if (res.status) {
let currentdate = res.data.datetime.substring(0, 10)
var date = new Date(currentdate);
// 获取当前月份注意JavaScript中的月份是从0开始计数的
var currentMonth = date.getMonth();
// 计算下个月的月份考虑到12月后应跳转到次年1月
var nextMonthMonth = (currentMonth + 1) % 12;
var nextMonthYear = date.getFullYear() + ((currentMonth + 1) / 12 | 0); // 处理年份的进位
// 获取当前日期的日
var currentDay = date.getDate();
// 创建下个月的同一天日期对象,需检查下月是否有同日,若无则调整至下月最后一天
var nextMonthSameDay = new Date(nextMonthYear, nextMonthMonth, currentDay);
// 检查是否需要调整到下月的最后一天例如3月31日到4月没有31日
if (nextMonthSameDay.getMonth() !== nextMonthMonth) {
// 如果构造的日期月份变了,说明原日超出下月范围,应调整为下月最后一天
nextMonthSameDay = new Date(nextMonthYear, nextMonthMonth, 0);
}
// 返回格式化的日期字符串,可根据需要调整格式
let nextMonth = nextMonthSameDay.toISOString().split('T')[0]; // 默认返回YYYY-MM-DD格式
dateRange.value = [currentdate, nextMonth];
}
})
}
let CheckedAll = ref(false);
//星期全选事件
const CheckedAllFunc = (e) => {
if (e) {
PlanInfo.value.xingqi = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'];
} else {
PlanInfo.value.xingqi = []
}
}
//总量设置方式切换
const CountTypeChange = (e) => {
CountType.value = e
MaxCountChange(0)
TimeLongChange(0)
if (e == 2) {
}
}
const handleSelectionChange = (e) => {
selectedPlanArr.value=[]
e.forEach((v,i)=>{
selectedPlanArr.value.push(v.id)
})
console.log(selectedPlanArr.value)
}
//监听时长输入
const TimeLongChange = (timelong) => {
if (CountType.value == 2) { //如果是根据时长计算总量
if (PlanInfo.value.begin_time == '' || PlanInfo.value.end_time == '') {
ElMessage.error("请先设置时段")
PlanInfo.value.max_total = 0
return false
}
ComPuteCountByTime(timelong)
}
}
//根据时长计算总量
const ComPuteCountByTime = (timelong) => {
let count = calculateTimeSegments(PlanInfo.value.begin_time, PlanInfo.value.end_time, timelong)
PlanInfo.value.max_total = count
MaxCountChange(count)
}
//根据时间段和跨度算出数量
function calculateTimeSegments(startTime, endTime, span) {
// 将时间字符串转换为分钟数
function timeToMinutes(timeStr) {
const [hours, minutes] = timeStr.split(':').map(Number);
return hours * 60 + minutes;
}
const startMinutes = timeToMinutes(startTime);
const endMinutes = timeToMinutes(endTime);
// 计算总的时间差(以分钟为单位)
const totalMinutes = endMinutes - startMinutes;
// 计算可以划分的时间段数量
const segments = Math.floor(totalMinutes / span);
return segments;
}
//计算总占位数量
const getTotalLocked = (countsInfo) => {
if (!countsInfo || !Array.isArray(countsInfo)) return 0
return countsInfo.reduce((total, item) => {
return total + (Number(item.locked_count) || 0)
}, 0)
}
//占位功能 - 打开占位对话框
const OpenZhanWeiDialog = (row) => {
ZhanWeiDialogVisible.value = true
loading.value = true
GetPlanModelDetailInfo({
id: row.id
}).then(res => {
loading.value = false
if (res.status) {
ZhanWeiInfo.value = res.data
// 获取资源的名称
const resource = enableResourceList.value.find(r => r.id === row.resources_id)
ZhanWeiInfo.value.resources_name = resource ? resource.department_resources_name : ''
// 获取时间段
const timeRange = row.time_range || ''
ZhanWeiInfo.value.time_range = timeRange
// 初始化 locked_count
if (ZhanWeiInfo.value.qudao_total) {
ZhanWeiInfo.value.qudao_total.forEach(item => {
if (item.locked_count === null) {
item.locked_count = 0
}
})
}
} else {
ElMessage.error(res.msg)
}
})
}
//保存占位设置
const SaveZhanWeiAction = () => {
let locked_counts = []
let hasError = false
ZhanWeiInfo.value.qudao_total.forEach((item) => {
if (hasError) return
if (Number(item.locked_count) < 0) {
ElMessage.error(`${item.name} 的占位数量不能为负数`)
hasError = true
return
}
// 验证占位数量不能超过可用数量(总数)
if (Number(item.locked_count) > item.count) {
ElMessage.error(`${item.name} 的占位数量不能超过可用数量,最多${item.count}`)
hasError = true
return
}
locked_counts.push({
appointment_type_id: item.appointment_type_id,
locked_count: item.locked_count || 0
})
})
if (hasError) return
loading.value = true
SavePlanModelLockedCount({
roster_id: ZhanWeiInfo.value.id,
locked_counts: locked_counts
}).then(res => {
loading.value = false
if (res.status) {
ZhanWeiDialogVisible.value = false
ElMessage.success('占位设置保存成功')
GetList() // 重新加载列表
} else {
ElMessage.error(res.msg)
}
})
}
onMounted(() => {
searchInfo.value.date_type = 1
GetDepartmentEnableList()
getEnableResource()
GetEnableDeviceListFunc()
setMonthRange()
})
</script>
<style lang="scss" scoped>
.type_count {
display: flex;
}
.type_count div {
white-space: nowrap;
margin-right: 10px;
}
.qudao_k {
display: flex;
}
.qudao_k_input {
width: 150px;
}
.hongzi {
color: #b25252;
}
.planInfo {
.planTable {
width: 100%;
background-color: #fff;
text-align: center;
border: 1px solid #f1f1f1;
border-collapse: collapse;
/* 合并边框 */
color: #333;
td {
border: 1px solid #f1f1f1;
// padding: 6px;
}
}
.table_plan_row td:first-child {
background-color: #f1f1f1;
border-bottom: 1px solid #e8e8e8;
}
.table_plan_row> :not(:first-child):hover {
background-color: #aeebf0;
cursor: pointer;
color: #fff;
}
.planActive {
background-color: #5bc0de;
color: #fff;
}
.plandisable {
pointer-events: none;
opacity: 0.4;
}
.shuxian {
border-left: 1px solid #dfdfdf;
margin-left: 40px;
margin-right: 40px;
}
.do_button {
width: 100px;
}
}
.zhenshiButton {
width: 150px;
border: 1px solid #e8e8e8;
text-align: center;
margin-top: 4px;
border-radius: 4px;
cursor: default;
padding: 6px 6px;
}
.zhenshiButtonActive {
background-color: #5bc0de;
color: #fff;
}
.planInfo_k_disabled{
background-color: #ffd6d2;
}
.planInfo_k {
font-size: 14px;
color: #333;
position: relative;
padding-top: 18px;
padding-bottom: 10px;
.plan_checkbox {
position: absolute;
top: 2px;
left: 2px;
height: 16px;
width: 16px;
border: 1px solid #98c4cc;
border-radius: 4px;
}
.plan_checkbox_active {
background-color: #409eff;
justify-content: center;
align-items: center;
display: flex;
}
.qudao_count_row {
display: flex;
div {
margin-left: 6px;
}
.qudao_title_zong {
font-weight: 700;
span {
font-weight: 700;
}
}
}
.patient_type_row {
display: flex;
margin-top: 4px;
justify-content: center;
.tps {
background-color: #ebfff4;
border: 1px solid #9fdebc;
color: #83b69a;
font-size: 12px;
padding: 1px 2px;
border-radius: 4px;
margin-left: 4px;
}
}
.locked_count_row {
position: absolute;
top: 2px;
right: 4px;
color: #ff9800;
font-size: 12px;
font-weight: bold;
}
.hoverTools {
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
border-radius: 4px;
.icon_k {
height: 30px;
width: 30px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
border: 1px solid #ccc;
background-color: #fff;
}
}
}
.plan_checkAllbox {
height: 20px;
width: 20px;
border: 1px solid #7cccc7;
border-radius: 4px;
}
.plan_checkAllbox_active {
background-color: #409eff;
justify-content: center;
align-items: center;
display: flex;
}
</style>