Vue+Element-ui实例_日历排班(自定义)

news2024/11/17 20:47:10

在日常开发需求中,可能会遇到给员工进行排班的需求,如果只是在table表格中显示,会显得枯燥、不直观,今天我们就来写一个可以自定义的日历排班功能,用的是vue2+element-ui。

效果图如下:

(图一):日历中显示排班数据,排班数据可以使用鼠标进行拖动,改变排班的顺序。

 (图二):可以对日期范围进行批量、多班次排班

(图三):可以对单日排班信息进行操作,显示单日排班时间的具体信息等。

下面是代码部分: 

 

<template>
  <div id="app">
    <div class="calender-class">
      <div class="batch-add-Work-class">
        <el-button class="add-btn-class" size="small" type="primary" @click="batchAddDrawer = true">批量排班</el-button>
      </div>
      <el-calendar>
        <!-- 这里使用的是 2.5 slot 语法,对于新项目请使用 2.6 slot 语法-->
        <template slot="dateCell" slot-scope="{date, data}">
          <div class="day-content-class">
            <template v-if="viewDate[data.day]">
              <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" size="mini" circle
                    @click="handleWorkInfo(viewDate[data.day], data)"></el-button>
                </div>
              </div>
              <div class="paiban-class">
                <div v-for="(dayValue, i) in viewDate[data.day]"
                  :class="['draggable-div' + i, 'each-paiban-class', setWorkClass(dayValue.sort)]" draggable="true"
                  @dragstart="handleDragStart($event, dayValue, data.day)" @dragover.prevent="handleDragOver($event)"
                  @dragenter="handleDragEnter($event, dayValue)" @dragend="handleDragEnd()">
                  <i :class="[setIconClass(dayValue.shiftName), 'paiban-icon-class']"></i>
                  <div class="paiban-name-class">{{ dayValue.groupName }}</div>
                </div>
              </div>
            </template>
            <template v-else>
              <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" size="mini" circle
                    @click="handleWorkInfo(viewDate[data.day], data)"></el-button>
                </div>
              </div>
              <div class="no-work-class">
                <div class="icon-class"><i class="el-icon-date"></i></div>
                <div class="tips-class">
                  暂无排班
                </div>
              </div>
            </template>
          </div>
        </template>
      </el-calendar>
    </div>
    <!-- 批量排班抽屉弹窗 -->
    <div>
      <el-drawer title="批量排班" :visible.sync="batchAddDrawer" size="40%">
        <div class="demo-drawer__content">
          <el-form :model="batchAddForm">
            <el-form-item label="排班日期" label-width="80px">
              <el-date-picker v-model="batchAddForm.batchDate" value-format="yyyy-MM-dd" type="daterange"
                range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期">
              </el-date-picker>
            </el-form-item>
            <el-button type="primary" icon="el-icon-plus" circle @click="addDomain"></el-button>
            <el-form-item label-width="80px" v-for="(data, index) in batchAddForm.classData"
              :label="'排班' + (index + 1) + ':'" :key="data.key">
              <p></p>
              <span>班次:</span>
              <el-radio-group v-model="data.shiftName">
                <el-radio label="早">早</el-radio>
                <el-radio label="中">中</el-radio>
                <el-radio label="晚">晚</el-radio>
              </el-radio-group>
              <p></p>
              <span>班别:</span>
              <el-radio-group class="margin-left:80px" v-model="data.groupName">
                <el-radio label="甲">甲</el-radio>
                <el-radio label="乙">乙</el-radio>
                <el-radio label="丙">丙</el-radio>
              </el-radio-group>
              <el-button class="remove-domain-class" @click.prevent="removeDomain(data)" type="danger"
                icon="el-icon-delete" circle></el-button>
            </el-form-item>
          </el-form>
        </div>
        <div class="demo-drawer__footer">
          <el-button @click="handleBatchClose">取 消</el-button>
          <el-button type="primary" @click="batchAddWork()">
            确定
          </el-button>
        </div>
      </el-drawer>
    </div>
    <!-- 单独排班 -->
    <div>
      <el-drawer :title="'【' + hanleDay.day + '】排班'" :visible.sync="drawer" size="40%">
        <div class="add-work-class">
          <el-button class="add-btn-class" type="primary" @click="innerDrawer = true">添加</el-button>
          <el-drawer title="添加排班" :append-to-body="true" :before-close="handleClose" :visible.sync="innerDrawer">
            <div class="demo-drawer__content">
              <el-form :model="addForm">
                <el-form-item label="班次:" label-width="80px">
                  <el-radio-group v-model="addForm.shiftName">
                    <el-radio label="早">早</el-radio>
                    <el-radio label="中">中</el-radio>
                    <el-radio label="晚">晚</el-radio>
                  </el-radio-group>
                </el-form-item>
                <el-form-item label="班别:" label-width="80px">
                  <el-radio-group v-model="addForm.groupName">
                    <el-radio label="甲">甲</el-radio>
                    <el-radio label="乙">乙</el-radio>
                    <el-radio label="丙">丙</el-radio>
                  </el-radio-group>
                </el-form-item>
              </el-form>
            </div>
            <div class="demo-drawer__footer">
              <el-button @click="handleClose">取 消</el-button>
              <el-button type="primary" @click="addWork()">
                确定
              </el-button>
            </div>
          </el-drawer>
        </div>
        <el-table :data="workInfoList">
          <el-table-column property="date" label="日期" width="100"></el-table-column>
          <el-table-column property="shiftName" label="班次"></el-table-column>
          <el-table-column property="groupName" label="班别"></el-table-column>
          <el-table-column property="startTime" label="开始时间" width="160"></el-table-column>
          <el-table-column property="endTime" label="结束时间" width="160"></el-table-column>
          <el-table-column fixed="right" label="操作" width="120">
            <template slot-scope="scope">
              <el-button @click.native.prevent="deleteRow(scope, workInfoList)" type="text" size="small">
                移除
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-drawer>
    </div>

  </div>
</template>

<script>
import moment from 'moment'
export default {
  data() {
    return {
      viewDate: {
        "2023-06-20": [
          {
            "id": "2023-06-20" + Math.random(1000),
            "ruleName": "三班两运转",
            "shiftName": "早",
            "groupName": "甲",
            "startTime": "2023-06-20 08:30",
            "endTime": "2023-06-20 20:30",
            "isNotHoliday": 0,
            "classId": 1,
            "date": "2023-06-20",
            "sort": 1
          },
          {
            "id": "2023-06-20" + Math.random(1000),
            "ruleName": "三班两运转",
            "shiftName": "中",
            "groupName": "乙",
            "startTime": "2023-06-20 20:30",
            "endTime": "2023-06-21 08:30",
            "isNotHoliday": 0,
            "classId": 1,
            "date": "2023-06-20",
            "sort": 2
          },
        ],
        "2023-06-21": [
          {
            "id": "2023-06-21" + Math.random(1000),
            "ruleName": "三班两运转",
            "shiftName": "早",
            "groupName": "甲",
            "startTime": "2023-06-20 08:30",
            "endTime": "2023-06-20 20:30",
            "isNotHoliday": 0,
            "classId": 1,
            "date": "2023-06-20",
            "sort": 1
          },
          {
            "id": "2023-06-21" + Math.random(1000),
            "ruleName": "三班两运转",
            "shiftName": "中",
            "groupName": "乙",
            "startTime": "2023-06-20 08:30",
            "endTime": "2023-06-20 20:30",
            "isNotHoliday": 0,
            "classId": 1,
            "date": "2023-06-20",
            "sort": 2
          },
          {
            "id": "2023-06-21" + Math.random(1000),
            "ruleName": "三班两运转",
            "shiftName": "晚",
            "groupName": "丙",
            "startTime": "2023-06-20 08:30",
            "endTime": "2023-06-20 20:30",
            "isNotHoliday": 0,
            "classId": 1,
            "date": "2023-06-20",
            "sort": 3
          },
        ],
      },
      thisDay: null,
      thisDayWork: null,
      ending: null,
      dragging: null,

      batchAddDrawer: false,
      // 批量添加
      batchAddForm: {
        batchDate: [],
        classData: [{
          shiftName: '早',
          groupName: '甲',
        }]
      },
      // 单日添加
      addForm: {
        shiftName: '早',
        groupName: '甲',
        sort: 1,
      },
      drawer: false,
      innerDrawer: false,
      hanleDay: '',
      workInfoList: []
    };
  },
  watch: {
    'addForm.shiftName'(newVal, oldVal) {
      switch (newVal) {
        case '早':
          this.addForm.sort = 1
          break;
        case '中':
          this.addForm.sort = 2
          break;
        case '晚':
          this.addForm.sort = 3
          break;
        default:
          break;
      }
    }
  },
  computed: {

  },
  methods: {
    handleDragStart(e, item, thisDay) {
      this.dragging = item
      this.thisDay = thisDay
      this.thisDayWork = this.viewDate[thisDay]
    },
    handleDragEnd() {
      if (this.ending.id === this.dragging.id) {
        return
      }
      let newItems = [...this.thisDayWork]
      const src = newItems.indexOf(this.dragging)
      const dst = newItems.indexOf(this.ending)
      newItems.splice(src, 1, ...newItems.splice(dst, 1, newItems[src]))
      this.$set(this.viewDate, this.thisDay, newItems)
      this.$nextTick(() => {
        this.dragging = null
        this.ending = null
      })
      console.log("🚀 ~ file: App.vue:286 ~ handleDragEnd ~ this.viewDate:", this.viewDate)
    },
    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
    },
    // 获取时间范围中的所有日期
    enumerateDaysBetweenDates(startDate, endDate) {
      let daysList = [];
      let SDate = moment(startDate);
      let EDate = moment(endDate);
      daysList.push(SDate.format("YYYY-MM-DD"));
      while (SDate.add(1, "days").isBefore(EDate)) {
        daysList.push(SDate.format("YYYY-MM-DD"));
      }
      daysList.push(EDate.format("YYYY-MM-DD"));
      return daysList;
    },
    setSortValue(value) {
      let sort = 1
      switch (value) {
        case '早':
          sort = 1
          break;
        case '中':
          sort = 2
          break;
        case '晚':
          sort = 3
          break;
        default:
          break;
      }
      return sort
    },
    setWorkClass(value) {
      let classValue = 'no-work-class'
      switch (value) {
        case 1:
          classValue = 'zao-work-class'
          break;
        case 2:
          classValue = 'wan-work-class'
          break;
        case 3:
          classValue = 'ye-work-class'
          break;
        default:
          break;
      }
      return classValue;
    },
    setIconClass(value) {
      let classValue = 'el-icon-sunrise'
      switch (value) {
        case "早":
          classValue = 'el-icon-sunrise'
          break;
        case "中":
          classValue = 'el-icon-sunny'
          break;
        case "晚":
          classValue = 'el-icon-moon'
          break;
        default:
          break;
      }
      return classValue;
    },
    // 编辑单日排班
    handleWorkInfo(info, data) {
      this.hanleDay = data
      this.drawer = true
      if (info && info.length > 0) {
        this.workInfoList = info
      } else {
        this.workInfoList = []
      }
    },
    handleClose() {
      this.innerDrawer = false;
    },
    // 添加单日排班
    addWork() {
      let info = {
        "id": this.hanleDay.day + Math.random(1000),
        "ruleName": "三班两运转",
        "shiftName": this.addForm.shiftName,
        "groupName": this.addForm.groupName,
        "startTime": this.hanleDay.day + " 08:30",
        "endTime": this.hanleDay.day + " 20:30",
        "isNotHoliday": 0,
        "classId": 1,
        "date": this.hanleDay.day,
        "sort": this.addForm.sort
      }
      this.workInfoList.push(info)
      this.$set(this.viewDate, this.hanleDay.day, this.workInfoList)
      this.$forceUpdate()
      this.innerDrawer = false;
    },
    // 清除单日排班数据
    deleteRow(row, tableData) {
      let index = row.$index
      tableData.splice(index, 1);
      if (tableData.length > 0) {
        this.$set(this.viewDate, this.hanleDay.day, tableData)
      } else {
        this.$delete(this.viewDate, this.hanleDay.day);
      }
    },
    addDomain() {
      this.batchAddForm.classData.push({
        shiftName: '早',
        groupName: '甲',
        key: Date.now()
      });
    },
    removeDomain(item) {
      if (this.batchAddForm.classData.length > 1) {
        var index = this.batchAddForm.classData.indexOf(item)
        if (index !== -1) {
          this.batchAddForm.classData.splice(index, 1)
        }
      } else {
        this.$message({
          message: '请至少安排一个排班',
          type: 'error'
        });
      }

    },
    // 批量添加排班数据
    batchAddWork() {
      let dateList = this.batchAddForm.batchDate
      let classList = this.batchAddForm.classData
      let list = []
      if (dateList && dateList.length > 0) {
        list = this.enumerateDaysBetweenDates(dateList[0], dateList[1])
      }
      list.forEach((item) => {
        let workList = []
        classList.forEach((work) => {
          let info = {
            "id": item + Math.random(1000),
            "ruleName": "三班两运转",
            "shiftName": work.shiftName,
            "groupName": work.groupName,
            "startTime": item + " 08:30",
            "endTime": item + " 20:30",
            "isNotHoliday": 0,
            "classId": 1,
            "date": item,
            "sort": this.setSortValue(work.shiftName)
          }
          workList.push(info)
        })
        this.$set(this.viewDate, item, workList)
      })
      this.batchAddDrawer = false
    },
    handleBatchClose() {
      this.batchAddDrawer = false
    }
  }
}
</script>

<style>
#app {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

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

.calender-class {
  width: 100%;
  height: 100%;
}

.is-selected {
  color: #1989FA;
}

.el-calendar__body {
  height: 85vh;
}

.el-calendar-table {
  height: 100%;
}

.el-calendar-day {
  height: 100% !important;
}


.day-content-class {
  height: 100px;
  display: flex;
  flex-direction: column;

}

.header-class {
  flex: 1;
  display: flex;
  height: 28px;
  flex-direction: row;
  justify-content: space-between;

}

.day-class {
  flex: 4;
}

.handle-class {
  flex: 1;
}

.paiban-class {
  flex: 4;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: flex-end;
}

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

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

.each-paiban-class {
  text-align: center;
  max-width: 50px;
  margin: 5px 5px 0 5px;
  border-radius: 5px;
  padding: 0 0 5px 0;
  flex: 1;
}

.zao-work-class {
  background-color: #d9ffd9;
  color: #11be11;
}

.wan-work-class {
  background-color: #fff0bd;
  color: #fccb2c;
}

.ye-work-class {
  background-color: #ddeffb;
  color: #2dabff;
}

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

.icon-class {
  font-size: 20px;
  margin-bottom: 20px;
}

/* 侧边弹窗 */
.add-btn-class {
  margin: 10px;
  float: right;
}
</style>

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

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

相关文章

输出流(写)学习

选择子类&#xff1a;FileOutputStream 文件输出字节流 看到的是d 说明会查询ASCII表 写入记事本时&#xff0c;一个字母是一个字节 public static void main(String[] args) throws Exception {FileOutputStream fos new FileOutputStream("e:\\asd.txt");byte[]…

☆Image captioning☆论文show,attend and tell的程序中create_input_files.py代码详解

手把手实现Image captioning,论文show,attend and tell的程序中create_input_files.py代码详解。如果感觉有用,不妨给博主来个一键三连,白天科研,晚上肝文,实属不易~ ~ ](https://imgse.com/i/p9FmMDK) 1. 代码解析(1) assert dataset in {coco, flickr8k, flickr30k…

【计算机网络】数据链路层--MAC媒体接入控制

1.概念 2.静态划分信道 2.1 频分复用 2.2 时分复用 2.3 波分复用 2.2 码分复用 2.3 习题1 2.4 应用举例 2.5 习题2 2.6 习题3 3.小结

服务器设置tomcat开机自启动(cmd命令行语句,tomcat注册到服务里)

1、找到tomcat安装目录&#xff0c;进入bin/文件夹下面&#xff0c;在此打开windows 命令行窗口。 2、输入 service install tomcatXXX 将tomcat注册成为windows服务&#xff0c;其中tomcatXXX为服务名。 3、查看刚刚注册的服务 “我的电脑”-》右键管理 发现刚刚的服务是手…

Stable Diffusion 无损放大图像和缩小图像

Stable Diffusion默认生成的图片尺寸为512512&#xff0c;这种尺寸的分辨率可能无法满足高质量的要求。若想生成大图&#xff0c;存在两种可选的方法&#xff0c;在显卡足够支撑的情况下可以将图像当打到8K。 文章目录 hires.fix高分辨率修复extras附加功能放大功能缩放功能 hi…

VirtualBox 开启硬件虚拟化

最近用VirtualBox开了一台centos7的虚拟机&#xff0c;想用虚拟机搭建一个KVM环境&#xff0c; 结果发现Virtualbox开启虚拟化的选项是灰色的&#xff0c;无法选择&#xff0c; 解决方法&#xff1a;进入virtualbox安装目录&#xff0c;打开cmd&#xff0c;进入命令行模式打开嵌…

使用NVM下载和安装NodeJS教程

NodeJS下载与安装教程 一、下载 NVM二、安装 NVM三、安装 Node四、配置 NVM 和 NodeJS4.1 配置环境变量4.2 配置node_global和node_cache 这里我是用的 NVM 下载&#xff0c;后期管理 Node 版本很方便&#xff0c;推荐这种方式&#xff0c;还有一种方式是直接下载 NodeJS 进行安…

PPT如何跨页让图像对齐?

例如&#xff1a; 第1页和第2页的图片&#xff0c;希望2张图片在ppt中是固定的位置。 选择视图菜单栏&#xff0c;勾选参考线。 页面空白处&#xff0c;鼠标右键点击&#xff0c;显示菜单栏&#xff0c;选择添加水平或垂直参考线。 拖动参考线到想要的位置&#xff0c…

elementUI表格勾选框判断选择相同的内容才能进行后续逻辑处理;否则拦截提示

需求是&#xff1a; 可多选需满足条件&#xff1a;同一个年级、同一个分数&#xff1b; 不满足条件给出提示&#xff1a;请选择同一个年级 、分数的学生 1、先对勾选数据进行赋值 /** 表格复选框勾选 */handleSelectionChange(val) {console.log(val)this.tableSelectArr va…

5.7.1 UDP概述

5.7.1 UDP概述 用户数据报UDP协议是在IP数据报服务之上增加了两个内容 端口的复用和分用差错控制 一、UDP特点 UDP特点TCP特点无连接面向连接不可靠的服务可靠的服务点到点和多点通信点到点的通信首部8字节首部固定部分20字节面向报文面向字节流 UDP是无连接的服务&#x…

想做一个简单功能小程序需要多久

对于小程序开发的新手来说&#xff0c;往往会有这样一个问题&#xff1a;想做一个简单功能的小程序&#xff0c;大概需要多久时间呢&#xff1f;实际上&#xff0c;这个问题的答案取决于许多因素&#xff0c;包括你的开发技能、你计划实现的功能以及你为项目投入的时间等。 首…

建筑企业缺成本票,怎么解决?学会这几招可胜券在握!

建筑企业缺成本票&#xff0c;怎么解决&#xff1f;学会这几招可胜券在握&#xff01; 《税筹顾问》专注于园区招商、企业税务筹划&#xff0c;合理合规助力企业节税&#xff01; 建筑行业业务流程的特点是一般建筑工期的周期长&#xff0c;涉及的施工人员构成十分复杂&#x…

Docker安装,常用命令,部署MySQL,Tomcat,nginx,redis

Docker简介 Docker是基于Go语言实现的云开源项目。 Docker的主要目标是“Build&#xff0c;Ship and Run Any App,Anywhere”&#xff0c;也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理&#xff0c;使用户的APP&#xff08;可以是一个WEB应用或数据库应用等等…

Cocos Creator Node 旋转角度实现的几种方法

rotation 需要四元数进行旋转&#xff0c;具体旋转方法本博主直接绕开了&#xff0c;因为没给案例不太了解,知道的欢迎评论 1.在Cocos Creator v3.6中&#xff0c;要使用setRotation方法将节点旋转90度&#xff0c;可以使用以下代码&#xff1a; // 获取节点 var node this.n…

Grafana嵌入iframe,websoket连接报错400或403(nginx代理)

1、custom.ini配置文件修改allowed_origins* 2、 nginx中增加配置&#xff0c;如下&#xff1a;

Effective Modern C++ 笔记

Effective Modern C 本文是Effective Modern C学习笔记&#xff0c;以细碎的知识点记录的形式来记录学习过程。 简介&#xff1a; 1、Effective Modern C目标&#xff1a;学习怎样高效地使用新机能 2、移动语义&#xff08;C11&#xff09;&#xff1a; 右值表明这个对象适合…

Unable to Locate package python2 | Linux Ubuntu系统下python2和cif2cell的安装

Linux Ubuntu系统下python2的安装 安装键入命令和报错如下&#xff1a; 背景&#xff1a;官方早年前已经宣布停止 Python 2 的更新和服务&#xff0c;所以对于ubuntu20版本之后的&#xff0c;都是自带安装了python3&#xff0c;但是我们在处理安装某些大型科学计算程序的时候…

【python百炼成魔】python之字典详解

前言 今天我们一起来探讨python的另外一种类型&#xff1a; 字典&#xff0c;如果你没有看过列表和元组&#xff0c;建议先学习列表和元组。 【python百炼成魔】python之元组详解 【python百炼成魔】python之列表详解 文章目录 前言字典的概念语法格式及字典的创建字典的日常…

广告数仓:可视化展示

系列文章目录 广告数仓&#xff1a;采集通道创建 广告数仓&#xff1a;数仓搭建 广告数仓&#xff1a;数仓搭建(二) 广告数仓&#xff1a;全流程调度 广告数仓&#xff1a;可视化展示 文章目录 系列文章目录前言一、FineBI1.FineBI下载2.软件安装3.配置数据库 二、数据可视化1…

I3C协议手册研读-2

阿兴的理解 I3C的时序主要包括SDR模式、HDR模式(HDR-DDR、HDR-TSP、HDR-TSL) 阿兴的理解 上图主要介绍了SDR模式&#xff0c;SDR模式下的波形远看很像I2C波形&#xff0c;因此可以被逻辑分析仪识别到。此外&#xff0c;SDR较I2C增加了一些新的特征。 阿兴的理解 图中很好的绘制…