文章目录
- 需求
- 分析
- 1. 页面渲染
- 2. 获取页面上的开始日期和结束日期
- 3. 总的代码
需求
之前实现过一版用 ElementPlus 的日历组件 Calendar 自定义渲染,是在 Vue3 项目中实现的,现在需求在 Vue2 中也实现一版
分析
1. 页面渲染
<el-calendar v-model="calendar" style="padding-bottom: 0"><template slot="dateCell" slot-scope="{ data }"><div class="calendar-day"><div:class="data.isSelected ? 'is-selected' : ''"style="font-weight: bold">{{ data.day.split("-").slice(1).join("-") }}</div><div class="duty-text">值班人员:<span v-for="item in tableData" :key="item.id"><spanv-if="item.dutyDate == data.day"style="font-weight: bold">{{ item.dutyUser }}</span></span><div><el-buttonsize="mini"type="text"style="color: #1e80ff; margin-right: 10px"@click.stop="handleEdit(data)">编辑</el-button><el-buttonslot="reference"size="mini"type="text"style="color: #1e80ff"@click="handleRemove(data)">删除</el-button></div></div></div></template></el-calendar>
data(){calendar: new Date(),
}
2. 获取页面上的开始日期和结束日期
methods: {// 获取日历显示时间范围getRange (date) {if (date) {} else {this.calendar = new Date()}// 日历第一天let firstDay = ''// 日历最后一天let lastDay = ''// 今天const today = date || new Date()// 上月const m = today.getMonth()// 本月const cm = m + 1// 下月const lm = m + 2 > 12 ? 1 : m + 2// 要显示的本月const currentMonth = cm < 10 ? '0' + cm : cm// 要显示的本本年const currentYear = today.getFullYear()// 要显示的上个月的年份,m = 0 则当前1月,上月则是去年12月const prevYear = m == 0 ? currentYear - 1 : currentYearconst prevMonth = m == 0 ? 12 : m < 10 ? '0' + m : m// 上个月天数const pmd = new Date(prevYear, m, 0).getDate()// 下个月的年份,当前12月,则需要加一年const lastYear = cm + 1 > 12 ? currentYear + 1 : currentYearconst lastMonth = lm < 10 ? '0' + lm : lm// 1号是周几const firstWeek = new Date(today.setDate(1)).getDay()// 如果是周日,则不需要显示上个月if (firstWeek == 0) {firstDay = `${currentYear}-${currentMonth}-01`}// 其他周几,对应用上个月的天数往前推算else {firstDay = `${prevYear}-${prevMonth}-${pmd - (firstWeek - 1)}`}// 这个月天数const currentMonthDate = new Date(currentYear, cm, 0).getDate()// 最后一天是周几const lastWeek = new Date(today.setDate(currentMonthDate)).getDay()// 周六显示当月最后一天if (lastWeek == 6) {lastDay = `${currentYear}-${currentMonth}-${currentMonthDate}`}// 其他周几,对应往后推算else {const day = ['06', '05', '04', '03', '02', '01']lastDay = `${lastYear}-${lastMonth}-${day[lastWeek]}`}this.timeList.startDate = firstDaythis.timeList.endDate = lastDaythis.getPageList()},
}
3. 总的代码
- plan.vue
<template><divv-loading="loading"class="module-container"element-loading-text="加载中...."><!-- {{ timeList.startDate }}-{{ timeList.endDate }} --><MyCard :is-have-left="false"><template slot="right-body"><div class="split-head" style="margin-bottom: -40px"><el-buttontype="primary"size="small"style="margin-left: 20px"@click="handlePlan()">排班计划</el-button></div><div class="split-body"><template><el-calendar v-model="calendar" style="padding-bottom: 0"><template slot="dateCell" slot-scope="{ data }"><div class="calendar-day"><div:class="data.isSelected ? 'is-selected' : ''"style="font-weight: bold">{{ data.day.split("-").slice(1).join("-") }}</div><div class="duty-text">值班人员:<span v-for="item in tableData" :key="item.id"><spanv-if="item.dutyDate == data.day"style="font-weight: bold">{{ item.dutyUser }}</span></span><div><el-buttonsize="mini"type="text"style="color: #1e80ff; margin-right: 10px"@click.stop="handleEdit(data)">编辑</el-button><el-buttonslot="reference"size="mini"type="text"style="color: #1e80ff"@click="handleRemove(data)">删除</el-button></div></div></div></template></el-calendar></template></div></template></MyCard><Edit:scheduling-visible.sync="schedulingVisible":edit_visible.sync="edit_visible":duty-info="dutyInfo"@getRange="getRange"/></div>
</template><script>
import Edit from './child/edit.vue'export default {name: '',components: {Edit},props: {},data () {return {projectId: this.$store.state.project.projectId,structId: this.$store.state.struct.structId,loading: false,visible: false,schedulingVisible: false,calendar: new Date(),editForm: {},tableData: [],timeList: {startDate: '',endDate: ''},edit_visible: false,dutyInfo: {}}},watch: {calendar (n, o) {if (n.getFullYear() !== o.getFullYear() || n.getMonth() !== o.getMonth()) {this.getRange(n)}}},created () {},mounted () { this.getRange(this.calendar) },beforeDestroy () { },methods: {// 获取日历显示时间范围getRange (date) {if (date) {} else {this.calendar = new Date()}// 日历第一天let firstDay = ''// 日历最后一天let lastDay = ''// 今天const today = date || new Date()// 上月const m = today.getMonth()// 本月const cm = m + 1// 下月const lm = m + 2 > 12 ? 1 : m + 2// 要显示的本月const currentMonth = cm < 10 ? '0' + cm : cm// 要显示的本本年const currentYear = today.getFullYear()// 要显示的上个月的年份,m = 0 则当前1月,上月则是去年12月const prevYear = m == 0 ? currentYear - 1 : currentYearconst prevMonth = m == 0 ? 12 : m < 10 ? '0' + m : m// 上个月天数const pmd = new Date(prevYear, m, 0).getDate()// 下个月的年份,当前12月,则需要加一年const lastYear = cm + 1 > 12 ? currentYear + 1 : currentYearconst lastMonth = lm < 10 ? '0' + lm : lm// 1号是周几const firstWeek = new Date(today.setDate(1)).getDay()// 如果是周日,则不需要显示上个月if (firstWeek == 0) {firstDay = `${currentYear}-${currentMonth}-01`}// 其他周几,对应用上个月的天数往前推算else {firstDay = `${prevYear}-${prevMonth}-${pmd - (firstWeek - 1)}`}// 这个月天数const currentMonthDate = new Date(currentYear, cm, 0).getDate()// 最后一天是周几const lastWeek = new Date(today.setDate(currentMonthDate)).getDay()// 周六显示当月最后一天if (lastWeek == 6) {lastDay = `${currentYear}-${currentMonth}-${currentMonthDate}`}// 其他周几,对应往后推算else {const day = ['06', '05', '04', '03', '02', '01']lastDay = `${lastYear}-${lastMonth}-${day[lastWeek]}`}this.timeList.startDate = firstDaythis.timeList.endDate = lastDaythis.getPageList()},handlePlan () {this.schedulingVisible = true},getPageList () {this.loading = trueconst url = `client/${this.projectId}/dh-duty-plan/list?startDate=${this.timeList.startDate}&endDate=${this.timeList.endDate}`this.$axios.get(url).then(res => {if (res.code !== 200) returnthis.tableData = res.data// this.total = res.data.total / 1}).finally(() => {this.loading = false})},handleEdit (row) {const url = `client/${this.projectId}/dh-duty-plan/list?dutyDate=${row.day}`this.$axios.get(url).then((res) => {if (res.code !== 200) returnif (res.data.length) {this.dutyInfo = res.data[0]} else {this.dutyInfo = {id: '',dutyUserId: '',dutyDate: row.day}}}).finally(() => {})this.edit_visible = true},async handleRemove (row) {const result = await this.$confirm(`确定要删除吗?`, {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning',closeOnClickModal: false}).catch((err) => err)if (result === 'confirm') {const url = `client/${this.projectId}/dh-duty-plan/list?dutyDate=${row.day}`this.$axios.get(url).then((res) => {if (res.code !== 200) returnif (res.data.length) {const info = res.data[0]this.$axios.post(`client/${this.projectId}/dh-duty-plan/delete`, { id: info.id }).then(response => {if (response.code !== 200) returnthis.getPageList()})} else {this.$message('该日期下未查询到值班人员')}}).finally(() => {// this.getPageList()})} else {// this.$message('取消了删除')}},}
}
</script><style lang="scss" scoped>
.module-container {// padding-top: 15px;padding-left: 22px;height: 100%;// ::v-deep .card-body {// background: #f6f9ff !important;// display: flex;// padding: 0px;// }.split-head {display: flex;justify-content: center;flex-direction: row;}
}
.duty-text {text-align: center;// color: #939fb6;font-size: large;line-height: 25px;padding-top: 5px;
}.is-selected {color: #1989fa;font-weight: bold;
}:deep(.el-calendar-table thead th) {font-weight: bold;
}
</style>
- 弹窗 edit.vue
<template><div class="container"><el-dialog:title="'排班计划'":visible="schedulingVisible"width="30%"top="20vh":close-on-click-modal="false":modal-append-to-body="false"custom-class="alarm-strategy"@update:visible="(bol) => $emit('update:schedulingVisible', bol)"><div><el-buttonv-show="activeName === '单人排班'"type="text"icon="el-icon-plus"class="add-one-btn"@click="handleaddNode">新增一条</el-button><el-tabs v-model="activeName" @tab-click="handleClick"><el-tab-pane label="单人排班" name="单人排班"><el-table :data="singleForm" style="width: 100%" height="250"><el-table-column label="日期" align="center"><template slot-scope="scope"><el-date-pickerv-model="scope.row.dutyDate"size="small"type="date"value-format="yyyy-MM-dd"placeholder="选择日期"style="width: 70%"/></template></el-table-column><el-table-column label="人员" align="center"><template slot-scope="scope"><el-selectv-model="scope.row.dutyUserId"size="small"clearableplaceholder="请选择"style="width: 70%"><el-optionv-for="item in person_options":key="item.id":label="item.name":value="item.id"/></el-select></template></el-table-column><el-table-column v-if="singleForm.length > 1" label="操作"><template slot-scope="scope"><div><el-buttontype="text"@click="handleremoveNode(scope.$index)">移除</el-button></div></template></el-table-column></el-table></el-tab-pane><el-tab-pane label="批量排班" name="批量排班"><div class="time-range batch-box"><span>日期范围</span><el-date-pickerv-model="multiForm.time"size="small"type="daterange"align="right"unlink-panelsrange-separator="至"start-placeholder="开始日期"end-placeholder="结束日期":picker-options="pickerOptions"value-format="yyyy-MM-dd"/></div><div class="personnel batch-box"><span>人员添加</span><el-selectv-model="multiForm.dutyUserIdList"size="small"multiplecollapse-tagsclearableplaceholder="请选择"><el-optionv-for="item in person_options":key="item.id":label="item.name":value="item.id"/></el-select></div></el-tab-pane></el-tabs></div><span slot="footer" class="dialog-footer"><el-button @click="$emit('update:schedulingVisible', false)">取 消</el-button><el-button type="primary" :loading="loading" @click="handleOk">确 定</el-button></span></el-dialog><el-dialog:title="'编辑'":visible="edit_visible"width="30%"top="20vh":close-on-click-modal="false":modal-append-to-body="false"custom-class="alarm-strategy"@update:visible="handleEditOk"><div class="time-range batch-box"><span>值班人</span><el-selectv-model="dutyInfo.dutyUserId"size="small"placeholder="请选择"><el-optionv-for="item in person_options":key="item.id":label="item.name":value="item.id"/></el-select><!-- {{ dutyInfo }} --></div><span slot="footer" class="dialog-footer"><el-button @click="$emit('update:edit_visible', false)">取 消</el-button><el-button type="primary" @click="handleEditOk">确 定</el-button></span></el-dialog></div>
</template><script>
export default {name: '',components: {},props: {schedulingVisible: {type: Boolean,default: false},edit_visible: {type: Boolean,default: false},dutyInfo: {type: Object,default: () => { }}},data () {return {projectId: this.$store.state.project.projectId,structId: this.$store.state.struct.structId,loading: false,activeName: '单人排班',value: '',person_options: [],value1: '',pickerOptions: {shortcuts: [{text: '最近一周',onClick (picker) {const end = new Date()const start = new Date()start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)picker.$emit('pick', [start, end])}},{text: '最近一个月',onClick (picker) {const end = new Date()const start = new Date()start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)picker.$emit('pick', [start, end])}},{text: '最近三个月',onClick (picker) {const end = new Date()const start = new Date()start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)picker.$emit('pick', [start, end])}}]},value2: '',singleForm: [{ dutyDate: '', dutyUserId: '' }],multiForm: {time: [],dutyUserIdList: []}}},created () {},mounted () {this.init()},beforeDestroy () { },methods: {handleClick (tab, event) {if (tab.label == '单人排班') {this.multiForm = {}} else {this.singleForm = [{ dutyDate: '', dutyUserId: '' }]}},handleremoveNode (data) {this.singleForm.splice(data, 1)},handleaddNode () {this.singleForm.push({dutyDate: null, // 日期dutyUserId: null // 人员})},// 提交handleOk () {if (this.activeName === '单人排班') {const flag = this.singleForm.some(item =>item.dutyDate == null || item.dutyUserId == null || item.dutyDate == undefined || item.dutyUserId == undefined || item.dutyDate == '' || item.dutyUserId == '')if (!flag) {const url = `client/${this.projectId}/dh-duty-plan/danGeAdd`this.$axios.post(url, { dhDutyPlanList: this.singleForm }).then((res) => {if (res.code === 200) {this.$emit('getRange')this.$emit('update:schedulingVisible', false)}}).finally(() => {this.handleClick('单人排班')})} else {return this.$message.warning('请完整填写表单')}} else {if (this.multiForm.time.length && this.multiForm.dutyUserIdList.length) {const tempData = {startDate: this.multiForm.time[0],endDate: this.multiForm.time[1],dutyUserIdList: this.multiForm.dutyUserIdList}const url = `client/${this.projectId}/dh-duty-plan/batchAdd`this.$axios.post(url, tempData).then((res) => {if (res.code === 200) {this.$emit('getRange')this.$emit('update:schedulingVisible', false)}}).finally(() => {this.handleClick('单人排班')})} else {return this.$message.warning('请完整填写表单')}}},getPersonList () {const url = `client/${this.projectId}/dh-duty-user/list`this.$axios.get(url).then(res => {if (res.code !== 200) returnthis.person_options = res.data}).finally(() => {})},handleEditOk () {if (this.dutyInfo.dutyUserId) {if (this.dutyInfo.id) {const tempData = {id: this.dutyInfo.id,dutyUserId: this.dutyInfo.dutyUserId,dutyDate: this.dutyInfo.dutyDate}const url = `client/${this.projectId}/dh-duty-plan/update`this.$axios.post(url, tempData).then((res) => {if (res.code !== 200) returnthis.$emit('getRange')this.$emit('update:edit_visible', false)}).finally(() => {})} else {const url = `client/${this.projectId}/dh-duty-plan/danGeAdd`this.$axios.post(url, { dhDutyPlanList: [{ dutyDate: this.dutyInfo.dutyDate, dutyUserId: this.dutyInfo.dutyUserId }] }).then((res) => {if (res.code === 200) {this.$emit('getRange')this.$emit('update:edit_visible', false)}}).finally(() => {})}} else {return this.$message.warning('请完整填写表单')}},init () {this.getPersonList()}}
}
</script><style lang="scss" scoped>
::v-deep .el-dialog__body {padding: 0 15px;padding-right: 0px;position: relative;margin-bottom: 30px;overflow: hidden;
}
.add-one-btn {position: absolute;right: 20px;z-index: 22;
}
.single-person-box {padding-right: 20px;max-height: 360px;overflow: auto;.limit {display: flex;margin-bottom: 12px;> div {flex: 1;margin-left: 10px;}.flex {display: flex;align-items: center;.el-date-editor {width: 160px;}.el-select {width: 160px;}}.time {margin-right: 10px;}.staff {}span {margin-right: 10px;}}
}
.batch-box {display: flex;align-items: center;width: 70%;margin-left: 10%;margin-top: 15px;span {margin-right: 10px;}.el-select,.el-date-editor {flex: 1;}
}
</style>