<template>
<div class="dwj_ss_pb_div" style="width: 100%;height: 800px;">
<div style="margin: 0px 10px;height: 50px;line-height: 50px">
<span class="dwj_div_span_font">手术间</span>
<el-select style="width: 200px;margin-left: 10px;"
class="theme-el-select"
popper-class="dwj_el_popper"
v-model="surgeryRoom">
<el-option v-for="item in surgeryRooms"
:key="item.value" :value="item.value" :label="item.label">
</el-option>
</el-select>
<span style="margin-left: 20px"></span>
<span class="dwj_div_span_font" style="margin: 0px 5px">手术暂定日期:</span>
<el-button @click="clickJtDate" class="dwjBtnBorder"
:class="[dq_date_time==jt_date_time?'dwjBtnStyle':'']">
今日 {{jt_date_time}}</el-button>
<el-button @click="clickMtDate" class="dwjBtnBorder"
:class="[dq_date_time==mt_date_time?'dwjBtnStyle':'']">
明日 {{mt_date_time}}</el-button>
<span style="margin-left: 20px"></span>
<el-date-picker type="date"
v-model="qt_date_time"
@change="changeQtDateByDwj"
class="theme-time-picker"
style="width: 160px"
:class="[qt_date_time!=null?'dwjOtherTime':'']"
placeholder="其他日期">
</el-date-picker>
<span v-if="true" class="dwj_div_span_font">
<span style="margin-left: 10px">当前选择的时间:{{dq_date_time}}</span>
</span>
</div>
<div class="dwj_div_tb_pb">
<el-table ref="multipleTable"
class="theme-el-table"
:data="tableData"
:height="500" border
:row-style="{height: '150px'}"
:cell-style="tableCellStyle"
:span-method="arraySpanMethod"
@cell-dblclick="dblclickTbCell"
:row-class-name="tableRowClassName"
highlight-current-row>
<el-table-column label="手术间" prop="itemName" width="100" align="center"/>
<el-table-column v-for="itemCol in tbSetColList"
:key="itemCol.value"
:index="itemCol.value"
:property="itemCol.value"
:label="itemCol.value"
show-overflow-tooltip
width="70" align="center">
<template v-slot="scope">
<span v-if="getDivBoxInfo(scope.row,itemCol.value)!='noInfo'">
<div class="dwj_time_bc_div">
<span v-if="false">{{itemCol.value}}</span>
<div v-for="(item,key) in [getDivBoxInfo(scope.row,itemCol.value)]">
<div class="div-inline dwj_box_lefts" style="">
<div style="height: 28px;">{{item.ssxh+1}}</div>
<div style="height: 28px;cursor: pointer;"
@click="addSurgeryTime(scope.row,item)"
@mouseleave="mouseLeaveAddBtn(scope.row,item)">
<el-tag class="dwj_add_del_btn" style="">+</el-tag>
</div>
<div style="height: 26px;cursor: pointer;"
@click="delSurgeryTime(scope.row,item)"
@mouseleave="mouseLeaveDelBtn(scope.row,item)">
<el-tag class="dwj_add_del_btn" style="">-</el-tag>
</div>
</div>
<div class="div-inline dwj_box_right">
<span v-if="item.hzxm!=null&&item.hzxm!=''">
<div class="dwj_box_row">
{{item.hzxm}},{{item.sex}},{{item.nl}}{{item.nldw}}
</div>
<div class="dwj_box_row">{{item.ksmc}},{{item.zdmc}}</div>
<div class="dwj_box_row">{{item.ydrq}}</div>
<div class="dwj_box_row">
{{item.mzys}}
<span v-if="!(item.mzys==null||item.kdys==null)">,</span>
{{item.kdys}}
</div>
</span>
</div>
</div>
</div>
</span>
<span v-else>
<div class="dwj_time_yd_div">
<span v-if="true">{{itemCol.value}}</span>
</div>
</span>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script lang="ts">
import { useStore } from 'vuex';
import { useRoute,useRouter} from 'vue-router';
import { warnMsg } from '@/utils/msgBox'
import { parseTimeTwo,parseTimeThrid,parseTimeOper } from '@/utils'
import { toRefs,reactive,onMounted,onBeforeMount,getCurrentInstance } from 'vue';
export default {
setup(props,content) {
const {proxy} = getCurrentInstance() as any;
const route = useRoute()
const state:any = reactive({
tableData: [
{
itemeCode: '01',
itemName: '第一手术间',
surgeryList: [],
},
{
itemeCode: '02',
itemName: '第二手术间',
surgeryList: [],
},
],
tbSetColList: [
{value:'00:00',},
{value:'01:00',},
{value:'02:00',},
{value:'03:00',},
{value:'04:00',},
{value:'05:00',},
{value:'06:00',},
{value:'07:00',},
{value:'08:00',},
{value:'09:00',},
{value:'10:00',},
{value:'11:00',},
{value:'12:00',},
],
tbSetColList2: [
{value:'00:00',},
{value:'00:30',},
{value:'01:00',},
{value:'01:30',},
{value:'02:00',},
{value:'02:30',},
{value:'03:00',},
{value:'03:30',},
{value:'04:00',},
{value:'04:30',},
{value:'05:00',},
{value:'05:30',},
{value:'06:00',},
{value:'06:30',},
{value:'07:00',},
{value:'07:30',},
{value:'08:00',},
{value:'08:30',},
{value:'09:00',},
{value:'09:30',},
{value:'10:00',},
{value:'10:30',},
{value:'11:00',},
{value:'11:30',},
{value:'12:00',},
],
SS_TIME_DIFF: 60,
surgeryRoom: null,
surgeryRooms: [],
oneNewSurgery: {},
dq_date_time: null,
jt_date_time: null,
mt_date_time: null,
qt_date_time: null,
})
const router = useRouter()
// 全局登录者信息user
const user = useStore().getters.user;
onBeforeMount(() => {
});
// 页面加载时
onMounted(() => {
let today = new Date()
// 今天jt_date_time-明天mt_date_time
state.jt_date_time = parseTimeThrid(today)
let nextDate = today.setDate(today.getDate()+1)
state.mt_date_time = parseTimeThrid(nextDate)
// 默认今天为当前排班时间
state.dq_date_time = state.jt_date_time
// 根据参数设置动态列表表头
methods.getTimeArray(state.SS_TIME_DIFF)
let params1 = {
value: '1', label: '第一手术间'
}
let params2 = {
value: '1', label: '第二手术间'
}
state.surgeryRooms.push(params1)
state.surgeryRooms.push(params2)
// 是否显示测试数据
let dwj_test = '1'
if(dwj_test == '1'){
let jt_ymr = state.jt_date_time
state.tableData[0].surgeryList = [
{
ssxh: 0,
kssj: jt_ymr+' '+'00:00',
jssj: jt_ymr+' '+'02:00',
hzxm: '孙富贵',
sex: '男',
nl: '62',
nldw: '岁',
ksmc: '骨科',
zdmc: '(鼻-)屁股疼',
ydrq: jt_ymr+' '+'00:00',
mzys: '大美丽(0123)',
kdys: '小索斯(0139)',
},
{
ssxh: 1,
kssj: jt_ymr+' '+'03:00',
jssj: jt_ymr+' '+'05:00',
}
]
state.tableData[1].surgeryList = [
{
ssxh: 0,
kssj: jt_ymr+' '+'01:00',
jssj: jt_ymr+' '+'05:00',
hzxm: 'dingwangjun',
sex: '男人',
nl: '28',
nldw: '岁',
ksmc: '骨科',
zdmc: '鼻炎、打喷嚏',
ydrq: jt_ymr+' '+'12:00',
mzys: '张大磊(0000)',
kdys: '张小斌(0230)',
},
{
ssxh: 1,
kssj: jt_ymr+' '+'06:00',
jssj: jt_ymr+' '+'08:00',
},
{
ssxh: 2,
kssj: jt_ymr+' '+'09:00',
jssj: jt_ymr+' '+'12:00',
},
]
}
});
const methods = {
parseTimeTwo,
parseTimeThrid,
parseTimeOper,
tableRowClassName({row, rowIndex}){
row.index = rowIndex
},
getDivBoxInfo(row,value){
let hasInfo = row.surgeryList.find(
p=>parseTimeOper(p.kssj)==value)
if(hasInfo!=undefined){
return hasInfo
}else {
return 'noInfo'
}
},
getTimeArray(step) {
// step:以分钟为步调
// 比如:15分30分60分
/**Mr.丁计算排班动态列*/
let timeArray :any= [];
for(let h = 0; h <= 24; h++){
for(let m = 0; m < 60; m += step){
let hour = String(h).padStart(2,'0');
let minute = String(m).padStart(2,'0');
let hourMinute:any = `${hour}:${minute}`
let numberStr = `${hour}.${minute}`
if(parseFloat(numberStr) <= 24){
timeArray.push({ value: hourMinute});
}
}
}
state.tbSetColList = timeArray
return timeArray;
},
clickJtDate(){
state.qt_date_time = null
state.dq_date_time = state.jt_date_time
},
clickMtDate(){
state.qt_date_time = null
state.dq_date_time = state.mt_date_time
},
changeQtDateByDwj(){
let qt_date = state.qt_date_time
if(![null,''].includes(qt_date)){
let qt_date_time = parseTimeThrid(qt_date)
state.dq_date_time = qt_date_time
}else {
// 其他选择时间为空就默认今天
methods.clickJtDate()
}
},
computeColDiffByDwj(row,i){
/**Mr.丁dingwangjun原创动态计算跨列数*/
// 中间间距60分钟|30分钟|15分钟
/**dwj:根据参数设置差距//设置的时间差*/
let midValue = state.SS_TIME_DIFF
// 获取一个手术计算手术开始时间位置
let hasSurgery = row.surgeryList[i]
if(row.surgeryList[i]!=undefined){
let kssj :any= row.surgeryList[i].kssj
let jssj :any= row.surgeryList[i].jssj
let jsrq = new Date(jssj).getTime()
let ksrq = new Date(kssj).getTime()
// 结束时间-开始时间的时间数,例如90分钟
let timeNo = (jsrq-ksrq)/(3600*1000)
// 列数:需要横跨几列(不同配置不同跨列)
let colNums = timeNo * 60 / midValue
// 开始时间的时:分;例如08:00
let ksValue = kssj.substring(11)
// 获取开始时间列的索引startNo
let list = state.tbSetColList
let startNo = list.findIndex(p=>p.value==ksValue)
return {
colNums: colNums,
startNo: startNo,
}
}else {
return {
colNums: 9999999,
startNo: 9999999,
}
}
},
arraySpanMethod({row,column,rowIndex,columnIndex}){
/**Mr.丁dingwangjun原创动态计算跨列方法*/
// 根据每一个手术间手术计算手术开始时间的位置
let opsList = row.surgeryList
for(let i=0;i<opsList.length;i++){
let dwjObj = methods.computeColDiffByDwj(row,i)
// dwjObj.colNums 列数需要横跨几列
// dwjObj.startNo 获取开始时间列的索引
let startIn = dwjObj.startNo+1
if(columnIndex===startIn){
// 横穿马路跨几列:colNum列
return [1, dwjObj.colNums];
}
let list :any= []
if(dwjObj.colNums>=2){
for(let i=0;i<dwjObj.colNums;i++){
list.push(startIn+i)
}
// 那几列需要合并为一列:list列
if(list.includes(columnIndex)){
return [1, 0];
}
}
}
},
tableCellStyle({row,column,rowIndex,columnIndex}){
//let dwjObj = methods.computeColDiffByDwj(row,0)
},
addSurgeryTime(row,item){
/**
* dingwangjun作者dwj说明:
* 1.根据参数配置的时间差分钟数增加一次结束时间
* 2.判断增加后的结束不能超过下一次手术的开始时间
* 3.需要标识下item有改动增加addUpdateTime='1'标识
**/
debugger
// 当前排班只限制24小时制度 不能大于24点
// 即:结束时间绝对不能大于下一天的01:00点
let dwjDate = new Date(item.kssj)
let nextDate = dwjDate.setDate(dwjDate.getDate()+1)
let next_Nyr = parseTimeThrid(nextDate)
// 限制结束时间例如:'2023-12-12 01:00'
let limitedMaxDate = next_Nyr+' '+'01:00'
// 更新的结束日期不能等于第二天开始日期
if(item.jssj != limitedMaxDate){
// 需要标识下item有改动
//item.kssj = '2023-10-13 03:00'
//item.jssj = '2023-10-13 09:00'
// 根据配置的时间差分钟数增加一次时间
let midValue = state.SS_TIME_DIFF
let jsrqTime = new Date(item.jssj)
let getMinutes = jsrqTime.getMinutes()
let updateMinutes = getMinutes+Number(midValue)
jsrqTime.setMinutes(updateMinutes)
let updatejsrq = jsrqTime
let updatejssj = parseTimeTwo(updatejsrq)
// 赋值结束时间前验证不能超过下一个手术的开始时间
// 更加当前项目的索引找下一个项目
let opsList = row.surgeryList
let index = opsList.findIndex(p=>p.kssj==item.kssj)
let hasNextItem = row.surgeryList[index+1]
if(hasNextItem==undefined){
// 没有下一个项目可以增加
item.jssj = parseTimeTwo(updatejssj)
item.addUpdateTime = '1' //增加了一次
}else {
// 有下一个项目需要校验下
// 更新的结束时间不能打印下一个开始时间
let this_jssj = new Date(updatejssj)
let next_kssj = new Date(hasNextItem.kssj)
if(this_jssj.getTime()>next_kssj.getTime()){
warnMsg("此次手术时间不能超过下一台手术时间")
}else {
item.jssj = parseTimeTwo(updatejssj)
item.addUpdateTime = '1' //增加了一次
}
}
console.log('====kssj===='+item.kssj)
console.log('====jssj===='+item.jssj)
}else {
warnMsg("时间"+item.jssj+"超限了(只能在选择的当天时间内)")
}
},
mouseLeaveAddBtn(row,item){
// 验证item有改到就执行
if(item.addUpdateTime=='1'){
warnMsg('鼠标离开加号需要执行入库接口??')
// 更新接口数据后需要清除标志
item.addUpdateTime = '0'
methods.saveOneSurgery(item,'0')
}
},
delSurgeryTime(row,item){
/**
* dingwangjun作者dwj说明:
* 1.根据参数配置的时间差分钟数减少一次结束时间
* 2.判断减少后的结束和剋是时间差不能小于时间差
* 3.需要标识下item有改动增加addUpdateTime='1'标识
**/
debugger
// 根据配置的时间差分钟数减少一次时间
let midValue = state.SS_TIME_DIFF
let jssjTime = new Date(item.jssj).getTime()
let kssjTime = new Date(item.kssj).getTime()
if((jssjTime-kssjTime)/(1000*midValue)==60){
warnMsg("手术时间小于设置的时间差,若要取消手术请右键")
}else {
let jsrqTime = new Date(item.jssj)
let getMinutes = jsrqTime.getMinutes()
let updateMinutes = getMinutes-Number(midValue)
jsrqTime.setMinutes(updateMinutes)
let updatejsrq = jsrqTime
let updatejssj = parseTimeTwo(updatejsrq)
item.jssj = parseTimeTwo(updatejssj)
item.addUpdateTime = '1' //增加了一次
}
},
mouseLeaveDelBtn(row,item){
// 验证item有改到就执行
if(item.addUpdateTime=='1'){
warnMsg('鼠标离开加号需要执行入库接口??')
// 更新接口数据后需要清除标志
item.addUpdateTime = '0'
methods.saveOneSurgery(item,'0')
}
},
getPatientInfo(item){
warnMsg("surgeryArrange.vue::"+item)
// 得到需要排列手术的患者信息
state.oneNewSurgery = item
},
dblclickTbCell(row,column,cell,event){
debugger
if(state.dq_date_time==null){
warnMsg("请先选择需要排班的日期(今天、明天、其他)")
return false
}
if(state.oneNewSurgery.hzxm!=null){
let ssList = row.surgeryList
let colList = state.tbSetColList
let hasIndex = colList.find(p=>p.value==column.label)
if(hasIndex!=undefined){
let sjdCell = hasIndex.value //列时间段
if(Array.isArray(ssList) && ssList.length>0){
let hasSjd = ssList.find(p=>p.kssj.includes(sjdCell))
if(hasSjd==undefined){
methods.addOneCollItem(row,sjdCell)
}else {
alert(column.label+"时间段已有手术,请重新排列手术时间")
}
}else {
// 手术间一台手术没有时就直接增加手术
methods.addOneCollItem(row,sjdCell)
}
}
}
},
addOneCollItem(row,sjdCell){
// 入参说明row当前手术间
// 入参说明sjdCell当前列时间段
// 患者手术排班完成需要情况复制的患者
let length = row.surgeryList.length
state.oneNewSurgery.ssxh = length
// 计算开始时间设置
let dq_date = state.dq_date_time
let qt_time_node = dq_date+' '+sjdCell
state.oneNewSurgery.kssj = qt_time_node
// 计算结束时间设置
let midValue = state.SS_TIME_DIFF
let jsrqTime = new Date(qt_time_node)
let getMinutes = jsrqTime.getMinutes()
let updateMinutes = getMinutes+Number(midValue)
jsrqTime.setMinutes(updateMinutes)
let jssj = parseTimeTwo(new Date(jsrqTime))
state.oneNewSurgery.jssj = jssj
// 增加一次排班并清空当前复制的患者
row.surgeryList.push(state.oneNewSurgery)
// 需要走一次保存接口
let item = state.oneNewSurgery
methods.saveOneSurgery(item,'1')
state.oneNewSurgery = {}
},
saveOneSurgery(item,flag){
setTimeout(() => {
if(flag=='0'){
warnMsg("需要保存一次手术")
}
if(flag=='1'){
warnMsg("需要保存一次手术并移除左侧患者")
}
}, 100)
},
};
return {
...toRefs(state),
...methods,
};
}
}
</script>
<style lang="scss">
.dwj_ss_pb_div{
/*table中单元格内边距-调整到靠近边框*/
.el-table .cell, .el-table th div, .el-table--border .cell {
padding-left: 1px;
padding-right: 1px;
}
/*禁掉一切封装的或其他自定义的样式*/
.el-table__body tr:hover>td{
background-color: #FFFFFF !important;
}
.el-table__body tr.current-row>td {
background-color: #FFFFFF !important;
}
}
.dwj_time_bc_div{
width: 100%;
height: 145px;
border-radius: 5px;
cursor: pointer;
border: 1px solid #4884F0;
}
.dwj_time_bc_div:hover{
cursor: pointer;
background: #dee4fe;
}
.dwj_time_yd_div{
width: 100%;
height: 145px;
cursor: pointer;
}
.dwj_time_yd_div:hover{
cursor: pointer;
background: #F4E6FF;
}
.dwj_box_lefts{
width: 20px;
height: 145px;
line-height: 145px;
border-right: 1px solid #f2f2f2;
//background: #ffd591;
}
.dwj_box_right{
width: calc(100% - 20px);
height: 145px;
text-align: left;
margin-left: 5px;
padding-top: 8px;
padding-bottom: 5px;
//background: #2D5AFA;
}
.dwj_box_row{
height: 30px;
line-height: 30px;
}
.dwj_add_del_btn{
width: 15px;
height: 24px;
cursor: pointer;
}
.dwj_add_del_btn:hover{
font-weight: bold;
color: #2D5AFA;
cursor: pointer;
}
.dwj_div_span_font{
color: #666666;
font-size: 14px;
font-weight: bold;
}
.dwjBtnStyle{
font-weight: bold;
border: 1px solid #4884F0;
}
.dwjBtnBorder:hover{
color: #666666;
border: 1px solid #4884F0;
}
.dwjBtnBorder:focus{
color: #4884F0;
font-weight: bold;
background: #FFFFFF;
border: 1px solid #4884F0;
}
.dwjOtherTime{
.el-input__inner {
color: #4884F0;
font-weight: bold;
border:1px solid #4884F0;
}
}
</style>