VUE2中做一个类似于jQuery拖动时间轴的组件

发布于:2023-01-12 ⋅ 阅读:(608) ⋅ 点赞:(0)

VUE2中做一个类似于jQuery拖动时间轴的组件

jQuery拖动时间轴的演示地址

https://www.jq22.com/yanshi20974

此处是我已经实现了的全部功能,诸君直接可以用,但是会有一个非常严重的性能问题要和诸君提前说一下。
在JQ的演示中不管创建多少个滑块浏览器都不会掉帧,滑动也非常顺畅,但是在vue项目中当滑块变多后会导致浏览器严重的掉帧问题,CPU占用率也会飙升,初步判断是因为vue是用数据驱动虚拟DOM而我其中是的操作是大量的DOM操作导致的,如果诸君在使用过程中改善了其性能请留言分享,在下感激不尽。
话不多说,上代码。类似$t(“xxx.xxx”)这种国际化的替换成中文即可

vue做的拖拽时间轴组件

<template>
    <div class="time" onselectstart="return false">
        <div v-loading="btnLoading">
            <div class="title-box">
                <span>类型</span>
                <el-select
                    v-model="typeVal"
                    @change="onSelect"
                    placeholder="请选择存储计划周期类型"
                    size="small"
                    class="w200 title"
                >
                    <el-option
                        v-for="dict in dict.type.sys_cycle_type"
                        :key="dict.value"
                        :label="dict.label"
                        :value="parseInt(dict.value)"
                    />
                </el-select>

                <el-button
                    slot="reference"
                    class="title"
                    type="text"
                    icon="el-icon-delete"
                    @click="deleteAllFun"
                    >删除所有</el-button
                >
            </div>

            <div class="df">
                <div>
                    <!-- 整个时间功能 -->
                    <div
                        class="cycle-box"
                        v-for="week of weekList"
                        :key="week.code"
                        @mouseenter="copyMouseenter(week.title)"
                    >
                        <!-- 周几 -->
                        <span class="week">{{ week.title }}</span>

                        <div class="slide-list">
                            <!-- 时间刻度 -->
                            <div class="slide-ruler">
                                <div
                                    class="scale"
                                    v-for="time of timeList"
                                    :key="time"
                                >
                                    {{ time }}
                                </div>
                            </div>

                            <!-- 时间功能数组中控制周几是否能创建数据disabled -->
                            <div
                                :style="
                                    week.disabled
                                        ? 'background:#C0C8D9;cursor:not-allowed;'
                                        : ''
                                "
                                class="slide-box"
                                @mousedown.stop="
                                    fatherMousedown($event, week.code, week)
                                "
                            >
                                <!-- 初始化的domObj,宽度不等于0并且week.code == code才显示 -->
                                <div
                                    v-show="
                                        domObj.width != 0 && week.code == code
                                    "
                                    class="item"
                                    :style="`width: ${domObj.width}px; left: ${domObj.left}px; background: ${domObj.bg}`"
                                ></div>

                                <!-- 创建的时间块数组domArr -->
                                <div
                                    v-for="(item, key) of week.domArr"
                                    :key="key"
                                    class="item"
                                    :style="`width: ${item.width}px; left: ${item.left}px; background: ${item.bg}`"
                                    @mousedown.stop="
                                        itemMousedown(
                                            $event,
                                            key,
                                            item,
                                            week.domArr
                                        )
                                    "
                                    @click="timeBlock(week.code, key, item)"
                                >
                                    <i
                                        v-show="
                                            item.changeTimeShow && iShow === key
                                        "
                                        class="i-left-class i-class"
                                        @mousedown.stop="
                                            checkI(
                                                'left',
                                                $event,
                                                code,
                                                key,
                                                item,
                                                week.domArr
                                            )
                                        "
                                    ></i>
                                    <i
                                        v-show="
                                            item.changeTimeShow && iShow === key
                                        "
                                        class="i-right-class i-class"
                                        @mousedown.stop="
                                            checkI(
                                                'right',
                                                $event,
                                                code,
                                                key,
                                                item,
                                                week.domArr
                                            )
                                        "
                                    ></i>
                                    <!-- hover时间展示 -->
                                    <div
                                        style="
                                            position: absolute;
                                            top: 0;
                                            left: 0;
                                            width: 100%;
                                            height: 100%;
                                        "
                                        v-show="
                                            blockShow && !item.changeTimeShow
                                        "
                                    >
                                        <el-tooltip placement="top">
                                            <div
                                                style="text-align: center"
                                                slot="content"
                                            >
                                                {{ item.startH }}:{{
                                                    item.startM
                                                }}
                                                - {{ item.endH }}:{{
                                                    item.endM
                                                }}
                                            </div>
                                            <div class="timeHover"></div>
                                        </el-tooltip>
                                    </div>

                                    <!-- 点击时间调整 -->
                                    <el-popover
                                        placement="top"
                                        trigger="manual"
                                        v-model="item.changeTimeShow"
                                        @show="showFun(item)"
                                        @hide="hideFun(item)"
                                    >
                                        <div style="text-align: center">
                                            <div>
                                                <el-select
                                                    v-model="sonVal"
                                                    placeholder="请选择存储计划周期类型"
                                                    size="mini"
                                                    class="w200"
                                                >
                                                    <el-option
                                                        v-for="dict in options"
                                                        :key="dict.value"
                                                        :label="dict.label"
                                                        :value="dict.value"
                                                    />
                                                </el-select>
                                            </div>
                                            <div style="margin: 15px 0">
                                                <input
                                                    size="mini"
                                                    class="w40"
                                                    v-model="item.startH"
                                                    maxlength="2"
                                                    @input="
                                                        hhInput(
                                                            'startH',
                                                            week.code,
                                                            key,
                                                            item
                                                        )
                                                    "
                                                />
                                                <span style="padding: 0 5px"
                                                    >:</span
                                                >
                                                <input
                                                    size="mini"
                                                    class="w40"
                                                    v-model="item.startM"
                                                    maxlength="2"
                                                    @input="
                                                        mmInput(
                                                            'startM',
                                                            week.code,
                                                            key,
                                                            item
                                                        )
                                                    "
                                                />
                                                <span style="padding: 0 5px"
                                                    >-</span
                                                >
                                                <input
                                                    size="mini"
                                                    class="w40"
                                                    v-model="item.endH"
                                                    maxlength="2"
                                                    @input="
                                                        hhInput(
                                                            'endH',
                                                            week.code,
                                                            key,
                                                            item
                                                        )
                                                    "
                                                />
                                                <span style="padding: 0 5px"
                                                    >:</span
                                                >
                                                <input
                                                    size="mini"
                                                    class="w40"
                                                    v-model="item.endM"
                                                    maxlength="2"
                                                    @input="
                                                        mmInput(
                                                            'endM',
                                                            week.code,
                                                            key,
                                                            item
                                                        )
                                                    "
                                                />
                                            </div>
                                            <div>
                                                <el-button-group>
                                                    <el-button
                                                        size="mini"
                                                        type="primary"
                                                        @click="
                                                            btns(
                                                                'delete',
                                                                week.code,
                                                                key,
                                                                item
                                                            )
                                                        "
                                                        >删除</el-button
                                                    >
                                                    <el-button
                                                        size="mini"
                                                        type="primary"
                                                        @click="
                                                            btns(
                                                                'cancel',
                                                                week.code,
                                                                key,
                                                                item
                                                            )
                                                        "
                                                        >取消</el-button
                                                    >
                                                    <el-button
                                                        size="mini"
                                                        type="primary"
                                                        @click="
                                                            btns(
                                                                'ok',
                                                                week.code,
                                                                key,
                                                                item
                                                            )
                                                        "
                                                        >确定</el-button
                                                    >
                                                </el-button-group>
                                            </div>
                                        </div>
                                        <div
                                            slot="reference"
                                            class="timeHover"
                                        ></div>
                                    </el-popover>
                                </div>
                            </div>
                        </div>

                        <!-- 复制相关 -->
                        <div
                            v-show="!week.disabled && week.title == codeHover"
                            class="title"
                        >
                            <el-popover
                                placement="left-end"
                                width="320"
                                v-model="week.copyShow"
                                :open-delay="0"
                                :close-delay="0"
                            >
                                <div>
                                    <div class="df copy-class mb10">
                                        <span>复制到...</span>
                                        <span
                                            ><el-checkbox
                                                :indeterminate="isIndeterminate"
                                                v-model="checkAll"
                                                @change="handleCheckAllChange"
                                                >全选</el-checkbox
                                            ></span
                                        >
                                    </div>

                                    <div style="margin: 15px 0">
                                        <el-checkbox-group
                                            v-model="checkedCities"
                                            @change="handleCheckedCitiesChange"
                                        >
                                            <el-checkbox
                                                :disabled="
                                                    copyValue === city.value
                                                "
                                                class="checkbox-class"
                                                v-for="city in cities"
                                                :label="city.value"
                                                :key="city.value"
                                                >{{ city.title }}</el-checkbox
                                            >
                                        </el-checkbox-group>
                                    </div>

                                    <div>
                                        <el-button
                                            type="text"
                                            size="mini"
                                            @click="copyBtn('cancel', week)"
                                            >取消</el-button
                                        >
                                        <el-button
                                            type="primary"
                                            size="mini"
                                            @click="copyBtn('confirm', week)"
                                            >确定</el-button
                                        >
                                    </div>
                                </div>
                                <i
                                    style="font-size: 16px"
                                    slot="reference"
                                    class="el-icon-document-copy"
                                    @click="copyBtn('icon', week)"
                                ></i>
                            </el-popover>
                        </div>
                    </div>
                </div>

                <div style="margin-left: 20px">
                    <div class="df color-class">
                        <span
                            class="color-bg"
                            style="background: #637dec"
                        ></span>
                        <span>定时</span>
                    </div>
                    <div class="df color-class">
                        <span
                            class="color-bg"
                            style="background: #74b557"
                        ></span>
                        <span>移动侦测</span>
                    </div>
                    <div class="df color-class">
                        <span
                            class="color-bg"
                            style="background: #b83f42"
                        ></span>
                        <span>报警</span>
                    </div>
                    <div class="df color-class">
                        <span
                            class="color-bg"
                            style="background: #e58805"
                        ></span>
                        <span>动测或报警</span>
                    </div>
                    <div class="df color-class">
                        <span
                            class="color-bg"
                            style="background: #b9e2fe"
                        ></span>
                        <span>动测和报警</span>
                    </div>
                    <div class="df color-class">
                        <span
                            class="color-bg"
                            style="background: #aa6ffe"
                        ></span>
                        <span>事件</span>
                    </div>
                </div>
            </div>
        </div>

        <div class="rbtn">
            <el-button @click="returnCancel">{{
                $t("public.dialogCancelText")
            }}</el-button>
            <el-button type="primary" :loading="btnLoading" @click="submit">{{
                $t("public.dialogSubmitText")
            }}</el-button>
        </div>
    </div>
</template>
<script>
// 接口
import {
    listStorageCycle,
    delStorageCycle,
    addStorageCycle,
} from "@/api/storage/storageCycle";
export default {
    name: "Time",
    // 数据字典
    dicts: ["sys_cycle_type"],
    props: {
        // 周几能操作
        dayData: {
            type: Array,
            default() {
                return [1, 2, 3, 4, 5, 6, 7];
            },
        },
        id: {
            type: Number,
            default() {
                return 0;
            },
        },
    },
    data() {
        return {
            btnLoading: false,
            // 删除的id,只有要传[]时才调用
            deleteId: [],

            // 下拉框所有数据
            options: [
                { label: "定时", value: 1 },
                { label: "移动侦测", value: 2 },
                { label: "报警", value: 3 },
                { label: "动测或报警", value: 4 },
                { label: "动测和报警", value: 5 },
                { label: "事件", value: 6 },
            ],
            // 下拉框选中的数据
            typeVal: 1,
            // 删除所有数据
            deleteAll: false,

            // 核心数据
            // 刻度
            timeList: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24],
            // 所有数据
            weekList: [],
            // 声明的DOM对象
            domObj: {},
            // 控制能做几个时间块
            allNum: 8,
            // 所有数据的code值
            code: 0,
            // 所有数据内domArr的下标值
            key: null,
            timeVal: null,
            // 存根数据
            stubData: {},
            // 是否是选中的时间子块
            loop: 0,
            // 子块的hover是否显示
            blockShow: true,
            // 左右i的显示
            iShow: null,
            // 每个子块的下拉框
            sonVal: null,
            // 小弹框显示前的存根数据,防止修改了时间不点击按钮组直接点空取消弹框而导致时间bug问题
            popoverStubData: [],

            // 复制相关
            // 控制是否显示复制
            copyShow: false,
            codeHover: null,
            checkAll: false,
            checkedCities: [],
            cities: [
                { title: "星期一", value: 0 },
                { title: "星期二", value: 1 },
                { title: "星期三", value: 2 },
                { title: "星期四", value: 3 },
                { title: "星期五", value: 4 },
                { title: "星期六", value: 5 },
                { title: "星期七", value: 6 },
            ],
            isIndeterminate: false,
            copyValue: null,
        };
    },
    created() {
        this.init();
    },
    mounted() {
        this.listStorageCycle();
    },
    methods: {
        // 初始化数据
        init() {
            this.domObj = {
                width: 0, //宽度
                left: 0, //左偏移量
                bg: "#637DEC", //背景色(与背景值关联,对应着下拉框的值
                value: 1, //背景值(与背景色关联,对应着下拉框的值
                startH: 0, //开始时间(时
                startM: 0, //开始时间(分
                endH: 0, //结束时间(时
                endM: 0, //结束时间(分
                changeTimeShow: false, //控制时间显示与时间调整
            };
            this.weekList = [
                {
                    title: "星期一",
                    code: 0,
                    copyShow: false,
                    domArr: [],
                    disabled: !this.dayData.includes(1),
                },
                {
                    title: "星期二",
                    code: 1,
                    copyShow: false,
                    domArr: [],
                    disabled: !this.dayData.includes(2),
                },
                {
                    title: "星期三",
                    code: 2,
                    copyShow: false,
                    domArr: [],
                    disabled: !this.dayData.includes(3),
                },
                {
                    title: "星期四",
                    code: 3,
                    copyShow: false,
                    domArr: [],
                    disabled: !this.dayData.includes(4),
                },
                {
                    title: "星期五",
                    code: 4,
                    copyShow: false,
                    domArr: [],
                    disabled: !this.dayData.includes(5),
                },
                {
                    title: "星期六",
                    code: 5,
                    copyShow: false,
                    domArr: [],
                    disabled: !this.dayData.includes(6),
                },
                {
                    title: "星期七",
                    code: 6,
                    copyShow: false,
                    domArr: [],
                    disabled: !this.dayData.includes(7),
                },
            ];
        },
        // 下拉框选择
        onSelect(code) {
            this.domObj = {
                width: 0, //宽度
                left: 0, //左偏移量
                value: code, //背景值(与背景色关联,对应着下拉框的值
                startH: 0, //开始时间(时
                startM: 0, //开始时间(分
                endH: 0, //结束时间(时
                endM: 0, //结束时间(分
                changeTimeShow: false,
            };
            if (code == 1) {
                this.domObj.bg = "#637DEC";
            } else if (code == 2) {
                this.domObj.bg = "#74B557";
            } else if (code == 3) {
                this.domObj.bg = "#B83F42";
            } else if (code == 4) {
                this.domObj.bg = "#E58805";
            } else if (code == 5) {
                this.domObj.bg = "#B9E2FE";
            } else if (code == 6) {
                this.domObj.bg = "#AA6FFE";
            }
        },
        // 删除所有数据
        deleteAllFun() {
            this.deleteAll = false;
            this.init();
        },
        // 拷贝按钮
        copyBtn(type, val) {
            this.checkAll = false;
            if (type === "icon") {
                this.copyValue = val.code;
                this.checkedCities = [];
                this.checkedCities.push(this.copyValue);
            } else if (type === "confirm") {
                if (this.checkedCities.length !== 1) {
                    let arr = JSON.parse(JSON.stringify(val.domArr));
                    arr.forEach((j) => {
                        j.changeTimeShow = false;
                    });
                    this.checkedCities.forEach((i) => {
                        if (i != val.code) {
                            this.weekList[i].domArr = JSON.parse(
                                JSON.stringify(arr)
                            );
                        }
                    });
                }
                val.copyShow = false;
                this.copyValue = null;
                this.checkedCities = [];
            } else if (type === "cancel") {
                val.copyShow = false;
                this.copyValue = null;
                this.checkedCities = [];
            }
        },
        // 进入周几事件后的拷贝功能
        copyMouseenter(title) {
            this.codeHover = title;
        },
        // 复制到...全选
        handleCheckAllChange(val) {
            if (val) {
                this.checkedCities = [0, 1, 2, 3, 4, 5, 6];
            } else {
                this.checkedCities = [];
                this.checkedCities.push(this.copyValue);
            }
            this.isIndeterminate = false;
        },
        handleCheckedCitiesChange(value) {
            let checkedCount = value.length;
            this.checkAll = checkedCount === this.cities.length;
            this.isIndeterminate =
                checkedCount > 0 && checkedCount < this.cities.length;
        },
        // 父节点的按下事件
        fatherMousedown(e, code, item) {
            // 控制是否还能创建
            if (item.domArr.length >= this.allNum || item.disabled) {
                return false;
            }
            this.code = code;
            let op = e.target;
            // 算出鼠标相对元素的位置
            let disX = e.clientX;
            // console.log(e.clientX, op.offsetLeft, "相对位置是他left的值", disX);
            // left
            this.domObj.left = e.layerX;
            // 开始时间
            this.domObj.startH = this.conversionhs("H", this.domObj.left * 2);
            this.domObj.startM = this.conversionhs("M", this.domObj.left * 2);
            //鼠标移动事件
            document.onmousemove = (e) => {
                //用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
                this.domObj.width = e.clientX - disX;
                // 拖动的宽不能大于刻度,否则就等于 刻度-偏移的left = 最终宽
                if (this.domObj.width + this.domObj.left > 720) {
                    this.domObj.width = 720 - this.domObj.left;
                }
                // 结束时间
                this.domObj.endH = this.conversionhs(
                    "H",
                    this.domObj.left * 2 + this.domObj.width * 2
                );
                this.domObj.endM = this.conversionhs(
                    "M",
                    this.domObj.left * 2 + this.domObj.width * 2
                );
            };
            // 鼠标抬起事件
            document.onmouseup = (e) => {
                if (this.domObj.width > 0) {
                    // console.log('width宽度==》》',this.domObj.width,'----left左偏移==》》',this.domObj.left)
                    // console.log(`${this.domObj.startH} : ${this.domObj.startM} - ${this.domObj.endH} : ${this.domObj.endM}`)
                    item.domArr.push(this.domObj);
                }
                this.onSelect(this.typeVal);
                document.onmousemove = null;
                document.onmouseup = null;
            };
        },
        // 子块节点的长按
        itemMousedown(e, key, item, arr) {
            this.loop = setTimeout(() => {
                this.loop = 0;
                let disX = e.clientX;
                let blockLeft = item.left; //左边偏移量left
                let blockWidth = item.width; //子滑块的宽
                // 控制子块长按时的hover显示
                this.blockShow = false;
                item.changeTimeShow = false;
                // console.log('是否显示了按钮组',item.changeTimeShow)
                let arrCopy = JSON.parse(JSON.stringify(arr));
                // 对需要移动的子块的所在数组重新按照left大小排序
                function sortLeft(a, b) {
                    return a.left - b.left;
                }
                arrCopy.sort(sortLeft);
                // 处理左右滑动的范围
                let leftL = 0; // 往左滑动的范围
                let leftR = 720; // 往右滑动的范围
                let mark = 0;
                for (let i = 0; i < arrCopy.length; i++) {
                    if (arrCopy[i].left === item.left) {
                        mark = i;
                        break;
                    }
                }
                if (arrCopy.length === 1) {
                    leftL = 0; // 往左滑动的范围
                    leftR = 720; // 往右滑动的范围
                } else {
                    if (mark === 0) {
                        leftL = 0; // 往左滑动的范围
                        leftR = arrCopy[mark + 1].left; // 往右滑动的范围
                    } else if (mark === arrCopy.length - 1) {
                        leftL =
                            arrCopy[mark - 1].left + arrCopy[mark - 1].width;
                        leftR = 720;
                    } else if (mark !== 0 && mark < arrCopy.length - 1) {
                        leftL =
                            arrCopy[mark - 1].left + arrCopy[mark - 1].width;
                        leftR = arrCopy[mark + 1].left;
                    }
                }
                // console.log('arrCopy==',arrCopy,'==mark=',mark,'=leftL=',leftL,'=leftR=',leftR)
                // 子块鼠标移动事件
                document.onmousemove = (e) => {
                    // console.log(e,'子块滑动事件',e.clientX,'--==--',e.clientX - disX,'---left=',blockLeft + (e.clientX - disX))
                    if (blockLeft + (e.clientX - disX) <= leftL) {
                        item.left = leftL;
                    } else if (
                        item.width + (blockLeft + (e.clientX - disX)) <=
                        leftR
                    ) {
                        // console.log('总长==',item.width + blockLeft + (e.clientX - disX))
                        item.left = blockLeft + (e.clientX - disX);
                    }
                    // 开始时间
                    item.startH = this.conversionhs("H", item.left * 2);
                    item.startM = this.conversionhs("M", item.left * 2);
                    // 结束时间
                    item.endH = this.conversionhs(
                        "H",
                        item.left * 2 + item.width * 2
                    );
                    item.endM = this.conversionhs(
                        "M",
                        item.left * 2 + item.width * 2
                    );
                };
                // 子块鼠标抬起事件
                document.onmouseup = (e) => {
                    this.blockShow = true;
                    this.iShow = null;
                    document.onmousemove = null;
                    document.onmouseup = null;
                };
            }, 200);
            return false;
        },
        // 子块节点的单击
        timeBlock(code, key, item) {
            clearTimeout(this.loop);
            if (this.loop !== 0) {
                this.iShow = key;
                this.sonVal = item.value;
                // console.log('单击=',code, key, JSON.stringify(item) );
                this.stubData = JSON.parse(JSON.stringify(item));
                // 找到对应的节点,根据条件把对应节点打开或者关闭,但是其它节点要全部关闭
                this.weekList.map((v, i) => {
                    v.domArr.map((val, j) => {
                        if (i == code && j == key) {
                            item.changeTimeShow = !item.changeTimeShow;
                        } else {
                            this.weekList[i].domArr[j].changeTimeShow = false;
                        }
                    });
                });
            }
            return false;
        },
        // 选中的左右小方块
        checkI(type, e, code, key, item, arr) {
            this.loop = setTimeout(() => {
                this.loop = 0;
                let disX = e.clientX;
                let blockLeft = item.left; //左边偏移量left
                let blockWidth = item.width; //子滑块的宽
                item.changeTimeShow = false;
                item.value = this.stubData.value;
                // console.log(item,'--->>>>>',this.stubData)
                // console.log('type==>>点击的那个',type, e, key, item, arr)
                let arrCopy = JSON.parse(JSON.stringify(arr));
                // 对需要移动的子块的所在数组重新按照left大小排序
                function sortLeft(a, b) {
                    return a.left - b.left;
                }
                arrCopy.sort(sortLeft);
                // 处理左右滑动的范围
                let leftL = 0; // 往左滑动的范围
                let leftR = 720; // 往右滑动的范围
                let mark = 0;
                for (let i = 0; i < arrCopy.length; i++) {
                    if (arrCopy[i].left === item.left) {
                        mark = i;
                        break;
                    }
                }
                if (arrCopy.length === 1) {
                    leftL = 0; // 往左滑动的范围
                    leftR = 720; // 往右滑动的范围
                } else {
                    if (mark === 0) {
                        leftL = 0; // 往左滑动的范围
                        leftR = arrCopy[mark + 1].left; // 往右滑动的范围
                    } else if (mark === arrCopy.length - 1) {
                        leftL =
                            arrCopy[mark - 1].left + arrCopy[mark - 1].width;
                        leftR = 720;
                    } else if (mark !== 0 && mark < arrCopy.length - 1) {
                        leftL =
                            arrCopy[mark - 1].left + arrCopy[mark - 1].width;
                        leftR = arrCopy[mark + 1].left;
                    }
                }
                // console.log('arrCopy==',arrCopy,'==mark=',mark,'=leftL=',leftL,'=leftR=',leftR)
                // 子块鼠标移动事件
                document.onmousemove = (e) => {
                    // console.log(blockWidth,'子块滑动事件',e.clientX,'--==-运算的-',e.clientX - disX,'---left=',blockLeft + (e.clientX - disX))
                    if (type === "left") {
                        if (blockLeft + (e.clientX - disX) < leftL) {
                            item.left = leftL;
                        } else {
                            if (blockWidth - (e.clientX - disX) >= 0) {
                                item.left = blockLeft + (e.clientX - disX);
                                item.width = blockWidth - (e.clientX - disX);
                            }
                        }
                    } else if (type === "right") {
                        if (
                            blockWidth + (blockLeft + (e.clientX - disX)) <=
                            leftR
                        ) {
                            item.width = blockWidth + (e.clientX - disX);
                        }
                    }
                    // 开始时间
                    item.startH = this.conversionhs("H", item.left * 2);
                    item.startM = this.conversionhs("M", item.left * 2);
                    // 结束时间
                    item.endH = this.conversionhs(
                        "H",
                        item.left * 2 + item.width * 2
                    );
                    item.endM = this.conversionhs(
                        "M",
                        item.left * 2 + item.width * 2
                    );
                };
                // 左右小方块的鼠标抬起事件
                document.onmouseup = (e) => {
                    this.iShow = null;
                    if (item.width <= 0) {
                        this.weekList[code].domArr.splice(key, 1);
                    }
                    document.onmousemove = null;
                    document.onmouseup = null;
                };
            }, 200);
            return false;
        },
        // 分钟 换算 时,分
        conversionhs(type, timeNum) {
            if (type == "H") {
                return parseInt(timeNum / 60) < 10
                    ? "0" + parseInt(timeNum / 60)
                    : parseInt(timeNum / 60);
            } else if (type == "M") {
                return parseInt(timeNum % 60) < 10
                    ? "0" + parseInt(timeNum % 60)
                    : parseInt(timeNum % 60);
            }
        },
        // 时,分 换算成 px
        conversionpx(type, pxNum) {
            if (type == "left") {
                return (
                    (parseInt(pxNum.startH) * 60 + parseInt(pxNum.startM)) / 2
                );
            } else if (type == "width") {
                return (
                    (parseInt(pxNum.endH) * 60 +
                        parseInt(pxNum.endM) -
                        (parseInt(pxNum.startH) * 60 +
                            parseInt(pxNum.startM))) /
                    2
                );
            }
        },
        // 点击时间调整-按钮组
        btns(type, code, key, item) {
            // console.log(type, code, key,JSON.stringify(item));
            // console.log('==1');
            if (type == "delete") {
                this.weekList[code].domArr.splice(key, 1);
            } else if (type == "cancel") {
                this.weekList[code].domArr[key] = this.stubData;
                item.changeTimeShow = false;
                this.iShow = null;
            } else if (type == "ok") {
                // console.log('点击ok要执行的操作',item,item.startM)
                item.startH = this.timeVerification(item.startH);
                item.startM = this.timeVerification(item.startM);
                item.endH = this.timeVerification(item.endH);
                item.endM = this.timeVerification(item.endM);
                this.operate(code, item);
            }
        },
        // 颜色调整
        adjustment(val) {
            if (val == 1) {
                return "#637DEC";
            } else if (val == 2) {
                return "#74B557";
            } else if (val == 3) {
                return "#B83F42";
            } else if (val == 4) {
                return "#E58805";
            } else if (val == 5) {
                return "#B9E2FE";
            } else if (val == 6) {
                return "#AA6FFE";
            }
        },
        // 按钮组-确定-验证逻辑
        operate(code, item) {
            // 1-时间验证
            if (
                parseInt(item.startH) > parseInt(item.endH) ||
                (parseInt(item.startH) == parseInt(item.endH) &&
                    parseInt(item.startM) >= parseInt(item.endM))
            ) {
                this.$modal.msgWarning("开始时间必须早于结束时间");
                return;
            }
            // 2-区域变更
            let domArr = this.weekList[code].domArr;
            // console.log('查找对应星期的所有时间块数据==',domArr,item)
            let arrCopy = JSON.parse(JSON.stringify(domArr));
            // 对需要移动的子块的所在数组重新按照left大小排序
            function sortLeft(a, b) {
                return a.left - b.left;
            }
            arrCopy.sort(sortLeft);
            let mark = 0;
            for (let i = 0; i < arrCopy.length; i++) {
                if (arrCopy[i].left === item.left) {
                    mark = i;
                    break;
                }
            }
            if (arrCopy.length !== 1) {
                if (mark === 0) {
                    if (
                        `${arrCopy[mark].endH}:${arrCopy[mark].endM}` >
                        `${arrCopy[mark + 1].startH}:${
                            arrCopy[mark + 1].startM
                        }`
                    ) {
                        this.$modal.msgWarning(
                            "时间段存在重复,请检查后重新设置"
                        );
                        return false;
                    }
                } else if (mark === arrCopy.length - 1) {
                    if (
                        `${arrCopy[mark].startH}:${arrCopy[mark].startM}` <
                        `${arrCopy[mark - 1].endH}:${arrCopy[mark - 1].endM}`
                    ) {
                        this.$modal.msgWarning(
                            "时间段存在重复,请检查后重新设置"
                        );
                        return false;
                    }
                } else if (mark !== 0 && mark < arrCopy.length - 1) {
                    if (
                        `${arrCopy[mark].startH}:${arrCopy[mark].startM}` <
                            `${arrCopy[mark - 1].endH}:${
                                arrCopy[mark - 1].endM
                            }` ||
                        `${arrCopy[mark].endH}:${arrCopy[mark].endM}` >
                            `${arrCopy[mark + 1].startH}:${
                                arrCopy[mark + 1].startM
                            }`
                    ) {
                        // 修改的开始时间要 大于等于 之前的结束时间 或 修改的结束时间 小于等于 之后的 开始时间
                        this.$modal.msgWarning(
                            "时间段存在重复,请检查后重新设置"
                        );
                        return false;
                    }
                }
            }
            item.left = this.conversionpx("left", item);
            item.width = this.conversionpx("width", item);
            item.changeTimeShow = !item.changeTimeShow;
            item.value = this.sonVal;
            item.bg = this.adjustment(item.value);
            this.iShow = null;
        },
        // 小弹框显示时触发
        showFun(item) {
            this.popoverStubData.push(JSON.parse(JSON.stringify(item)));
        },
        // 小弹框隐藏时触发
        hideFun(item) {
            if (this.iShow != null) {
                item.endH = this.popoverStubData[0].endH;
                item.endM = this.popoverStubData[0].endM;
                item.startH = this.popoverStubData[0].startH;
                item.startM = this.popoverStubData[0].startM;
            }
            this.popoverStubData.splice(0, 1);
        },
        // 剥离自定义指令的小时事件
        hhInput(val, code, key, item) {
            var reg = RegExp(/\D/);
            if (reg.test(item[val])) {
                item[val] = "00";
            } else if (item[val] >= 24) {
                item[val] = 24;
                if (item[val] == 24) {
                    item[val == "startH" ? "startM" : "endM"] = "00";
                }
            }
        },
        // 剥离自定义指令的分钟事件
        mmInput(val, code, key, item) {
            var reg = RegExp(/\D/);
            // 数字验证
            if (
                reg.test(item[val]) ||
                item["startH"] == 24 ||
                item["endH"] == 24
            ) {
                item[val] = "00";
            } else if (item[val] > 59) {
                item[val] = 59;
            }
        },
        // 点击确定后验证时间数据是否需要添加 '0' 或者 '00' 或者不变
        timeVerification(time) {
            let timeData = time.toString();
            if (timeData.length == 0) {
                return "00";
            } else if (timeData.length == 1) {
                return `0${timeData}`;
            } else if (timeData.length == 2) {
                return timeData;
            }
        },
        // 取消
        returnCancel() {
            this.$emit("returnCancel");
        },
        // 确定
        submit() {
            // this.$emit('returnSubmit')
            // console.log(this.domObj,'---===storagePlanId=',this.id,"查看data内的数据==>>", JSON.stringify(this.weekList));
            this.addStorageCycle();
        },
        // 查询
        listStorageCycle() {
            this.btnLoading = true;
            listStorageCycle({ storagePlanId: this.id }).then((res) => {
                if (res.code === 200 && res.rows.length != 0) {
                    // 此处如果接口正常并且有数据才能进行操作
                    res.rows.forEach((i) => {
                        this.deleteId.push(i.storageTimeId);
                        this.weekList.forEach((j) => {
                            if (i.week - 1 == j.code) {
                                let obj = {
                                    width: i.width, //宽度
                                    left: i.left, //左偏移量
                                    bg: this.adjustment(i.type), //背景色(与背景值关联,对应着下拉框的值
                                    value: i.type, //背景值(与背景色关联,对应着下拉框的值
                                    startH: i.startTime.split(":")[0], //开始时间(时
                                    startM: i.startTime.split(":")[1], //开始时间(分
                                    endH: i.endTime.split(":")[0], //结束时间(时
                                    endM: i.endTime.split(":")[1], //结束时间(分
                                    changeTimeShow: false, //控制时间显示与时间调整
                                };
                                j.domArr.push(obj);
                            }
                        });
                    });
                    // console.log(this.deleteId,'《==删除的id=====渲染的数据==》',JSON.stringify(this.weekList))
                } else if (res.code != 200) {
                    this.$modal.msgWarning(res.msg);
                }
                this.btnLoading = false;
            });
        },
        // 新增或修改
        addStorageCycle() {
            this.btnLoading = true;
            // 数据处理
            let params = [];
            this.weekList.forEach((i) => {
                i.domArr.forEach((j) => {
                    if (j) {
                        let obj = {
                            startTime: `${j.startH}:${j.startM}`, //存储开始时间 HH:MM
                            endTime: `${j.endH}:${j.endM}`, //存储结束时间 HH:MM
                            storagePlanId: this.id, //存储计划id
                            type: j.value, //存储计划周期类型(1=定时 2=移动侦测 3=报警 4=动测或报警 5=动测和报警 6=事件)
                            week: i.code + 1, //星期(1~7)
                            width: j.width, //宽
                            left: j.left, //left
                        };
                        params.push(obj);
                    }
                });
            });
            // console.log('接口参数==>>',params)
            if (this.deleteId.length === 0 && params.length === 0) {
                this.$emit("returnSubmit");
                this.btnLoading = false;
                return;
            }
            if (params.length != 0) {
                addStorageCycle(params).then((res) => {
                    // console.log('新增或者修改返回==>',res)
                    if (res.code == 200) {
                        this.$modal.msgSuccess(
                            this.$t("public.successfulTexts")
                        );
                        this.$emit("returnSubmit");
                    } else {
                        this.$modal.msgError(this.$t("public.failedTexts"));
                    }
                    this.btnLoading = false;
                });
            } else {
                this.delStorageCycle();
            }
        },
        // 当要传的数据是[]时则调用(删除所有)
        delStorageCycle() {
            delStorageCycle(this.deleteId).then((res) => {
                if (res.code == 200) {
                    this.$modal.msgSuccess(this.$t("public.successfulTexts"));
                    this.$emit("returnSubmit");
                } else {
                    this.$modal.msgError(this.$t("public.failedTexts"));
                }
                this.btnLoading = false;
            });
        },
    },
};
</script>
<style lang="scss" scoped>
.title-box {
    margin-bottom: 20px;
}
.title {
    margin-left: 10px;
}
.cycle-box {
    margin: 15px 0;
    width: 800px;
    display: flex;
    align-items: end;
}
.week {
    color: #fff;
    padding-right: 10px;
}
/* 此处总长是720,是一天1440分钟的一半 */
.slide-list {
    width: 720px;
    color: #fff;
}
.slide-ruler {
    position: relative;
    left: -5px;
    width: 730px;
    display: flex;
    justify-content: space-between;
}
.scale {
    text-align: center;
    width: 15px;
    font-size: 12px;
}
.slide-box {
    width: 100%;
    height: 20px;
    background: #fff;
    display: flex;
    position: relative;
}
.item {
    height: 100%;
    position: absolute;
}
.i-class {
    width: 6px;
    height: 20px;
    position: absolute;
    display: inline-block;
    background: url(../../../../assets/images/storageImg/xiaofk.png);
    background-position: -5px;
    z-index: 1;
}
.i-left-class {
    left: -3px;
}
.i-right-class {
    right: -3px;
}
.i-class:hover {
    cursor: w-resize;
}

.timeHover {
    width: 100%;
    height: 100%;
    display: inline-block;
}
.copy-class {
    justify-content: space-between;
    border-bottom: 1px solid #eeeeee;
}
.checkbox-class {
    margin: 5px 10px;
}
.w40 {
    width: 40px !important;
}
.color-class {
    align-items: center;
    margin-bottom: 10px;
}
.color-bg {
    width: 20px;
    height: 20px;
    margin-right: 10px;
}
</style>

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到