Vue+Element-ui日歷排班自定義實(shí)例代碼
前言
在日常開發(fā)需求中,可能會遇到給員工進(jìn)行排班的需求,如果只是在table表格中顯示,會顯得枯燥、不直觀,今天我們就來寫一個可以自定義的日歷排班功能,用的是vue2+element-ui。
效果圖如下:

(圖一):日歷中顯示排班數(shù)據(jù),排班數(shù)據(jù)可以使用鼠標(biāo)進(jìn)行拖動,改變排班的順序。

(圖二):可以對日期范圍進(jìn)行批量、多班次排班

(圖三):可以對單日排班信息進(jìn)行操作,顯示單日排班時間的具體信息等。
下面是代碼部分:
<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 語法,對于新項(xiàng)目請使用 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="結(jié)束日期">
</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>
<!-- 單獨(dú)排班 -->
<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="結(jié)束時間" 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": "三班兩運(yùn)轉(zhuǎn)",
"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": "三班兩運(yùn)轉(zhuǎn)",
"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": "三班兩運(yùn)轉(zhuǎn)",
"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": "三班兩運(yùn)轉(zhuǎn)",
"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": "三班兩運(yùn)轉(zhuǎn)",
"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中針對放置目標(biāo)來設(shè)置!
},
handleDragEnter(e, item) {
e.dataTransfer.effectAllowed = 'move'// 為需要移動的元素設(shè)置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": "三班兩運(yùn)轉(zhuǎn)",
"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;
},
// 清除單日排班數(shù)據(jù)
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'
});
}
},
// 批量添加排班數(shù)據(jù)
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": "三班兩運(yùn)轉(zhuǎn)",
"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;
}
/* 側(cè)邊彈窗 */
.add-btn-class {
margin: 10px;
float: right;
}
</style>總結(jié)
到此這篇關(guān)于Vue+Element-ui日歷排班的文章就介紹到這了,更多相關(guān)Vue Element-ui日歷排班內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue 中 a標(biāo)簽上href無法跳轉(zhuǎn)的解決方式
今天小編大家分享一篇Vue 中 a標(biāo)簽上href無法跳轉(zhuǎn)的解決方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11
vue如何將html內(nèi)容轉(zhuǎn)為圖片并下載到本地
這篇文章主要介紹了vue如何將html內(nèi)容轉(zhuǎn)為圖片并下載到本地,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-01-01
vue中實(shí)現(xiàn)子組件相互切換且數(shù)據(jù)不丟失的策略詳解
項(xiàng)目為數(shù)據(jù)報(bào)表,但是一個父頁面中有很多的子頁面,而且子頁面中不是相互關(guān)聯(lián),但是數(shù)據(jù)又有聯(lián)系,所以本文給大家介紹了vue中如何實(shí)現(xiàn)子組件相互切換,而且數(shù)據(jù)不會丟失,并有詳細(xì)的代碼供大家參考,需要的朋友可以參考下2024-03-03
vue報(bào)錯"vue-cli-service‘不是內(nèi)部或外部命令,也不是...”的解決辦法
這篇文章主要介紹了vue報(bào)錯"vue-cli-service‘不是內(nèi)部或外部命令,也不是...”的解決辦法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-01-01
vue項(xiàng)目登錄頁面實(shí)現(xiàn)記住用戶名和密碼的示例代碼
本文主要介紹了vue項(xiàng)目登錄頁面實(shí)現(xiàn)記住用戶名和密碼的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07

