el-calendar日历 简易排班

news2024/12/23 11:48:46

公司物流部要个简易的排班功能,由主管去设置线路,线路绑定上负责人。然后直接往日历里添加。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1、隐藏了自带的切换月份,改用了日期选择器。
2、禁用了非本月的点击事件,防止点击自动跳转到其他月份。
3、添加了点击多选,批量处理,也有单日排班处理。
4、拖拽删除排班,

代码如下

export function getFirstDay(monthValue) {
  let date = new Date(monthValue)
  let month = parseInt(date.getMonth() + 1)
  let day = date.setDate(1);
  if (month < 10) month = '0' + month
  if (day < 10) day = '0' + day
  return date.getFullYear() + '-' + month
}
export function getLastDay(monthValue){
  var year = new Date(monthValue).getFullYear(); //获取年份
  var month = new Date(monthValue).getMonth() + 1; //获取月份
  var lastDate = new Date(year, month , 0).getDate(); //获取当月最后一日
  month = month < 10 ? '0' + month : month ; //月份补 0
  return [ year,month ,lastDate ].join("-")
}
export function getNextDayByDay(dayValue) {
  let date = new Date(new Date(dayValue).getTime() + 3600 * 24 * 1000)
  let month = parseInt(date.getMonth() + 1)
  let day = date.getDate()
  if (month < 10) month = '0' + month
  if (day < 10) day = '0' + day
  return date.getFullYear() + '-' + month + '-' + day
}

时间过滤是因为我这边大部分后端接口让传2个日期,所以统一处理了。

<template>
  <div class="calender_body">
    <div class="calender-class">
      <div class="class-header">
        <el-date-picker
          v-model="currentMonth"
          type="month"
          format="yyyy 年 MM 月"
          value-format="yyyy-MM"
          placeholder="选择月份"
          @change="changeCurrentMonth"
        />
        <el-button
          type="primary"
          style="margin-left: 10px;"
          :disabled="!selectDateItems.length"
          @click="handleShowAddBatchDialog"
        >批量排班</el-button>
      </div>
      <div class="monthText">{{ currentMonth && currentMonth.replace(/-/,'年') }}月 排班表</div>
      <div v-if="isdraging" class="deleteDiv">
        <div
          class="delIconBox"
          @dragover.prevent
          @dragenter.prevent
          @drop="handleDeleteClassByDrop"
        >
          <i class="el-icon-delete" style="font-size: 40px;" />
        </div>
      </div>
    </div>
    <el-calendar v-model="currentMonth">
      <!-- 这里使用的是 2.5 slot 语法,对于新项目请使用 2.6 slot 语法-->
      <template slot="dateCell" slot-scope="{date, data}">
        <div
          class="day-content-class"
          :class="selectDateItems.some(el => el == data.day)? 'is-selected':''"
          @click.stop="handleSelectItem(data)"
        >
          <div class="header-class">
            <div class="day-class">{{ data.day.split('-').slice(1).join('-') }}</div>
            <div class="handle-class">
              <el-button
                icon="el-icon-edit"
                class="edit-color"
                circle
                @click.stop="handleWorkInfo(data)"
              />
            </div>
          </div>
          <template v-if="viewDate[data.day]">
            <div class="paiban-class">
              <!--  @dragenter="handleDragEnter($event, dayValue)"  @dragover.prevent="handleDragOver($event)"-->
              <div
                v-for="(dayValue, i,index) in viewDate[data.day]"
                :key="index"
                draggable="true"
                @dragstart="handleDragStart(dayValue)"
                @dragend="handleDragEnd()"
              >
                <div class="class-item-tag">
                  <span>{{ dayValue.logisticsRouteName }}</span>
                  <span v-if="dayValue.users">-{{ dayValue.users[0].userName }}</span>
                </div>
              </div>
            </div>
          </template>
          <template v-else>
            <div class="no-work-class">
              <div class="icon-class">
                <i class="el-icon-date" />
              </div>
              <div class="tips-class">暂无排班</div>
            </div>
          </template>
        </div>
      </template>
    </el-calendar>
    <!-- 批量排班 -->
    <el-dialog title="批量排班" :visible.sync="addBatchDialog" size="50%">
      <el-form :model="addBatchForm">
        <el-form-item label="值班路线" label-width="80px">
          <el-select
            v-model="addBatchForm.logisticsRouteCode"
            style="width:100%"
            placeholder="请选择"
            filterable
            multiple
            default-first-option
            clearable
          >
            <el-option
              v-for="item in routerDataList"
              :key="item.id"
              :label="item.name"
              :value="item.code"
              :disabled="selectDateItemsHasRouteArr.some(el => el == item.code)"
            >
              <span style="float: left">{{ item.name }}</span>
              <span
                style="float: right;margin-right: 12px; color: #8492a6; font-size: 13px"
              >{{ item.userInfos[0].userName }}</span>
            </el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addBatchDialog = false">取 消</el-button>
        <el-button type="primary" @click="handleSubmitAddBatch">确 定</el-button>
      </span>
    </el-dialog>
    <!-- 排班详情-->
    <el-drawer :title="'【' + currentDay + '】排班'" :visible.sync="dayClassdrawer" size="50%">
      <div style="width: 99%;margin:0 auto">
        <el-button type="primary" style="margin-bottom: 4px;" @click="addDayClassDialog = true">添加排班</el-button>
        <el-table :data="workInfoList" border :height="`calc(100vh - 180px)`">
          <el-table-column prop="day" label="日期" width="90" show-overflow-tooltip />
          <el-table-column prop="logisticsRouteName" label="线路" width="140" show-overflow-tooltip />
          <el-table-column label="负责人" width="120" show-overflow-tooltip>
            <template slot-scope="scope">{{ scope.row.users.join('; ') }}</template>
          </el-table-column>
          <el-table-column label="途径医院" width="*" show-overflow-tooltip>
            <template slot-scope="scope">{{ scope.row.hospitals.join('; ') }}</template>
          </el-table-column>
          <el-table-column fixed="right" label="操作" width="100">
            <template slot-scope="scope">
              <el-button
                type="text"
                style="color:red"
                @click.native.prevent="deleteRow(scope.row)"
              >删除</el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </el-drawer>
    <!-- 单日排班 -->
    <el-dialog :title="'添加【' + currentDay + '】排班'" :visible.sync="addDayClassDialog" size="50%">
      <el-form :model="addForm">
        <el-form-item label="值班路线" label-width="80px">
          <el-select
            v-model="addForm.logisticsRouteCode"
            style="width:100%"
            placeholder="请选择"
            filterable
            multiple
            default-first-option
            clearable
          >
            <el-option
              v-for="item in routerDataList"
              :key="item.id"
              :label="item.name"
              :value="item.code"
              :disabled="workInfoList.some(el => el.logisticsRouteCode == item.code)"
            >
              <span style="float: left">{{ item.name }}</span>
              <span
                style="float: right;margin-right: 12px; color: #8492a6; font-size: 13px"
              >{{ item.userInfos[0].userName }}</span>
            </el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDayClassDialog = false">取 消</el-button>
        <el-button type="primary" @click="handleSubmitAddDayClass">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>
   
<script>
import { getFirstDay, getNextDayByDay, getLastDay } from "@/utils/index";
export default {
  data() {
    return {
      isdraging: false,
      selectDateItems: [], // 当前选择日期
      selectDateItemsHasRouteArr: [], // 当前日期包含的线路
      routerDataList: [], // 线路
      currentMonth: "",
      viewDate: {},
      thisDay: null,
      thisDayWork: null,
      ending: null,
      dragging: null,

      addBatchDialog: false,
      // 批量添加
      addBatchForm: {
        logisticsRouteCode: []
      },
      // 单日添加
      addForm: {
        logisticsRouteCode: []
      },
      dayClassdrawer: false,
      currentDay: "",
      addDayClassDialog: false,
      workInfoList: [],
      dialogLoading: false
    };
  },
  mounted() {
    this.getRouteListData();
    this.currentMonth = getFirstDay(new Date().getTime());
    this.getCurrentMonthClass();
  },
  methods: {
    handleDragStart(item) {
      this.isdraging = true;
      this.dragging = item;
    },
    handleDragEnd() {
      this.isdraging = false;
    },
    // 拖动删除排班
    handleDeleteClassByDrop(e) {
      let params = [this.dragging.id];
      this.$api.LogisticsScheduleApi.DeleteLogisticsSchedule(params).then(
        res => {
          this.$message.success("删除成功");
          this.getCurrentMonthClass();
        }
      );
    },
    // handleDragOver(e) {
    //   // 首先把div变成可以放置的元素,即重写dragenter/dragover
    //   e.dataTransfer.dropEffect = "move"; // e.dataTransfer.dropEffect="move";//在dragenter中针对放置目标来设置!
    // },
    // handleDragEnter(e, item) {
    //   e.dataTransfer.effectAllowed = "move"; // 为需要移动的元素设置dragstart事件
    //   this.ending = item;
    // },

    // 获取线路列表
    getRouteListData() {
      let params = {
        pageIndex: 1,
        pageSize: 999
      };
      this.$api.LogisticsScheduleApi.PageLogisticsRoute(params).then(res => {
        this.routerDataList = res.data.items;
      });
    },
    // 切换月份
    changeCurrentMonth(e) {
      this.currentMonth = e;
      this.getCurrentMonthClass();
    },
    // 获取当前月物流排班
    getCurrentMonthClass() {
      let params = {
        StartDay: this.currentMonth + "-01",
        EndDay: getLastDay(this.currentMonth + "-01")
      };
      this.$api.LogisticsScheduleApi.QueryLogisticsSchedule(params).then(
        res => {
          let obj = {};
          if (res.data.length) {
            for (let i of res.data) {
              if (obj[i.day]) {
                obj[i.day].push({ ...i });
              } else {
                obj[i.day] = [{ ...i }];
              }
            }
          }
          this.viewDate = obj;
        }
      );
    },
    // 单日排班详情抽屉
    handleWorkInfo(data) {
      this.currentDay = data.day;
      let params = {
        StartDay: this.currentDay,
        EndDay: getNextDayByDay(this.currentDay)
      };
      this.$api.LogisticsScheduleApi.QueryLogisticsSchedule(params).then(
        res => {
          this.workInfoList = res.data.map(el => {
            el.hospitals = el.hospitals.map(item => item.hospitalName);
            el.users = el.users.map(item => item.userName);
            return el;
          });
        }
      );
      this.dayClassdrawer = true;
    },
    // 添加单日排班
    handleSubmitAddDayClass() {
      let params = {
        logisticsRouteCode: this.addForm.logisticsRouteCode,
        day: [this.currentDay]
      };
      this.dialogLoading = true;
      this.$api.LogisticsScheduleApi.CreateLogisticsSchedule(params)
        .then(res => {
          this.$message.success("添加成功");
          let parmas = {
            day: this.currentDay
          };
          this.handleWorkInfo(parmas);
          this.getCurrentMonthClass();
          this.addDayClassDialog = false;
        })
        .finally(() => {
          this.dialogLoading = false;
        });
    },
    // 删除排班
    deleteRow(row) {
      this.$confirm("此操作将会删除此条排班记录, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }).then(() => {
        let params = [row.id];
        this.$api.LogisticsScheduleApi.DeleteLogisticsSchedule(params).then(
          res => {
            this.$message.success("删除成功");
            this.getCurrentMonthClass();
            let date = {
              day: this.currentDay
            };
            this.handleWorkInfo(date);
          }
        );
      });
    },
    // 选中事件
    handleSelectItem(data) {
      let dataStr = data.day;
      if (this.selectDateItems.findIndex(el => el == dataStr) > -1) {
        this.selectDateItems.splice(
          this.selectDateItems.findIndex(el => el == dataStr),
          1
        );
      } else {
        this.selectDateItems.push(dataStr);
      }
    },
    //批量弹窗
    handleShowAddBatchDialog() {
      let arr = [];
      for (let i of this.selectDateItems) {
        if (this.viewDate[i]) {
          for (let j of this.viewDate[i]) {
            arr.push(j.logisticsRouteCode);
          }
        }
      }
      const newArr = [...new Set(arr)];
      this.selectDateItemsHasRouteArr = newArr;
      this.addBatchDialog = true;
    },
    //批量排班提交
    handleSubmitAddBatch() {
      let params = {
        logisticsRouteCode: this.addBatchForm.logisticsRouteCode,
        day: this.selectDateItems
      };
      this.dialogLoading = true;
      this.$api.LogisticsScheduleApi.CreateLogisticsSchedule(params)
        .then(res => {
          this.$message.success("添加成功");
          this.getCurrentMonthClass();
          this.selectDateItems = [];
          this.addBatchForm = this.$options.data().addBatchForm;
          this.addBatchDialog = false;
        })
        .finally(() => {
          this.dialogLoading = false;
        });
    }
  }
};
</script>
   
<style lang="scss" scoped>
.calender_body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

.el-table__fixed-right {
  height: 100% !important;
}

.calender-class {
  position: relative;
  width: 100%;
  height: 70px;
}
.class-header {
  position: relative;
  padding: 10px;
  display: flex;
}
.deleteDiv {
  position: absolute;
  width: 100%;
  height: 70px;
  line-height: 70px;
  text-align: center;
  z-index: 11;
  top: 0;
  left: 0;
  background: rgba(155, 155, 155, 0.6);
}
.delIconBox {
  width: 160px;
  height: 60px;
  border-radius: 10px;
  background: rgba(155, 155, 155, 0.9);
  box-shadow: 0 0 10px #fff;
  margin: 5px auto;
}
.monthText {
  width: 100%;
  text-align: center;
  font-size: 16px;
  font-weight: 500;
  line-height: 20px;
  color: #666;
  height: 20px;
}
::v-deep .el-calendar-table thead th {
  box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.3);
}
.is-selected {
  color: #1989fa;
  background: #ddeffb;
}

::v-deep .el-calendar__body {
  height: 85vh;
}

::v-deep .el-calendar-table {
  width: 100%;
  height: 100%;
  //使不是本月的日期不可点击,不会跳转到其他月份
  &:not(.is-range) {
    td.next {
      pointer-events: none;
    }
    td.prev {
      pointer-events: none;
    }
  }
  td.is-selected {
    background: none !important;
  }
  .prev,
  .next {
    .icon-class,
    .tips-class,
    .edit-color {
      color: #e1e1e1;
    }
  }
  td.is-today {
    .day-class {
      background: #44a2f3;
      width: 50px;
      text-align: center;
      height: 20px;
      border-radius: 4px;
      color: #fff;
      font-weight: 500;
    }
  }
}

::v-deep .el-calendar-day {
  height: 100% !important;
  padding: 1px;
}
::v-deep .el-calendar__header {
  display: none;
}

.day-content-class {
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: 7px;
}

.header-class {
  display: flex;
  height: 24px;
  justify-content: space-between;
  align-items: center;
}

.paiban-class {
  display: flex;
  flex-flow: wrap;
  align-items: center;
  .class-item-tag {
    font-size: 12px;
    line-height: 20px;
    color: #fff;
    width: auto;
    border-radius: 4px;
    padding: 0 4px;
    margin: 4px;
    background: #11be11;
  }
}

.paiban-icon-class {
  font-size: 22px;
  margin: 8px 0 10px 0;
}

.paiban-name-class {
  padding-top: 10px;
}

.no-work-class {
  text-align: center;
  color: #cacaca;
}

.icon-class {
  font-size: 20px;
  color: #777;
  margin-bottom: 20px;
}
.tips-class {
  font-size: 14px;
  color: #777;
}
.edit-color {
  color: #333;
}
</style>

文章参考: https://blog.csdn.net/qq_40601005/article/details/131376086

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1012714.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C# 流Stream详解(3)——FileStream源码

【FileStream】 构造函数 如果创建一个FileStream&#xff0c;常见的参数例如路径Path、操作方式FileMode、权限FileAccess。 这里说下FileShare和SafeFileHandle。 我们知道在读取文件时&#xff0c;通常会有两个诉求&#xff1a;一是如何更快的读取文件内容&#xff1b;二…

ATECLOUD二极管测试系统可以解决反向电流测试哪些痛点?

二极管具有单向导电性&#xff0c;但是有时候也会出现反向电流的情况。当反向电流变得很大时&#xff0c;二极管性能和寿命会受到很大影响。通过二极管测试系统对反向电流进行测试可以评估其性能和稳定性。 反向电流测试的重要性 理想情况下反向电流非常小&#xff0c;甚至可以…

2021年电工杯数学建模A题高铁牵引供电系统运行数据分析及等值建模求解全过程论文及程序

2021年电工杯数学建模 A题 高铁牵引供电系统运行数据分析及等值建模 原题再现&#xff1a; 我国是世界上电气化铁路运营里程最长、服役电力机车型号最多、运营最繁忙的国家。截至 2020 年底&#xff0c;我国铁路年消耗电量约 800 亿千瓦时&#xff0c;约占三峡年总发电量的 8…

Java实现添加文字水印、图片水印功能实战

java实现给图片添加水印实现步骤&#xff1a; 获取原图片对象信息&#xff08;本地图片或网络图片&#xff09; 添加水印&#xff08;设置水印颜色、字体、坐标等&#xff09; 处理输出目标图片 java实现给图片添加文字水印 获取原图片对象信息 第一步&#xff1a;获取需要…

人工智能安全-6-SQL注入检测

0 提纲 概述SQL注入方法SQL注入的检测方法SQL语句的特征提取天池AI上的实践 1 概述 SQLIA&#xff1a;SQL injection attack SQL 注入攻击是一个简单且被广泛理解的技术&#xff0c;它把 SQL 查询片段插入到 GET 或 POST 参数里提交到网络应用。 由于SQL数据库在Web应用中的…

【微服务实战之Docker容器】第四章-【微服务实战之Docker容器】第三章-镜像仓库

系列文章目录 【微服务实战之Docker容器】第一章-下载及安装 文章目录 系列文章目录坑&#xff1a;容器卷记得加入以下命令配置是个啥&#xff1f;能干啥&#xff1f;基本的命令读写规则映射添加说明卷的继承和共享 坑&#xff1a;容器卷记得加入以下命令配置 --privilegedtr…

van-calendar 实现移动端日历效果

<!--移动端端展示日历--><divv-if"isMobile &&tabActiveName true &&(formName 值班日历 || formName 值班编排)"><template v-if"Array.isArray(listData) && listData.length"><van-calendar:poppable&…

一生一芯14——chisel环境搭建

本人使用的ubuntu版本为22.04 anaconda 版本为23.1.0 本博客参考自https://blog.csdn.net/qq_38798111/article/details/129190615?ops_request_misc%257B%2522request%255Fid%2522%253A%2522169465704516800222836484%2522%252C%2522scm%2522%253A%252220140713.130102334…%…

芯科蓝牙BG27开发笔记8-片上Flash读写

目标 熟悉片上Flash的特点&#xff0c;知道如何使用&#xff0c;最好找到示例代码&#xff0c;有完整例程那是最好的 查找参考手册 除了768K的主空间&#xff0c;还包含&#xff1a; 1. USERDATA区域&#xff0c;用户定义数据&#xff0c;可以读写。大小只有1K。 2. 设备特…

长胜证券:十大流通股东占比例高好还是低好?

近年来&#xff0c;跟着我国本钱商场的不断发展&#xff0c;越来越多的投资者开始了解和关注股东占比这个目标。而在股东占比中&#xff0c;十大流转股东的持股份额是一个重要的目标。可是&#xff0c;关于投资者来说&#xff0c;十大流转股东占比是高好还是低好&#xff1f;本…

【SPI读取外部Flash】使用逻辑分析仪来读取FLASH Device ID

实验设备&#xff1a;25块钱的 逻辑分析仪 和 野火F429开发板 注意点&#xff0c;这个逻辑分析仪最大只能检测24M的波形&#xff0c;而SPI是在外部通道2&#xff0c;所以我们对系统时钟的分频&#xff0c;也就是给到通道2的时钟速度要在24M内&#xff0c;不然检测到的数据是有…

Peppertype.ai:人工智能内容营销平台

【产品介绍】 名称 Peppertype.ai 具体描述 Peppertype.ai是一个AI驱动的文章生成工具&#xff0c;可以帮助你在几秒钟内为各种渠道创建吸引人 的内容。无论你是想要写广告文案、社交媒体标题、博客大纲还是网站内容&#xff0c;Peppertype…

C++ PrimerPlus 复习 第五章 循环和关系表达式

第一章 命令编译链接文件 make文件 第二章 进入c 第三章 处理数据 第四章 复合类型 &#xff08;上&#xff09; 第四章 复合类型 &#xff08;下&#xff09; 第五章 循环和关系表达式 文章目录 for循环&#xff1b;基本语法重要问题和解答 基于范围的for循环&#xff08…

中秋学习Qt6

中秋学习Qt6 【1】Qt6 新增的模块【2】Qt6剔除模块和方法【3】Qt6改进 【1】Qt6 新增的模块 Qt6引入了一些新的模块&#xff0c;以便提供更多的功能和改进。以下是一些Qt6新增的模块&#xff1a; QtQuick3D&#xff1a;Qt6引入了全新的3D引擎模块QtQuick3D&#xff0c;它提供了…

脚本:python绘制七夕爱心

文章目录 效果脚本Reference 效果 脚本 import random from math import sin, cos, pi, log from tkinter import *CANVAS_WIDTH 640 # 画布的宽 CANVAS_HEIGHT 640 # 画布的高 CANVAS_CENTER_X CANVAS_WIDTH / 2 # 画布中心的X轴坐标 CANVAS_CENTER_Y CANVAS_HEIGHT /…

ABB 1TGE120010R1300 控制主板模块

ABB 1TGE120010R1300 控制主板模块是一种用于控制和监测电力设备的模块&#xff0c;具有以下功能&#xff1a; 控制和监测电力设备&#xff1a;该模块可以通过与电力设备连接来控制和监测设备的性能和状态&#xff0c;例如启停设备、调节电压和功率等。 通信功能&#xff1a;该…

学Python的漫画漫步进阶 -- 第十六步

学Python的漫画漫步进阶 -- 第十六步 十六、多线程16.1 线程相关的知识16.1.1 进程16.1.2 线程16.1.3 主线程 16.2 线程模块——threading16.3 创建子线程16.3.1 自定义函数实现线程体16.3.2 自定义线程类实现线程体 16.4 线程管理16.4.1 等待线程结束16.4.2 线程停止 16.5 动动…

【ant-design-vue】ant-design-vue在uniapp使用时,auto-import失败报错

前言 在我的 uniapp vue3 vite 项目中&#xff0c;使用了 ant-design-vue 4.x 组件库&#xff0c;同时我还使用了 vite 插件 auto-import 用于自动导入vue3的组合式api。当我全局引用antd-vue时&#xff0c;开发模式下可以正常运行&#xff0c;却不能 npm run build 正常打包…

港联证券:“保险+期货”快速落地生花 涉及品种累计达18个

从普洱火车站出发&#xff0c;乘车3小时40分钟&#xff0c;经过250公里山路之后&#xff0c;能够到达云南西南边境的孟连县。孟连县全称孟连傣族拉祜族佤族自治县&#xff0c;“孟连”音自傣语&#xff0c;意为“寻找到的好地方”。这里属亚热带气候&#xff0c;热区资源丰富&a…

与社交媒体结合:视频直播美颜sdk在社交平台上的应用

为了让直播内容更吸引人&#xff0c;视频直播美颜sdk&#xff08;Software Development Kit&#xff09;正逐渐崭露头角&#xff0c;为社交媒体用户提供了卓越的美颜效果和互动体验。 一、什么是视频直播美颜sdk&#xff1f; 在深入讨论如何将视频直播美颜sdk整合到社交媒体平…