Browse Source

2024-04-18 排班日历的新页面

master_hella_20240701
zhousq 7 months ago
parent
commit
c2b7a057fa
  1. 641
      src/views/mes/calendar/index.vue

641
src/views/mes/calendar/index.vue

@ -0,0 +1,641 @@
<template>
<div class="app-container">
<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 ref="calendarMain">
<template #date-cell="{ data }">
<template v-if="viewDate[data.day.replace(/-/g, '')]">
<div class="header-class">
<div class="day-class">
{{ data.day.split('-').slice(1).join('-') }}
</div>
<div class="handle-class">
<el-button
size="mini"
circle
@click="handleWorkInfo(viewDate[data.day.replace(/-/g, '')], data)"
><Icon icon="ep:edit" />
</el-button>
</div>
</div>
<div class="paiban-class">
<div
v-for="(dayValue, i) in viewDate[data.day.replace(/-/g, '')]"
:key="i"
:class="['draggable-div' + i, 'each-paiban-class', setWorkClass(dayValue.sort)]"
draggable="true"
@dragstart="handleDragStart(dayValue, data.day)"
@dragover.prevent="handleDragOver($event)"
@dragenter="handleDragEnter($event, dayValue)"
@dragend="handleDragEnd"
>
<i> <Icon :icon="setIconClass(dayValue.shiftName)" /></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
size="mini"
circle
@click="handleWorkInfo(viewDate[data.day.replace(/-/g, '')], data)"
><Icon icon="ep:edit" />
</el-button>
</div>
</div>
<div class="no-work-class">
<div class="icon-class"><Icon icon="ep:clock" /></div>
<div class="tips-class"> 暂无排班 </div>
</div>
</template>
</template>
</el-calendar>
</div>
<!-- 批量排班抽屉弹窗 -->
<div>
<el-drawer title="批量排班" v-model="batchAddDrawer" size="40%">
<div class="demo-drawer_content">
<el-form v-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" @click="addDomain" link> <Icon icon="ep:plus" /> </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 @click.prevent="removeDomain(data)" type="danger" size="mini" link
><Icon icon="ep:delete"
/></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 + '】排班'" v-model="drawer" size="40%">
<div class="add-work-class">
<el-button type="primary" @click="innerDrawer = true">添加</el-button>
<el-drawer
title="添加排班"
:append-to-body="true"
:before-close="handleClose"
v-model="innerDrawer"
>
<div class="demo-drawer__content">
<el-form v-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 #default="scope">
<el-button @click="deleteRow(scope.row, workInfoList)" type="text" size="small">
移除
</el-button>
</template>
</el-table-column>
</el-table>
</el-drawer>
</div>
</div>
</template>
<script setup lang="ts">
import { useMessage } from '@/hooks/web/useMessage'
import dayjs from 'dayjs'
import { ref, reactive, toRefs, watch, computed, onMounted, onBeforeMount, nextTick } from 'vue'
const message = useMessage() //
const viewDate = ref({
'20240417': [
{
id: '2024-4-17' + Math.random() * 1000,
ruleName: '三班两运转',
shiftName: '早',
groupName: '甲',
startTime: '2024-4-17 08:30',
endTime: '2024-4-17 20:30',
isNotHoliday: 0,
classId: 1,
date: '2024-4-17',
sort: 1
},
{
id: '2024-4-17' + Math.random() * 1000,
ruleName: '三班两运转',
shiftName: '中',
groupName: '乙',
startTime: '2024-4-17 20:30',
endTime: '2023-4-16 08:30',
isNotHoliday: 0,
classId: 1,
date: '2024-4-17',
sort: 2
}
],
'20240416': [
{
id: '2024-4-16' + Math.random() * 1000,
ruleName: '三班两运转',
shiftName: '早',
groupName: '甲',
startTime: '2024-4-16 08:30',
endTime: '2024-4-16 20:30',
isNotHoliday: 0,
classId: 1,
date: '2024-4-16',
sort: 1
},
{
id: '2024-4-16' + Math.random() * 1000,
ruleName: '三班两运转',
shiftName: '中',
groupName: '乙',
startTime: '2024-4-16 08:30',
endTime: '2024-4-16 20:30',
isNotHoliday: 0,
classId: 1,
date: '2024-4-16',
sort: 2
},
{
id: '2024-4-16' + Math.random() * 1000,
ruleName: '三班两运转',
shiftName: '晚',
groupName: '丙',
startTime: '2024-4-16 08:30',
endTime: '2024-10-09 20:30',
isNotHoliday: 1,
classId: 1,
date: '2024-4-16',
sort: 3
}
]
})
const thisDay = ref()
const thisDayWork = ref()
const ending = ref()
const dragging = ref()
const batchAddDrawer = ref(false)
//
const batchAddForm = ref({
batchDate: [],
classData: [
{
shiftName: '早',
groupName: '甲'
}
]
})
//
const addForm = ref({
shiftName: '早',
groupName: '甲',
sort: 1
})
const drawer = ref(false)
const innerDrawer = ref(false)
const hanleDay = ref('')
const workInfoList = ref()
//
const dateRange = ref({
start: '2023-10-1',
end: '2023-10-20'
})
const changeDateDrawer = ref(false)
//
const currentDate = ref([])
watch(
() => addForm.value.shiftName,
(newVal) => {
switch (newVal) {
case '早':
addForm.value.sort = 1
break
case '中':
addForm.value.sort = 2
break
case '晚':
addForm.value.sort = 3
break
default:
break
}
}
)
const handleDragStart = (item, data) => {
dragging.value = item
thisDay.value = data
let dkey = dayjs(thisDay.value.date).format('YYYYMMDD')
thisDayWork.value = viewDate.value[dkey]
}
const handleDragEnd = () => {
if (ending.value.id === dragging.value.id) {
return
}
let newItems = [...thisDayWork.value]
const src = newItems.indexOf(dragging.value)
const dst = newItems.indexOf(ending.value)
newItems.splice(src, 1, ...newItems.splice(dst, 1, newItems[src]))
//obj.set(viewDate.value, thisDay.value, newItems);
nextTick(() => {
dragging.value = null
ending.value = null
})
//let dkey=dayjs(thisDay.value.date).format("YYYYMMDD");
//viewDate.value[dkey]=newItems
// console.log(
// "🚀 ~ file: App.vue:286 ~ handleDragEnd ~ this.viewDate:",
// //viewDate.value[dkey]
// );
}
const handleDragOver = (e) => {
// divdragenter/dragover
e.dataTransfer.dropEffect = 'move' // e.dataTransfer.dropEffect="move";//在dragenter中针对放置目标来设置!
}
const handleDragEnter = (e, item) => {
e.dataTransfer.effectAllowed = 'move' // dragstart
ending.value = item
}
//
const enumerateDaysBetweenDates = (startDate, endDate) => {
let daysList = []
let SDate = dayjs(startDate)
let EDate = dayjs(endDate)
//daysList.push(SDate.format("YYYY-MM-DD"));
while (SDate.isBefore(EDate)) {
daysList.push(SDate.format('YYYY-MM-DD'))
//console.log('3333',SDate);
SDate = SDate.add(1, 'day')
//console.log('44',SDate);
}
daysList.push(EDate.format('YYYY-MM-DD'))
return daysList
}
const setSortValue = (value) => {
let sort = 1
switch (value) {
case '早':
sort = 1
break
case '中':
sort = 2
break
case '晚':
sort = 3
break
default:
break
}
return sort
}
const 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
}
const setIconClass = (value) => {
let classValue = 'ep:sunrise'
switch (value) {
case '早':
classValue = 'ep:sunrise'
break
case '中':
classValue = 'ep:sunny'
break
case '晚':
classValue = 'ep:moon'
break
default:
break
}
return classValue
}
//
const handleWorkInfo = (info, data) => {
hanleDay.value = data
console.log('info', info)
drawer.value = true
if (info && info.length > 0) {
workInfoList.value = info
} else {
workInfoList.value = []
}
}
const handleClose = () => {
innerDrawer.value = false
}
//
const addWork = () => {
let info = {
id: hanleDay.value.day + Math.random() * 1000,
ruleName: '三班两运转',
shiftName: addForm.value.shiftName,
groupName: addForm.value.groupName,
startTime: hanleDay.value.day + ' 08:30',
endTime: hanleDay.value.day + ' 20:30',
isNotHoliday: 0,
classId: 1,
date: hanleDay.value.day,
sort: addForm.value.sort
}
workInfoList.value.push(info)
if (!viewDate.value[hanleDay.value.day.replace(/-/g, '')]) {
viewDate.value[hanleDay.value.day.replace(/-/g, '')] = [info]
} else {
viewDate.value[hanleDay.value.day.replace(/-/g, '')].push(info)
}
//row.set(viewDate.value, hanleDay.value, workInfoList.value);
innerDrawer.value = false
}
//
const deleteRow = (row, tableData) => {
let index = row.$index
tableData.splice(index, 1)
if (tableData.length > 0) {
//tableData.$set(viewDate.value, hanleDay.value, tableData.value);
} else {
//tableData.$delete(viewDate.value, hanleDay.value);
}
}
const addDomain = () => {
batchAddForm.value.classData.push({
shiftName: '早',
groupName: '甲',
key: Date.now()
})
}
const removeDomain = (item) => {
if (batchAddForm.value.classData.length > 1) {
var index = batchAddForm.value.classData.indexOf(item)
if (index !== -1) {
batchAddForm.value.classData.splice(index, 1)
}
} else {
message.alert('请至少安排一个排班')
}
}
//
const batchAddWork = () => {
let dateList = batchAddForm.value.batchDate
let classList = batchAddForm.value.classData
//console.log('dateList', dateList)
//console.log('classList', classList)
let list = []
if (dateList && dateList.length > 0) {
list = 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: setSortValue(work.shiftName)
}
workList.push(info)
})
//set(viewDate.value, item, workList.value);
viewDate.value[item.replace(/-/g, '')] = workList
})
batchAddDrawer.value = false
batchAddForm.value = {
batchDate: [],
classData: [
{
shiftName: '早',
groupName: '甲'
}
]
}
}
const handleBatchClose = () => {
batchAddDrawer.value = false
}
//
const initHolidayDate = (data) => {
console.log('🚀 ~ file: App.vue:510 ~ initHolidayDate ~ data:', currentDate.value)
for (let i in currentDate.value) {
if (data.day === currentDate.value[i].day) {
data.isSelected = true
return '✔'
}
}
}
//
const setDisabled = (date) => {
// console.log("🚀 ~ file: App.vue:537 ~ setDisabled ~ date:", date)
if (dayjs(date).isBefore(dateRange.value[0]) || dayjs(date).isAfter(dateRange.value[1])) {
return 'disabled-date-class'
}
}
</script>
<style>
#app-container {
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;
}
.change-date-drawer-class .el-calendar__body {
height: 45%;
}
.change-date-drawer-class .day-content-class {
height: 30px;
}
.disabled-date-class {
color: #ccc;
pointer-events: none;
}
</style>
Loading…
Cancel
Save