父组件
<template>
<div class="dateSet">
<div class="tabs-list">
<el-tabs type="card" v-model="tabPosition" :before-leave="confirmLeave">
<el-tab-pane
v-for="(year, index) in tabs"
:label="year.name"
:name="year.name"
></el-tab-pane>
</el-tabs>
</div>
<div class="month" v-loading="!showMonth">
<div class="tips">
<div class="box"></div>
<div class="title">红色块表示节假日</div>
<el-button class="holiday" @click="selectHoliday"
>一健选择周六日</el-button
>
</div>
<div class="content" v-for="(ym, index) in yearMonth">
<the-month
v-if="showMonth"
ref="month"
:yearMonth="ym"
:key="index"
:holidaySetting="holidaySetting"
>
</the-month>
</div>
</div>
<div class="btn-list">
<el-button class="save" type="primary" @click="save">保存</el-button>
</div>
</div>
</template>
<script>
import { holidaySettingService_addHolidaySetting } from "apis/wtzg/business/services/HolidaySettingServiceAPI";
import { busiHolidaySetting_fetchAll } from "apis/wtzg/business/publicschema/BusiHolidaySettingAPI";
export default {
name: "dateSet",
data() {
return {
yearMonth: [],
tabs: [],
currYear: "",
tabPosition: "",
holidaySetting: [],
showMonth: false,
isSelect: true
};
},
watch: {
currYear(val) {
this.setYearMonth();
}
},
computed: {
isPrimary() {
return isActive => {
return isActive ? "primary" : "default";
};
},
isActive(item) {
return item.active;
}
},
mounted() {
this.initYearMonth();
this.getHolidaySetting();
},
methods: {
// 获取节假日
async getHolidaySetting() {
this.showMonth = false;
const { code, content } = await this.$to(busiHolidaySetting_fetchAll());
if (code == 200) {
this.holidaySetting = content;
this.showMonth = true;
}
},
// 保存节假日
async save() {
let params = this.getParams();
if (!params.length) return this.$showMessage("请选择非工作日", "warning");
this.showMonth = false;
const { code } = await this.$to(
holidaySettingService_addHolidaySetting(params)
);
if (code == 200) {
this.$showMessage("保存成功");
this.getHolidaySetting();
this.showMonth = true;
}
},
selectHoliday() {
let month = this.$refs.month;
let refLeg = month.length;
for (let i = 0; i < refLeg; i++) {
month[i].todayArr.forEach(item => {
if (["00", "06"].includes(item.day)) {
item.isActive = this.isSelect;
}
});
}
this.isSelect = !this.isSelect;
},
getParams() {
let month = this.$refs.month;
let refLeg = month.length;
let arr = [],
params = [];
for (let i = 0; i < refLeg; i++) {
arr.push(month[i].getNonworkdays());
}
arr = arr.flat();
arr.forEach(date => {
params.push({
date,
year: this.currYear.toString()
});
});
return params;
},
initYearMonth() {
let today = new Date();
this.currYear = today.getFullYear();
this.settabs();
},
settabs() {
this.tabs = [];
for (let i = 0; i < 2; i++) {
this.tabs.push({
name: parseInt(this.currYear) + i + "年"
});
}
this.tabPosition = this.tabs[0].name;
},
setYearMonth() {
this.yearMonth = [];
for (let i = 1; i <= 12; i++) {
this.yearMonth.push(`${this.currYear}-${i}`);
}
},
async confirmLeave(active, old) {
if (!old) return;
await this.$confirm("请确认您已保存当前页面数据, 是否继续跳转?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.currYear = parseInt(active);
return true;
})
.catch(() => {
return reject();
});
}
}
};
</script>
<style lang="less" scoped>
.dateSet {
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding-bottom: 50px;
background: white;
.tabs-list {
display: flex;
justify-content: center;
padding: 20px 0 10px 0;
}
.month {
position: relative;
display: flex;
justify-content: space-around;
flex-wrap: wrap;
width: 100%;
max-width: 1100px;
.tips {
display: flex;
justify-content: flex-end;
align-items: center;
margin-right: 30px;
margin-bottom: 20px;
width: 100%;
.box {
width: 20px;
height: 20px;
background: #ed646f;
margin-right: 10px;
}
.title {
font-size: 14px;
}
.holiday {
margin-left: 10px;
}
}
.content {
}
}
.btn-list {
display: flex;
justify-content: flex-end;
position: sticky;
bottom: 0;
left: 0;
right: 0;
width: 100%;
padding: 20px 0;
background: rgba(255, 255, 255, 0.6);
.save {
margin-right: 20px;
}
}
}
</style>
子组件
<template>
<div class="theMonth">
<div class="month">{{ month }}</div>
<div class="week">
<div
class="week-item"
v-for="(week, index) in weekArr"
:key="index"
:class="{ redColor: isRed(week) }"
>
{{ week }}
</div>
</div>
<div class="day">
<div
class="day-item"
v-for="(today, index) in todayArr"
:title="getYMD(today)"
:class="[
{
redColor: isRed(today.day),
active: today.isActive,
text: hasText(today.date)
}
]"
:key="index"
@click="selectToday(today.date)"
>
{{ today.date }}
</div>
</div>
</div>
</template>
<script>
import { month } from "@/common/localDict";
export default {
name: "theMonth",
props: {
yearMonth: {
type: String,
default: ""
},
holidaySetting: {
type: Array,
default: () => {
return [];
}
}
},
data() {
return {
todayArr: [],
newTodayArr: [],
weekArr: ["一", "二", "三", "四", "五", "六", "日"],
nonworkdays: []
};
},
watch: {
yearMonth() {
this.initDate();
},
holidaySetting() {
this.initDate();
}
},
computed: {
month() {
let m = this.yearMonth.split("-")[1].padStart(2, "0");
return month[m];
},
isRed() {
return week => {
return ["六", "日", "6", "0"].includes(week.toString());
};
},
getYMD() {
return today => {
return `${today.year}年${today.month}月${today.date}日`;
};
},
hasText() {
return day => {
return day != "";
};
}
},
mounted() {
this.initDate();
},
methods: {
// 选择非工作日
selectToday(date) {
if (!date) return;
this.nonworkdays = [];
this.todayArr.forEach(item => {
if (item.date === date) item.isActive = !item.isActive;
});
},
initDate() {
// 获取当月的日期数量
let currMonthMax = this.getCountDays();
// 将当前年、月、日、周 存储于数据
this.getTodayArr(currMonthMax);
// 计算需要补充的空格(即第几天开始)
this.unshiftEmpty();
// 回显选择数据
this.recoverSelectData();
},
getTodayArr(currMonthMax) {
this.todayArr = [];
for (let i = 1; i < currMonthMax + 1; i++) {
let today = new Date(`${this.yearMonth}-${i}`),
isActive = ["0", "6"].includes(today.getDay().toString()),
date = this.setPadStart(today.getDate()),
day = this.setPadStart(today.getDay()),
month = this.setPadStart(today.getMonth() + 1),
year = today.getFullYear(),
ymdd = {
year,
month,
date,
day,
ymd: `${year}-${month}-${date}`,
isActive
};
this.todayArr.push(ymdd);
}
},
setPadStart(today) {
return today.toString().padStart(2, "0");
},
unshiftEmpty() {
let day = this.todayArr[0].day == 0 ? 7 : this.todayArr[0].day;
let emptyLength = 7 - (7 - parseInt(day) + 1);
for (let i = 0; i < emptyLength; i++) {
this.todayArr.unshift({ year: "", month: "", date: "", day: "" });
}
},
recoverSelectData() {
if (!this.holidaySetting.length) return;
let holidayArr = this.holidaySetting.map(item => {
return item.date.split(" ")[0];
});
this.todayArr.forEach(item => (item.isActive = false));
this.todayArr.forEach(item => {
if (holidayArr.includes(item.ymd)) {
item.isActive = true;
}
});
},
getNonworkdays() {
this.todayArr.forEach(item => {
item.isActive
? this.nonworkdays.push(
`${item.year}-${item.month}-${item.date} 00:00:00`
)
: "";
});
return this.nonworkdays;
},
getCountDays() {
var curDate = new Date(this.yearMonth);
var curMonth = curDate.getMonth();
curDate.setMonth(curMonth + 1);
curDate.setDate(0);
return curDate.getDate();
}
}
};
</script>
<style lang="less" scoped>
@redColor: #ed646f;
.theMonth {
width: 218px !important;
height: 260px;
display: flex;
flex-direction: column;
color: #333;
font-size: 13px;
padding: 0 10px;
.month {
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
font-weight: bold;
padding: 8px 0;
}
.week {
.week-item {
float: left;
width: 15px;
text-align: center;
padding: 5px 6px;
margin-right: 4px;
background: #dbdbdc;
}
}
.day {
.day-item {
float: left;
width: 15px;
padding: 5px 6px;
text-align: center;
margin-right: 4px;
margin-top: 4px;
cursor: pointer;
user-select: none;
}
.text:hover {
color: #fff;
background: #999;
}
.text:active {
color: #666;
}
.active {
color: #fff;
background: @redColor !important;
}
}
.redColor {
color: @redColor;
}
}
</style>