vue之排班日历的 实现
- 查询日期和数据,展示对于的排班日历,蓝色为高亮区,代表排班的日期
index.vue
<template>
<div class="inspect_schedule_page repair_page spotCheck-page" v-cloak>
<div class="content">
<div class="do_content">
<div class="content-top">
<div class="search-left">
<el-form :model="ruleForm" :rules="rules" ref="ruleFormRef" label-width="100px">
<el-col :span="8">
<el-form-item :label="年月份" prop="date">
<el-date-picker v-model="ruleForm.date" type="month" format="yyyy-MM" value-format="yyyy-MM"
:placeholder="选择月份" clearable>
</el-date-picker>
</el-form-item>
</el-col>
</el-form>
</div>
<el-col :span="8">
<div style="text-align:right">
<el-button type="primary" @click="search">查询</el-button>
<el-button @click="reset('ruleFormRef')">清除'</el-button>
</div>
</el-col>
</div>
<div class="content-button">
<el-button type="primary" @click="setSchedule">排班设置</el-button>
ruleForm - {{ ruleForm}}
</div>
<div class="table_wrapper table-wrap">
<div class="current-time">
{{ currentShowMonthDate }}
</div>
<div class="btn-wrap">
<el-button :class="['baseBtn', activeMonth ==='prev' ? 'activeBtn':'']" @click="monthChange('prev')"
:disabled="activeMonth ==='prev'">上个月</el-button>
<el-button :class="['baseBtn', activeMonth ==='current' ? 'activeBtn':'']" @click="monthChange('current')"
:disabled="activeMonth ==='current'">本月
</el-button>
<el-button :class="['baseBtn', activeMonth ==='next' ? 'activeBtn':'']" @click="monthChange('next')"
:disabled="activeMonth ==='next'">下个月
</el-button>
</div>
<calendar class="calendar" :width="'100%'" :currentShowMonth="currentShowMonth"
:calendarData="currentTableData" userType="show">
</calendar>
</div>
</div>
</div>
<!-- 设置弹窗 -->
<ScheduleSetting v-if="showSchedule" :showSchedule="showSchedule" @changeScheduleDialog="changeScheduleDialog">
</ScheduleSetting>
</div>
</template>
<script>
import calendar from './components/calendar.vue'
import ScheduleSetting from "./components/ScheduleSetting.vue"
import "@/views/repair/assets/css/repair.css"
export default {
components: {
calendar,
ScheduleSetting,
},
name: 'index',
data() {
return {
ruleForm: {
date: "",
},
rules: {
],
date: [
{ required: true, message: '请选择年月份', trigger: ['blur', 'change'] }
]
},
groupList: [],
currentMonth: "",
currentShowMonth: "",
activeMonth: "current",
currentTableData: [],
showSchedule: false,
};
},
computed: {
currentShowMonthDate() {
let resMonth = "";
if (this.currentShowMonth) {
let tempArr = this.currentShowMonth.split("-");
resMonth = tempArr[0] + " 年 " + parseInt(tempArr[1]) + " 月"
} else {
resMonth = ""
}
return resMonth;
}
},
watch: {
currentMonth(newV) {
this.currentShowMonth = newV;
this.activeMonth = "current"
}
},
methods: {
getPreMonth(date) {
let arr = String(date).split('-');
let year = arr[0];
let month = arr[1];
let year2 = year;
let month2 = parseInt(month) - 1;
if (month2 == 0) {
year2 = parseInt(year2) - 1;
month2 = 12;
}
if (month2 < 10) {
month2 = '0' + month2;
}
let t2 = year2 + '-' + month2
return t2;
},
getNextMonth(date) {
var arr = String(date).split('-');
var year = arr[0];
var month = arr[1];
var year2 = year;
var month2 = parseInt(month) + 1;
if (month2 == 13) {
year2 = parseInt(year2) + 1;
month2 = 1;
}
if (month2 < 10) {
month2 = '0' + month2;
}
var t2 = year2 + '-' + month2;
return t2;
},
search() {
console.log("查询", this.ruleForm);
this.$refs.ruleFormRef.validate((valid) => {
if (valid) {
this.searchSucObj.date = this.ruleForm.date;
this.currentMonth = this.ruleForm.date;
this.currentShowMonth = this.ruleForm.date;
this.activeMonth = "current";
if (this.ruleForm.date == "2022-04") {
this.currentTableData = ["2022-04-01", "2022-04-02", "2022-04-03", "2022-04-04", "2022-04-05", "2022-04-08"];
} else if (this.ruleForm.date == "2022-05") {
this.currentTableData = ["2022-05-08", "2022-05-09", "2022-05-10", "2022-05-11", "2022-05-13", "2022-05-17"];
}
console.log("currentTableData", this.currentTableData);
} else {
return false;
}
});
},
reset(formName) {
this.$refs[formName].resetFields();
this.currentShowMonth = "";
this.activeMonth = "current"
console.log("清除", this.ruleForm);
},
setSchedule() {
this.showSchedule = true;
},
changeScheduleDialog(flag) {
this.showSchedule = flag;
},
monthChange(type) {
this.activeMonth = type;
if (type == "prev") {
this.currentShowMonth = this.getPreMonth(this.currentMonth);
} else if (type == "next") {
this.currentShowMonth = this.getNextMonth(this.currentMonth);
} else {
this.currentShowMonth = this.currentMonth
}
},
},
}
</script>
<style lang="scss" scoped>
.spotCheck-page {
height: calc(100% - 20px);
.content {
&-top {
position: relative;
margin: 10px 0px;
height: 60px;
border-bottom: 1px solid #d9d9d9;
}
&-button {
position: relative;
top: -5px;
margin-bottom: 10px;
}
}
.table-wrap {
.current-time {
font-weight: 900;
font-size: 18px;
}
.btn-wrap {
position: relative;
right: 0;
margin-bottom: 5px;
text-align: right;
/deep/ .el-button + .el-button {
margin-left: 0;
}
.baseBtn {
color: #001e48;
background: #0e91e3;
}
.activeBtn {
background: #dbdbdb;
}
}
}
}
</style>
排班日历组件 calendar.vue
<template>
<div class="calendar">
<table class="calendar-table" :style="{width}">
<thead>
<tr>
<th v-for="(item, i) in weeks" :key="i">{{ item }}</th>
</tr>
</thead>
<tbody class="tbody">
<tr v-for="(dates, i) in res" :key="i" :style="{height: tbodyHeight}">
<td v-for="(item, index) in dates" :key="index"
:class="{notCurMonth: !item.isCurMonth, currentDay: item.date === curDate, selectDay: item.isSelected, rangeSelectd: item.isRangeSelected, weekend: item.isWeekend}"
@click="handleItemClick(item, i, index)">
<span v-if="item.isCurMonth">{{ item.date }}</span>
<slot :data="item" />
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import { getDaysInMonth, handleCrateDate,parseTime} from './calendar.js'
export default {
props: {
userType: {
type: String,
default: "show"
},
canSelect: {
type: Boolean,
default: false
},
currentShowMonth: {
type: String,
default: "",
},
calendarData: {
type: Array,
default() {
return []
}
},
startOfWeek: {
type: Number,
default: 1
},
width: {
type: String,
default: '70%'
},
tbodyHeight: {
type: String,
default: '60px'
}
},
data() {
return {
weeks: ['一', '二', '三', '四', '五', '六', '日'],
days: 0,
curDate: parseTime(new Date().getTime()),
showDays: [],
res: [],
selectedDates: [],
}
},
watch: {
'currentShowMonth': {
immediate: true,
handler(newV) {
if (this.userType == "show") {
if (!this.calendarData.length) return;
let curYear = newV.split('-')[0];
let curMonth = newV.split('-')[1] * 1 - 1;
this.handleGetDays(curYear, curMonth, this.startOfWeek)
this.showDays = this.showDays.map(item => {
this.calendarData.forEach(it => {
if (it == item.date) {
item.isSelected = true;
}
})
return item;
})
} else if (this.userType = "edit") {
console.log("编辑的", newV);
let curYear = newV.split('-')[0];
let curMonth = newV.split('-')[1] * 1 - 1;
this.handleGetDays(curYear, curMonth, this.startOfWeek)
}
}
}
},
created() {
this.weeks.unshift(...this.weeks.splice(this.startOfWeek - 1))
},
mounted() {
},
methods: {
handleGetDays(year, month, startOfWeek) {
this.showDays = []
this.days = getDaysInMonth(year, month);
let firstDayOfWeek = new Date(`${year}-${month + 1}-01`).getDay()
const obj = {
1: '一',
2: '二',
3: '三',
4: '四',
5: '五',
6: '六',
0: '日'
}
const firstDayInCN = obj[firstDayOfWeek]
const index = this.weeks.indexOf(firstDayInCN)
if (firstDayOfWeek === 0) {
firstDayOfWeek = 7
}
let prevDays = handleCrateDate(year, month - 1, 1, index + 1, 'prev')
let rearDays = handleCrateDate(year, month * 1 + 1, 1, 42 - this.days - (index), 'rear')
let curDays = handleCrateDate(year, month, 1, this.days)
this.showDays.unshift(...prevDays)
this.showDays.push(...curDays)
this.showDays.push(...rearDays)
this.res = this.handleFormatDates(this.showDays)
this.res.forEach((item, index) => {
if (Array.from(item).filter(i => i.isCurMonth == false).length == 7) {
this.res.splice(index, 1)
}
})
},
handleFormatDates(arr, size = 7) {
const arr2 = []
for (let i = 0; i < size; i++) {
const temp = arr.slice(i * size, i * size + size)
arr2.push(temp)
}
return arr2
},
handleTableHead(start) {
const sliceDates = this.weeks.splice(start - 1)
this.weeks.unshift(...sliceDates)
},
handleItemClick(item, i, j) {
if (!this.canSelect) return
console.log('单元格点击', item)
this.$nextTick(() => {
this.res[i][j].isSelected = !this.res[i][j].isSelected
if (this.res[i][j].isSelected) {
this.selectedDates.push(this.res[i][j].date)
this.selectedDates = Array.from(new Set(this.selectedDates))
} else {
this.selectedDates.splice(this.selectedDates.indexOf(item.date), 1)
}
console.log('选中的selectedDates22', this.selectedDates)
this.$emit('dateSelected', this.selectedDates)
})
},
}
}
</script>
<style scoped lang="scss">
.calendar {
display: flex;
flex-direction: column;
}
.calendar-table {
table-layout: fixed;
border-collapse: collapse;
transition: 0.3s;
thead tr {
height: 45px;
line-height: 45px;
}
tbody tr {
&:first-child td {
border-top: 1px solid #08a8a0;
}
td {
cursor: pointer;
border-right: 1px solid #08a8a0;
border-bottom: 1px solid #08a8a0;
&:first-child {
border-left: 1px solid #08a8a0;
}
}
}
}
.notCurMonth {
color: #c0c4cc;
}
.currentDay {
background-color: #f8f8de;
}
.selectDay {
color: #fff;
background-color: #409eff;
}
.rangeSelectd {
color: #606266;
background-color: #dee2e9;
}
.weekend {
color: #f73131;
}
</style>
calendar.js
export const getDaysInMonth = (year, month) => {
const day = new Date(year, month + 1, 0).getDate()
return day
}
export const handleCrateDate = (year, month, start, end, type) => {
const arr = []
if (type === 'prev') {
if (start === end) return []
const daysInLastMonth = getDaysInMonth(year, month - 1)
for (let i = daysInLastMonth - end + 2; i <= daysInLastMonth; i++) {
arr.push({
date: parseTime(new Date(year, month - 1, i)),
isCurMonth: false,
isSelected: false,
isRangeSelected: false
})
}
} else if (type === 'rear') {
for (let i = start; i <= end; i++) {
arr.push({
date: parseTime(new Date(year, month + 1, i)),
isCurMonth: false,
isSelected: false,
isRangeSelected: false
})
}
} else {
for (let i = start; i <= end; i++) {
arr.push({
date: parseTime(new Date(year, month, i)),
isCurMonth: true,
isSelected: false,
isRangeSelected: false
})
}
}
return arr
}
export const handleCreateDatePicker = () => {
const years = []
const months = []
for (let i = 1970; i <= 2099; i++) {
years.push({
label: `${i}年`,
value: i
})
}
for (let i = 0; i <= 11; i++) {
months.push({
label: `${i + 1}月`,
value: i
})
}
return {
years,
months
}
}
export function parseTime(time, cFormat) {
if (arguments.length === 0 || !time) {
return null
}
const format = cFormat || '{y}-{m}-{d}'
let date
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string')) {
if ((/^[0-9]+$/.test(time))) {
time = parseInt(time)
} else {
time = time.replace(new RegExp(/-/gm), '/')
}
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000
}
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
const value = formatObj[key]
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
return value.toString().padStart(2, '0')
})
return time_str
}
- 效果