vue3+ts el-table动态计算合并列(24小时内排班数据构建及页面构建数据案例)成型产品

<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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值