当前位置: 首页 > news >正文

div 封装日历

 案例图:

代码: 

<template><el-dialog :title="dialogTitle" :visible.sync="showCalendar" width="27%" @close="handleClose"><div class="custom-calendar"><!-- 月份切换区域 --><div class="calendar-header"><el-button icon="el-icon-arrow-left" plain @click="prevMonth"></el-button><span>{{ currentYear }}年{{ currentMonth }}月</span><el-button icon="el-icon-arrow-right" plain @click="nextMonth"></el-button></div><!-- 星期标题区域 --><div class="weekdays"><div v-for="(weekday, index) in weekdays" :key="index" class="weekday">{{ weekday }}</div></div><!-- 日期单元格区域 --><div class="days-grid"><!-- 填充空白日期 --><div v-for="(empty, index) in firstDayOffset" :key="'empty-' + index" class="day empty"></div><!-- 遍历展示当前月日期 --><div v-for="(dateObj, index) in visibleDates" :key="index" class="day" :class="{ 'selected': isSelected(dateObj.dateStr) }" @click="toggleSelection(dateObj.dateStr)">{{ dateObj.day }}</div></div><!-- 底部按钮 --><div slot="footer" class="dialog-footer"><el-button @click="cancel">{{ console.log('点击取消按钮,执行 cancel 方法') }}取消</el-button><el-button type="primary" @click="confirm">{{ console.log('点击确认按钮,执行 confirm 方法') }}确定</el-button></div></div></el-dialog>
</template><script>
export default (await import('vue')).defineComponent({name: 'CustomCalendar',// 从父组件接收 dialogTitle,用于动态设置 el-dialog 的 titleprops: {dialogTitle: {type: String,default: '设置工厂日历' },customData: {type: Object,default: () => ({})}},data() {return {getrowData: null, //父组件-选中行的数据showCalendar: false, currentYear: new Date().getFullYear(),  //显示当前的年份currentMonth: new Date().getMonth() + 1, //显示当前的月份selectedDates: [], //存储选中的日期,格式为'YYYY-MM-DD',用于渲染cancelDatas: [], //从接口获取 上一次存入的值(用于-最终生成取消选中的数据,作为参数传递)oldSelectDate: [], //从接口获取 上一次存入的值且过滤出当钱日期之前的日期值,(目的:选择日期时,需要判断是否时上一次选择过的,如果时上一次选择的日期,不可取消选中)weekdays: ['日', '一', '二', '三', '四', '五', '六'] }},computed: {// 计算当前月要显示的日期数据visibleDates() {console.log('执行 visibleDates 计算属性');const dates = [];const firstDay = new Date(this.currentYear, this.currentMonth - 1, 1); const lastDay = new Date(this.currentYear, this.currentMonth, 0).getDate(); for (let i = 1; i <= lastDay; i++) {const date = new Date(this.currentYear, this.currentMonth - 1, i); dates.push({dateStr: this.formatDate(date), day: i });}return dates;},// 计算当前月第一天是星期几,用于填充空白日期firstDayOffset() {console.log('执行 firstDayOffset 计算属性');const firstDay = new Date(this.currentYear, this.currentMonth - 1, 1); return firstDay.getDay(); }},watch: {customData: {handler(newValue, oldVal) {console.log('监听 customData 变化,newValue===', newValue, 'oldVal===', oldVal);if (newValue) {this.selectedDates = newValue.workDate || []; this.getrowData = newValue.rowData; }},deep: true, immediate: true }},methods: {// 弹窗右上角--关闭handleClose() {this.selectedDates = []; this.cancelDatas = []; this.oldSelectDate = []; this.showCalendar = false; },// 格式化日期为 'YYYY - MM - DD' 格式formatDate(date) {const year = date.getFullYear();const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`;},// 判断日期是否已选中isSelected(dateStr) {return this.selectedDates.includes(dateStr);},// 切换日期选中状态toggleSelection(dateStr) {console.log('执行 toggleSelection 方法,切换日期:', dateStr);debugger;if (this.oldSelectDate.includes(dateStr)) {console.log('上次已选择过的值==', dateStr);return; }if (this.isSelected(dateStr)) {// 取消选中console.log('取消选中日期:', dateStr);this.cancelDatas.push(dateStr); this.selectedDates = this.selectedDates.filter((item) => item !== dateStr); } else {// 选中日期console.log('选中日期:', dateStr);this.selectedDates.push(dateStr); }},// 切换到上月prevMonth() {if (this.currentMonth === 1) { this.currentYear--; this.currentMonth = 12; } else {this.currentMonth--; }// 切换月份后清空已选中日期(可根据需求决定是否保留,目前是保留)// this.selectedDates = []; },// 切换到下月nextMonth() {if (this.currentMonth === 12) { this.currentYear++; this.currentMonth = 1; } else {this.currentMonth++; }// 切换月份后清空已选中日期(可根据需求决定是否保留,目前是保留)// this.selectedDates = []; },// 取消按钮 cancel() {this.selectedDates = []; this.cancelDatas = []; this.oldSelectDate = []; this.showCalendar = false; this.$emit('close', false); },// 确定,将值传入父组件 confirm() {console.log('执行 confirm 方法,最终选中的日期:', this.selectedDates);// 过滤 selectedDates,只保留和 oldSelectDate 不相等的日期const filteredSelectedDates = this.selectedDates.filter((date) => !this.oldSelectDate.includes(date)); const result = this.validateWorkDates(filteredSelectedDates); if (result === true) {console.log('所有日期都在允许范围内');} else {return this.$message.warning(result); }// 已选中的值const newSelectedDates = this.selectedDates.map((date) => ({operateType: 'Y', workDate: date }));// 取消选中的数据const newCancelDatas = this.cancelDatas.map((date) => ({operateType: 'N', workDate: date }));const workDates = [...newCancelDatas, ...newSelectedDates]; console.log(workDates, '==进来了==', newCancelDatas); this.getrowData.workDate = workDates; this.$emit('submit', this.getrowData); this.showCalendar = false; },// 验证日期是否符合规则validateWorkDates(workDate) {console.log('执行 validateWorkDates 方法,验证日期:', workDate);const today = new Date(); const currentMonth = today.getMonth(); const currentYear = today.getFullYear(); const currentDay = today.getDate(); // 计算允许的最大月份(当前月+5)const maxMonth = (currentMonth + 5) % 12; const maxYear =currentYear + Math.floor((currentMonth + 5) / 12); // 错误信息收集const pastDayDates = []; const pastDates = []; const futureDates = []; // 遍历检查每个日期workDate.forEach((dateStr) => {const date = new Date(dateStr); if (isNaN(date.getTime())) {return; }const dateYear = date.getFullYear(); const dateMonth = date.getMonth(); const dateDay = date.getDate(); // 1. 判断是否在当前之前if (dateYear < currentYear ||(dateYear === currentYear && dateMonth < currentMonth)) {pastDates.push(dateStr); }// 2. 判断是否当前日期else if (dateYear < currentYear ||(dateYear === currentYear && dateMonth < currentMonth) ||(dateYear === currentYear &&dateMonth === currentMonth &&dateDay < currentDay)) {pastDayDates.push(dateStr); }// 判断是否超过当前月+5个月else if (dateYear > maxYear ||(dateYear === maxYear && dateMonth > maxMonth)) {futureDates.push(dateStr); }});// 生成提示信息let message = ''; if (pastDates.length > 0 || pastDayDates.length > 0) {message += '当前日期之前的日期不可修改设置\n'; }if (futureDates.length > 0) {message += '仅支持设置当前月及往后5个月的日历\n'; }// 如果有错误,返回错误信息;否则返回 truereturn message ? message : true; }}
});
</script><style scoped>
/* 日历整体样式 */
.custom-calendar {width: 100%;border: 1px solid #f9fafc;background-color: #f9fafc;border-radius: 4px;padding: 10px;margin: 0 auto;font-size: 18px;
}
/* 头部样式 */
.calendar-header {display: flex;justify-content: space-between;align-items: center;margin-bottom: 10px;
}
/* 星期标题样式 */
.weekdays {display: flex;margin-bottom: 10px;
}
.weekday {flex: 1;text-align: center;font-weight: bold;
}
/* 日期网格样式 */
.days-grid {display: flex;flex-wrap: wrap;
}
/* 日期单元格基础样式 */
.day {width: 14.28%; height: 63px;line-height: 63px;text-align: center;border: 1px solid #fffbfb;box-sizing: border-box;cursor: pointer;
}
/* 空白日期样式(用于填充月初前面的空白) */
.day.empty {background-color: #f9f9f9;cursor: default;
}
/* 选中日期样式 */
.day.selected {background-color: #409eff;color: white;
}
/* 底部按钮样式 */
.dialog-footer {display: flex;justify-content: flex-end;margin-top: 10px;
}
.dialog-footer button {margin-left: 10px;
}
/**选中日期展示样式*/
.result{margin-top:10px;text-align:center
}</style>

http://www.lryc.cn/news/603392.html

相关文章:

  • C++学习之继承
  • scrapy框架新浪新闻
  • linux中简易云盘系统项目实战:基于 TCP协议的 Socket 通信、json数据交换、MD5文件区别与多用户文件管理实现
  • uniapp 微信小程序 列表点击分享 不同的信息
  • YOLO--目标检测基础
  • 计算机视觉-图像基础处理
  • TailWindCss安装使用教程
  • eudev是什么东西,有什么作用
  • 1768. 交替合并字符串
  • 无线网络优化实践
  • [学习记录]URP流程解析(2)--初始化阶段
  • 虚拟机网络修复
  • 充电宝自燃隐患引发关注:如何确保充电宝安全?
  • 门控激活函数:GLU/GTU/Swish/HSwish/Mish/SwiGLU
  • 机器学习sklearn:泰坦尼克幸存预测(决策树、网格搜索找最佳参数)
  • 【深度学习新浪潮】什么是世界模型?
  • fastApi中的ocr
  • 译 | 介绍PyTabKit:一个试图超越 Scikit-Learn的新机器学习库
  • 如何查询并访问路由器的默认网关(IP地址)?
  • 主应用严格模式下,子应用组件el-date-picker点击无效
  • 【Dify】-进阶14- 用 Dify 搭建法律文档解析助手
  • Vue.js 指令系统完全指南:深入理解 v- 指令
  • 智能图书馆管理系统开发实战系列(一):项目架构设计与技术选型
  • Ubuntu上开通Samba网络共享
  • Ambari 3.0.0 全网首发支持 Ubuntu 22!
  • Kafka——消费者组重平衡全流程解析
  • cpolar 内网穿透 ubuntu 使用石
  • Spark SQL 数组函数合集:array_agg、array_contains、array_sort…详解
  • 【MySQL】从连接数据库开始:JDBC 编程入门指南
  • Vim与VS Code