封装日期选择组件
This commit is contained in:
		
							parent
							
								
									2cbcc62ec2
								
							
						
					
					
						commit
						ddd5ab1ed5
					
				|  | @ -0,0 +1,661 @@ | ||||||
|  | <template> | ||||||
|  |     <div class="diy-calendar-wrapper"> | ||||||
|  |         <div class="calendar-header"> | ||||||
|  |             <!-- 左箭头 --> | ||||||
|  |             <div class="left-arrow" @click="jumpMonth(-1)"> | ||||||
|  |                 <svg width="30" height="30"> | ||||||
|  |                     <path d="M 19,9 L 11,15 18,21" stroke="rgba(95,147,238,0.9)" fill="none" stroke-width="2" | ||||||
|  |                         stroke-linecap="round" stroke-linejoin="round" /> | ||||||
|  |                 </svg> | ||||||
|  |             </div> | ||||||
|  |             <!-- 年月标题 --> | ||||||
|  |             <div class="center-title">{{ targetDateFormat }}</div> | ||||||
|  |             <!-- 右箭头 --> | ||||||
|  |             <div class="right-arrow" @click="jumpMonth(1)"> | ||||||
|  |                 <svg width="30" height="30"> | ||||||
|  |                     <path d="M 11,9 L 18,15 11,21" stroke="rgba(95,147,238,0.9)" fill="none" stroke-width="2" | ||||||
|  |                         stroke-linecap="round" stroke-linejoin="round" /> | ||||||
|  |                 </svg> | ||||||
|  |             </div> | ||||||
|  |         </div> | ||||||
|  |         <!-- 日历主体 --> | ||||||
|  |         <table class="diy-calendar-table"> | ||||||
|  |             <!-- 星期栏 --> | ||||||
|  |             <thead> | ||||||
|  |                 <tr class="table-header-row"> | ||||||
|  |                     <th v-for="day in dayNameList" :key="day.chineseShortName" class="table-header"> | ||||||
|  |                         {{ day.chineseFullName }} | ||||||
|  |                     </th> | ||||||
|  |                 </tr> | ||||||
|  |             </thead> | ||||||
|  |             <!-- 日期部分 --> | ||||||
|  |             <tbody> | ||||||
|  |                 <tr class="table-body-row" v-for="(row, index) in calendarData" :key="index"> | ||||||
|  |                     <td v-for="col in row" class="table-data" :data-date="col.dateNumber" | ||||||
|  |                         :key="`${col.dateObj.getMonth()}-${col.dateNumber}`"> | ||||||
|  |                         <div class="td-content-box"> | ||||||
|  |                             <div class="content-border" :class="{ selected: isSelectedDate(col) }" | ||||||
|  |                                 @click="checkoutTargetDate(col)"> | ||||||
|  |                                 <div class="date-number" :class="{ current: isCurrentMonth(col) }"> | ||||||
|  |                                     {{ col.dateNumber }} | ||||||
|  |                                 </div> | ||||||
|  |                                 <!--<div class="the-tradition-chinese-calendar"> | ||||||
|  |                     {{ col.dateObj }} | ||||||
|  |                   </div>--> | ||||||
|  |                             </div> | ||||||
|  |                         </div> | ||||||
|  |                     </td> | ||||||
|  |                 </tr> | ||||||
|  |             </tbody> | ||||||
|  |         </table> | ||||||
|  |     </div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script setup> | ||||||
|  | import { reactive, ref, computed, watch } from "vue"; | ||||||
|  | import dayjs from "dayjs" | ||||||
|  | const props = defineProps({ | ||||||
|  |     modelValue: Date, | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | const emits = defineEmits(["update:modelValue"]); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 最小年份 | ||||||
|  |  */ | ||||||
|  | const MIN_YEAR = 1900; | ||||||
|  | /** | ||||||
|  |  * 最大年份 | ||||||
|  |  */ | ||||||
|  | const MAX_YEAR = 9999; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 目标日期 | ||||||
|  |  * @type {Ref<Date>} | ||||||
|  |  */ | ||||||
|  | const targetDate = ref(props.modelValue); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 有关月度的名称列表 | ||||||
|  |  */ | ||||||
|  | const monthNameList = { | ||||||
|  |     chineseFullName: [ | ||||||
|  |         "一月", | ||||||
|  |         "二月", | ||||||
|  |         "三月", | ||||||
|  |         "四月", | ||||||
|  |         "五月", | ||||||
|  |         "六月", | ||||||
|  |         "七月", | ||||||
|  |         "八月", | ||||||
|  |         "九月", | ||||||
|  |         "十月", | ||||||
|  |         "十一月", | ||||||
|  |         "十二月", | ||||||
|  |     ], | ||||||
|  |     fullName: [ | ||||||
|  |         "January", | ||||||
|  |         "February", | ||||||
|  |         "March", | ||||||
|  |         "April", | ||||||
|  |         "May", | ||||||
|  |         "June", | ||||||
|  |         "July", | ||||||
|  |         "August", | ||||||
|  |         "September", | ||||||
|  |         "October", | ||||||
|  |         "November", | ||||||
|  |         "December", | ||||||
|  |     ], | ||||||
|  |     mmm: [ | ||||||
|  |         "Jan", | ||||||
|  |         "Feb", | ||||||
|  |         "Mar", | ||||||
|  |         "Apr", | ||||||
|  |         "May", | ||||||
|  |         "Jun", | ||||||
|  |         "Jul", | ||||||
|  |         "Aug", | ||||||
|  |         "Sep", | ||||||
|  |         "Oct", | ||||||
|  |         "Nov", | ||||||
|  |         "Dec", | ||||||
|  |     ], | ||||||
|  | }; | ||||||
|  | /** | ||||||
|  |  * 有关周几的名称列表 | ||||||
|  |  */ | ||||||
|  | const dayNameList = [ | ||||||
|  |     { | ||||||
|  |         chineseFullName: "周日", | ||||||
|  |         chineseShortName: "日", | ||||||
|  |         fullName: "Sunday", | ||||||
|  |         shortName: "Sun", | ||||||
|  |         dayNumber: 0, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         chineseFullName: "周一", | ||||||
|  |         chineseShortName: "一", | ||||||
|  |         fullName: "Monday", | ||||||
|  |         shortName: "Mon", | ||||||
|  |         dayNumber: 1, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         chineseFullName: "周二", | ||||||
|  |         chineseShortName: "二", | ||||||
|  |         fullName: "Tuesday", | ||||||
|  |         shortName: "Tue", | ||||||
|  |         dayNumber: 2, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         chineseFullName: "周三", | ||||||
|  |         chineseShortName: "三", | ||||||
|  |         fullName: "Wednesday", | ||||||
|  |         shortName: "Wed", | ||||||
|  |         dayNumber: 3, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         chineseFullName: "周四", | ||||||
|  |         chineseShortName: "四", | ||||||
|  |         fullName: "Thursday", | ||||||
|  |         shortName: "Thu", | ||||||
|  |         dayNumber: 4, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         chineseFullName: "周五", | ||||||
|  |         chineseShortName: "五", | ||||||
|  |         fullName: "Friday", | ||||||
|  |         shortName: "Fri", | ||||||
|  |         dayNumber: 5, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         chineseFullName: "周六", | ||||||
|  |         chineseShortName: "六", | ||||||
|  |         fullName: "Saturday", | ||||||
|  |         shortName: "Sat", | ||||||
|  |         dayNumber: 6, | ||||||
|  |     }, | ||||||
|  | ]; | ||||||
|  | /** | ||||||
|  |  * 今日 | ||||||
|  |  */ | ||||||
|  | const today = new Date(); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 日历的各项属性 | ||||||
|  |  */ | ||||||
|  | const calendarProps = reactive({ | ||||||
|  |     target: { | ||||||
|  |         year: null, | ||||||
|  |         month: null, | ||||||
|  |         date: null, | ||||||
|  |         day: null, | ||||||
|  |         monthShortName: null, | ||||||
|  |         monthFullName: null, | ||||||
|  |         monthChineseFullName: null, | ||||||
|  |         firstDay: null, | ||||||
|  |         firstDayIndex: null, | ||||||
|  |         totalDays: null, | ||||||
|  |     }, | ||||||
|  |     previous: { | ||||||
|  |         totalDays: null, | ||||||
|  |     }, | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 用于展现的日历数据 | ||||||
|  |  */ | ||||||
|  | const calendarData = ref([]); | ||||||
|  | 
 | ||||||
|  | initCalendar(); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 初始化日历数据 | ||||||
|  |  */ | ||||||
|  | function initCalendar() { | ||||||
|  |     setCalendarProps(); | ||||||
|  |     setCalendarData(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 设置日历的各个属性,比如当前年月日,本月一共多少天,上个月一共多少天等等 | ||||||
|  |  */ | ||||||
|  | function setCalendarProps() { | ||||||
|  |     if (!targetDate.value) { | ||||||
|  |         targetDate.value = today; | ||||||
|  |     } | ||||||
|  |     // 获取目标日期的年月日星期几数据 | ||||||
|  |     calendarProps.target.year = targetDate.value.getFullYear(); | ||||||
|  |     calendarProps.target.month = targetDate.value.getMonth(); | ||||||
|  |     calendarProps.target.date = targetDate.value.getDate(); | ||||||
|  |     calendarProps.target.day = targetDate.value.getDay(); | ||||||
|  | 
 | ||||||
|  |     if ( | ||||||
|  |         calendarProps.target.year < MIN_YEAR || | ||||||
|  |         calendarProps.target.year > MAX_YEAR | ||||||
|  |     ) { | ||||||
|  |         console.error("无效的年份,请检查传入的数据是否是正常"); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // 获取到目标日期的月份【中文】名称 | ||||||
|  |     let dateString; | ||||||
|  |     dateString = targetDate.value.toString().split(" "); | ||||||
|  |     calendarProps.target.monthShortName = dateString[1]; | ||||||
|  |     calendarProps.target.monthFullName = | ||||||
|  |         monthNameList.fullName[calendarProps.target.month]; | ||||||
|  |     calendarProps.target.monthChineseFullName = | ||||||
|  |         monthNameList.chineseFullName[calendarProps.target.month]; | ||||||
|  |     // 获取目标月份的第一天是星期几,和在星期几中的索引值 | ||||||
|  |     const targetMonthFirstDay = new Date( | ||||||
|  |         calendarProps.target.year, | ||||||
|  |         calendarProps.target.month, | ||||||
|  |         1 | ||||||
|  |     ); | ||||||
|  |     calendarProps.target.firstDay = targetMonthFirstDay.getDay(); | ||||||
|  |     calendarProps.target.firstDayIndex = dayNameList.findIndex( | ||||||
|  |         (day) => day.dayNumber === calendarProps.target.firstDay | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     // 获取目标月份总共多少天 | ||||||
|  |     const targetMonthLastDay = new Date( | ||||||
|  |         calendarProps.target.year, | ||||||
|  |         calendarProps.target.month + 1, | ||||||
|  |         0 | ||||||
|  |     ); | ||||||
|  |     calendarProps.target.totalDays = targetMonthLastDay.getDate(); | ||||||
|  | 
 | ||||||
|  |     // 获取目标月份的上个月总共多少天 | ||||||
|  |     const previousMonth = new Date( | ||||||
|  |         calendarProps.target.year, | ||||||
|  |         calendarProps.target.month, | ||||||
|  |         0 | ||||||
|  |     ); | ||||||
|  |     calendarProps.previous.totalDays = previousMonth.getDate(); | ||||||
|  | 
 | ||||||
|  |     console.log('calendarProps:', calendarProps); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 生成日历的数据 | ||||||
|  |  */ | ||||||
|  | function setCalendarData() { | ||||||
|  |     let i; | ||||||
|  |     let date = 1; | ||||||
|  |     const originData = []; | ||||||
|  |     const firstRow = []; | ||||||
|  |     // 设置第一行数据 | ||||||
|  |     for (i = 0; i <= 6; i++) { | ||||||
|  |         // 设置目标月份之前月份的日期数据 | ||||||
|  |         if (i < calendarProps.target.firstDayIndex) { | ||||||
|  |             const previousDate = | ||||||
|  |                 calendarProps.previous.totalDays - | ||||||
|  |                 calendarProps.target.firstDayIndex + | ||||||
|  |                 (i + 1); | ||||||
|  |             firstRow.push({ | ||||||
|  |                 dateObj: new Date( | ||||||
|  |                     calendarProps.target.year, | ||||||
|  |                     calendarProps.target.month - 1, | ||||||
|  |                     previousDate | ||||||
|  |                 ), | ||||||
|  |                 dateNumber: previousDate, | ||||||
|  |                 dateType: "previous", | ||||||
|  |             }); | ||||||
|  |         } else { | ||||||
|  |             // 设置目标月份当月的日期数据 | ||||||
|  |             firstRow.push({ | ||||||
|  |                 dateObj: new Date( | ||||||
|  |                     calendarProps.target.year, | ||||||
|  |                     calendarProps.target.month, | ||||||
|  |                     date | ||||||
|  |                 ), | ||||||
|  |                 dateNumber: date, | ||||||
|  |                 dateType: "current", | ||||||
|  |             }); | ||||||
|  |             date++; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     originData.push(firstRow); | ||||||
|  |     // 设置后面五行的数据 | ||||||
|  |     for (let j = 0; j <= 4; j++) { | ||||||
|  |         const rowData = []; | ||||||
|  |         for (let k = 0; k <= 6; k++) { | ||||||
|  |             // 设置目标月份剩下的日期数据 | ||||||
|  |             if (date <= calendarProps.target.totalDays) { | ||||||
|  |                 rowData.push({ | ||||||
|  |                     dateObj: new Date( | ||||||
|  |                         calendarProps.target.year, | ||||||
|  |                         calendarProps.target.month, | ||||||
|  |                         date | ||||||
|  |                     ), | ||||||
|  |                     dateNumber: date, | ||||||
|  |                     dateType: "current", | ||||||
|  |                 }); | ||||||
|  |             } else { | ||||||
|  |                 // 设置目标月份下个月的日期数据 | ||||||
|  |                 const nextDate = date - calendarProps.target.totalDays; | ||||||
|  |                 rowData.push({ | ||||||
|  |                     dateObj: new Date( | ||||||
|  |                         calendarProps.target.year, | ||||||
|  |                         calendarProps.target.month + 1, | ||||||
|  |                         nextDate | ||||||
|  |                     ), | ||||||
|  |                     dateNumber: nextDate, | ||||||
|  |                     dateType: "next", | ||||||
|  |                 }); | ||||||
|  |             } | ||||||
|  |             date++; | ||||||
|  |         } | ||||||
|  |         originData.push(rowData); | ||||||
|  |     } | ||||||
|  |     calendarData.value = originData; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 是否是被选中的日期 | ||||||
|  |  * @param col 日期数据 | ||||||
|  |  */ | ||||||
|  | function isSelectedDate(col) { | ||||||
|  |     const colDateObj = col.dateObj; | ||||||
|  |     const colYear = colDateObj.getFullYear(); | ||||||
|  |     const colMonth = colDateObj.getMonth(); | ||||||
|  |     const colDate = colDateObj.getDate(); | ||||||
|  | 
 | ||||||
|  |     const targetDateYear = targetDate.value.getFullYear(); | ||||||
|  |     const targetDateMonth = targetDate.value.getMonth(); | ||||||
|  |     const targetDateDate = targetDate.value.getDate(); | ||||||
|  | 
 | ||||||
|  |     if ( | ||||||
|  |         colYear === targetDateYear && | ||||||
|  |         colMonth === targetDateMonth && | ||||||
|  |         colDate === targetDateDate | ||||||
|  |     ) { | ||||||
|  |         return true; | ||||||
|  |     } else { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 是否是当前月份 | ||||||
|  |  * @param col 日期数据 | ||||||
|  |  */ | ||||||
|  | function isCurrentMonth(col) { | ||||||
|  |     if (col.dateType !== "current") { | ||||||
|  |         return false; | ||||||
|  |     } else { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 切换目标日期 | ||||||
|  |  * @param col 日期数据 | ||||||
|  |  */ | ||||||
|  | function checkoutTargetDate(col) { | ||||||
|  |     const currentDate = col.dateObj; | ||||||
|  |     const oldDate = targetDate.value; | ||||||
|  |     // 如果本次点击的日期是当前选中的日期,则停止执行 | ||||||
|  |     if (currentDate.getTime() === oldDate.getTime()) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     if (col.dateType === "current") { | ||||||
|  |         targetDate.value = col.dateObj; | ||||||
|  |         setCalendarProps(); | ||||||
|  |     } else { | ||||||
|  |         targetDate.value = col.dateObj; | ||||||
|  |         initCalendar(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 跳转月份 | ||||||
|  |  * @param flag 跳转数字标识,+1,就是增加一个月,-1就是减少一个月 | ||||||
|  |  */ | ||||||
|  | function jumpMonth(flag) { | ||||||
|  |     let targetMonthNumber = calendarProps.target.month; | ||||||
|  |     let targetYear = calendarProps.target.year; | ||||||
|  |     targetDate.value = calendarProps.target.date; | ||||||
|  |     targetMonthNumber += flag; | ||||||
|  |     console.log('targetMonthNumber', calendarProps.target.month, targetMonthNumber); | ||||||
|  |     if (targetMonthNumber > 11) { | ||||||
|  |         targetYear += 1; | ||||||
|  |         targetMonthNumber = 0; | ||||||
|  |     } else if (targetMonthNumber < 0) { | ||||||
|  |         targetYear -= 1; | ||||||
|  |         targetMonthNumber = 11; | ||||||
|  |     } | ||||||
|  |     targetDate.value = new Date(targetYear, targetMonthNumber, targetDate.value); | ||||||
|  |     initCalendar(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const targetDateFormat = computed(() => { | ||||||
|  |     const monthNumber = targetDate.value.getMonth() + 1 | ||||||
|  |     let monthString = ""; | ||||||
|  | 
 | ||||||
|  |     if (monthNumber > 9) { | ||||||
|  |         monthString = monthNumber + ''; | ||||||
|  |     } else { | ||||||
|  |         monthString = '0' + monthNumber; | ||||||
|  |     } | ||||||
|  |     return `${targetDate.value.getFullYear()}.${monthString}`; | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | watch(targetDate, (newVal) => { | ||||||
|  |     emits("update:modelValue", newVal); | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style scoped lang="scss"> | ||||||
|  | .diy-calendar-wrapper { | ||||||
|  |     width: auto; | ||||||
|  |     height: 100%; | ||||||
|  | 
 | ||||||
|  |     .calendar-header { | ||||||
|  |         height: 54px; | ||||||
|  |         padding: 13px 20px; | ||||||
|  |         margin-bottom: 15px; | ||||||
|  |         display: flex; | ||||||
|  |         justify-content: space-between; | ||||||
|  |         user-select: none; | ||||||
|  | 
 | ||||||
|  |         .left-arrow, | ||||||
|  |         .right-arrow { | ||||||
|  |             width: 40px; | ||||||
|  |             height: 40px; | ||||||
|  |             border-radius: 50%; | ||||||
|  |             background-color: rgba(215, 221, 228, 0.2); | ||||||
|  |             display: flex; | ||||||
|  |             justify-content: center; | ||||||
|  |             align-items: center; | ||||||
|  |             cursor: pointer; | ||||||
|  |             border: 1px solid rgba(95, 147, 238, 0.5); | ||||||
|  |             transition: all 0.2s; | ||||||
|  |             overflow: hidden; | ||||||
|  | 
 | ||||||
|  |             &:hover { | ||||||
|  |                 border: 1px solid rgba(8, 94, 243, 0.9); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .center-title { | ||||||
|  |             display: flex; | ||||||
|  |             justify-content: center; | ||||||
|  |             align-items: center; | ||||||
|  |             font-family: Magneto; | ||||||
|  |             font-size: 30px; | ||||||
|  |             font-weight: bold; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     .diy-calendar-table { | ||||||
|  |         width: 100%; | ||||||
|  |         user-select: none; | ||||||
|  |         border-collapse: collapse; | ||||||
|  | 
 | ||||||
|  |         .table-header-row { | ||||||
|  |             height: 32px; | ||||||
|  |             background-color: rgba(95, 147, 238, 0.06); | ||||||
|  | 
 | ||||||
|  |             .table-header { | ||||||
|  |                 font-size: 16px; | ||||||
|  |                 text-align: center; | ||||||
|  |                 font-family: "Lucida Handwriting"; | ||||||
|  |                 font-weight: bold; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .table-body-row { | ||||||
|  |             height: 75px; | ||||||
|  | 
 | ||||||
|  |             .table-data { | ||||||
|  |                 text-align: center; | ||||||
|  | 
 | ||||||
|  |                 .td-content-box { | ||||||
|  |                     width: 100%; | ||||||
|  |                     height: 100%; | ||||||
|  |                     display: flex; | ||||||
|  |                     justify-content: center; | ||||||
|  |                     align-items: center; | ||||||
|  | 
 | ||||||
|  |                     .content-border { | ||||||
|  |                         position: relative; | ||||||
|  |                         width: 60px; | ||||||
|  |                         height: 60px; | ||||||
|  |                         border-radius: 50%; | ||||||
|  |                         cursor: pointer; | ||||||
|  |                         transition: all ease 0.3s; | ||||||
|  | 
 | ||||||
|  |                         .table-badge { | ||||||
|  |                             width: 14px; | ||||||
|  |                             height: 14px; | ||||||
|  |                             border-radius: 50%; | ||||||
|  |                             position: absolute; | ||||||
|  |                             right: 3px; | ||||||
|  |                             top: 3px; | ||||||
|  |                             background-color: rgba(20, 167, 59, 0.5); | ||||||
|  |                             color: #ffffff; | ||||||
|  |                             font-size: 10px; | ||||||
|  |                             transition: all ease 0.3s; | ||||||
|  | 
 | ||||||
|  |                             &.current { | ||||||
|  |                                 background-color: #14a73b; | ||||||
|  |                                 font-weight: normal; | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  |                         .date-number { | ||||||
|  |                             width: 100%; | ||||||
|  |                             position: absolute; | ||||||
|  |                             left: 0; | ||||||
|  |                             text-align: center; | ||||||
|  |                             top: 20px; | ||||||
|  |                             font-size: 18px; | ||||||
|  |                             line-height: 20px; | ||||||
|  |                             transition: all ease 0.3s; | ||||||
|  |                             font-family: Magneto; | ||||||
|  |                             font-weight: normal; | ||||||
|  |                             // color: rgba(42, 63, 103, 0.48); | ||||||
|  |                             color: #666; | ||||||
|  | 
 | ||||||
|  |                             &.current { | ||||||
|  |                                 // color: #435069; | ||||||
|  |                                 color: #cdd2d8; | ||||||
|  | 
 | ||||||
|  |                                 font-weight: bold; | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  |                         .the-tradition-chinese-calendar { | ||||||
|  |                             width: 40px; | ||||||
|  |                             position: absolute; | ||||||
|  |                             left: 10px; | ||||||
|  |                             top: 34px; | ||||||
|  |                             font-size: 10px; | ||||||
|  |                             transition: all ease 0.2s; | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  |                         &.selected { | ||||||
|  |                             //background: #023f99; | ||||||
|  |                             background: radial-gradient(#2B6CFF , #0062fb ); | ||||||
|  |                             border-radius: 50%; | ||||||
|  | 
 | ||||||
|  |                             .table-badge { | ||||||
|  |                                 background: #ffffff; | ||||||
|  |                                 color: #023f99; | ||||||
|  |                             } | ||||||
|  | 
 | ||||||
|  |                             .date-number { | ||||||
|  |                                 color: #ffffff; | ||||||
|  |                             } | ||||||
|  | 
 | ||||||
|  |                             .the-tradition-chinese-calendar { | ||||||
|  |                                 color: #ffffff; | ||||||
|  |                             } | ||||||
|  | 
 | ||||||
|  |                             /* &::before, | ||||||
|  |                             &::after { | ||||||
|  |                                 content: ""; | ||||||
|  |                                 position: absolute; | ||||||
|  |                                 width: 80px; | ||||||
|  |                                 height: 80px; | ||||||
|  |                                 border: 3px solid rgba(2, 63, 153, 0.5); | ||||||
|  |                                 border-radius: 50%; | ||||||
|  |                                 inset: -10px; | ||||||
|  |                             } | ||||||
|  | 
 | ||||||
|  |                             &::before { | ||||||
|  |                                 // animation: pathRotate1 4s linear infinite; | ||||||
|  |                             } | ||||||
|  | 
 | ||||||
|  |                             &::after { | ||||||
|  |                                 animation: pathRotate2 4s linear infinite; | ||||||
|  |                             } */ | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @keyframes pathRotate1 { | ||||||
|  | 
 | ||||||
|  |     0%, | ||||||
|  |     100% { | ||||||
|  |         clip-path: inset(0 0 95% 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     25% { | ||||||
|  |         clip-path: inset(0 0 0 95%); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     50% { | ||||||
|  |         clip-path: inset(95% 0 0 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     75% { | ||||||
|  |         clip-path: inset(0 95% 0 0); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @keyframes pathRotate2 { | ||||||
|  | 
 | ||||||
|  |     0%, | ||||||
|  |     100% { | ||||||
|  |         clip-path: inset(95% 0 0 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     25% { | ||||||
|  |         clip-path: inset(0 95% 0 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     50% { | ||||||
|  |         clip-path: inset(0 0 95% 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     75% { | ||||||
|  |         clip-path: inset(0 0 0 95%); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | </style> | ||||||
|  | @ -0,0 +1,187 @@ | ||||||
|  | <!-- | ||||||
|  |  * @Author: 张宁 18339727226@163.com | ||||||
|  |  * @Date: 2024-05-27 14:46:17 | ||||||
|  |  * @LastEditors: 张宁 18339727226@163.com | ||||||
|  |  * @LastEditTime: 2024-05-29 15:37:58 | ||||||
|  |  * @FilePath: \welcome-system-screen\src\components\datePicker\datePicker.vue | ||||||
|  |  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE | ||||||
|  | --> | ||||||
|  | <template> | ||||||
|  |     <div ref="datePickerRef" class="datePicker"> | ||||||
|  |         <el-config-provider :locale="zhCn"> | ||||||
|  |             <!-- Dropdown button --> | ||||||
|  |             <button @click="toggleDropdown" style="width: 100%;"> | ||||||
|  |                 切换日期 | ||||||
|  |             </button> | ||||||
|  |             <!-- Dropdown menu --> | ||||||
|  |             <div v-if="isOpen" class="datePicker-menu"> | ||||||
|  |                 <div class="picker-title"> | ||||||
|  |                     <div class="tabs"> | ||||||
|  |                         <div class="title-item" v-for="(tab, index) in tabs" :key="index" | ||||||
|  |                             :class="{ active: activeTab === index }" @click="changeTab(index)"> | ||||||
|  |                             {{ tab.content?tab.content:'' }}{{ tab.title }} | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="confirm-box" @click="confirmDate">确定</div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="picker-content" v-show="activeTab === 0"> | ||||||
|  |                     <yearPane v-model:curYear="myYear" /> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="picker-content" v-show="activeTab === 1"> | ||||||
|  |                     <monthPane v-model:curMonth="myMonth" /> | ||||||
|  | 
 | ||||||
|  |                 </div> | ||||||
|  |                 <div class="picker-content" v-show="activeTab === 2"> | ||||||
|  |                     <DayPane :curYear="myYear" :curMonth="myMonth" v-model:curDay="myDay" /> | ||||||
|  |                 </div> | ||||||
|  | 
 | ||||||
|  |             </div> | ||||||
|  |         </el-config-provider> | ||||||
|  |     </div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script lang="ts" setup name="datePicker"> | ||||||
|  | import { ref, onMounted, onUnmounted, nextTick } from "vue"; | ||||||
|  | import { ElConfigProvider } from 'element-plus' | ||||||
|  | 
 | ||||||
|  | import zhCn from 'element-plus/es/locale/lang/zh-cn' | ||||||
|  | 
 | ||||||
|  | // Reactive variables | ||||||
|  | const isOpen = ref(false); // Dropdown open/close state | ||||||
|  | const datePickerRef = ref(null); // Reference to datePicker element | ||||||
|  | const { proxy } = getCurrentInstance(); | ||||||
|  | // Toggle datePicker open/close state | ||||||
|  | const toggleDropdown = () => { | ||||||
|  |     isOpen.value = !isOpen.value; | ||||||
|  | }; | ||||||
|  | const myYear = ref(); | ||||||
|  | const myMonth = ref(); | ||||||
|  | const myDay = ref(); | ||||||
|  | 
 | ||||||
|  | // tabs 切换 | ||||||
|  | const activeTab = ref(0); | ||||||
|  | const tabs = computed(()=>{ | ||||||
|  |     return [ | ||||||
|  |         { title: '年', content: myYear.value }, | ||||||
|  |         { title: '月', content: myMonth.value }, | ||||||
|  |         { title: '日', content: myDay.value }, | ||||||
|  |     ]; | ||||||
|  | }) | ||||||
|  | const changeTab = (index: number) => { | ||||||
|  |     activeTab.value = index; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // Select an option from the datePicker | ||||||
|  | const confirmDate = () => { | ||||||
|  |     isOpen.value = false; // Close the datePicker | ||||||
|  |     // 将选择的值传递给父组件 | ||||||
|  |     let dates = `${myYear.value}-${myMonth.value}-${myDay.value}` | ||||||
|  |     console.log(dates); | ||||||
|  |     proxy.$emit("getOption",dates); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // Close datePicker when clicking outside | ||||||
|  | const closeDropdown = (event: any) => { | ||||||
|  |     // 单独针对dataPane中的组件进行处理 | ||||||
|  |     if (event.target.className === 'content-border' || event.target.className === 'date-number') { | ||||||
|  |         return | ||||||
|  |     } | ||||||
|  |     if (!datePickerRef.value.contains(event.target)) { | ||||||
|  |         isOpen.value = false; | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // Lifecycle hook: mounted | ||||||
|  | onMounted(() => { | ||||||
|  |     nextTick(() => { | ||||||
|  |         document.addEventListener("click", closeDropdown); // Listen for click events outside datePicker | ||||||
|  |     }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // Lifecycle hook: unmounted | ||||||
|  | onUnmounted(() => { | ||||||
|  |     document.removeEventListener("click", closeDropdown); // Remove event listener when component is unmounted | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style lang="scss" scoped> | ||||||
|  | .datePicker { | ||||||
|  |     position: relative; | ||||||
|  |     display: inline-block; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .datePicker button { | ||||||
|  |     background: none; | ||||||
|  |     color: inherit; | ||||||
|  |     padding: 0; | ||||||
|  |     border: none; | ||||||
|  |     // cursor: pointer; | ||||||
|  |     font-size: inherit; | ||||||
|  |     font-weight: inherit; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .datePicker-menu { | ||||||
|  |     width: 580px; | ||||||
|  |     height: 660px; | ||||||
|  |     position: absolute; | ||||||
|  |     // left: -50%; | ||||||
|  |     transform: translate(-530px, 20px); | ||||||
|  |     // background-color: #f9f9f9; | ||||||
|  |     background: rgba(0, 0, 0, 0.8); | ||||||
|  |     min-width: 580px; | ||||||
|  |     max-height: 660px; | ||||||
|  |     box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2); | ||||||
|  |     z-index: 1; | ||||||
|  |     margin: 0; | ||||||
|  |     padding: 0; | ||||||
|  |     overflow-y: auto; | ||||||
|  |     border: 5px double #34354a; | ||||||
|  |     border-radius: 20px; | ||||||
|  |     cursor: default; | ||||||
|  | 
 | ||||||
|  |     // padding: 10px; | ||||||
|  |     .picker-title { | ||||||
|  |         line-height: 70px; | ||||||
|  |         height: 70px; | ||||||
|  |         border-bottom: 3px solid #272b40; | ||||||
|  |         display: flex; | ||||||
|  |         justify-content: space-between; | ||||||
|  |         align-items: center; | ||||||
|  | 
 | ||||||
|  |         // width: 580px; | ||||||
|  |         .tabs { | ||||||
|  |             display: flex; | ||||||
|  | 
 | ||||||
|  |             div { | ||||||
|  |                 display: inline-block; | ||||||
|  |                 cursor: pointer; | ||||||
|  |                 width: 100px; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             .active { | ||||||
|  |                 border-bottom: 3px solid #0254eb; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .confirm-box { | ||||||
|  |             width: 100px; | ||||||
|  |             height: 50px; | ||||||
|  |             line-height: 50px; | ||||||
|  |             background: #0254eb; | ||||||
|  |             border-radius: 20px; | ||||||
|  |             margin-right: 20px; | ||||||
|  |             cursor: pointer; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* 设置滚动条的宽度 */ | ||||||
|  | ::-webkit-scrollbar { | ||||||
|  |     display: none; | ||||||
|  | } | ||||||
|  | </style> | ||||||
|  | @ -0,0 +1,232 @@ | ||||||
|  | <!-- | ||||||
|  |  * @Author: 张宁 18339727226@163.com | ||||||
|  |  * @Date: 2024-05-28 11:55:39 | ||||||
|  |  * @LastEditors: 张宁 18339727226@163.com | ||||||
|  |  * @LastEditTime: 2024-05-29 15:38:56 | ||||||
|  |  * @FilePath: \welcome-system-screen\src\components\datePicker\dayPane.vue | ||||||
|  |  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE | ||||||
|  | --> | ||||||
|  | <template> | ||||||
|  |     <div class="box"> | ||||||
|  |         <!-- 日历主体 --> | ||||||
|  |         <table class="diy-calendar-table"> | ||||||
|  |             <!-- 星期栏 --> | ||||||
|  |             <thead> | ||||||
|  |                 <tr class="table-header-row"> | ||||||
|  |                     <th v-for="day in dayNameList" class="table-header"> | ||||||
|  |                         {{ day }} | ||||||
|  |                     </th> | ||||||
|  |                 </tr> | ||||||
|  |             </thead> | ||||||
|  |             <!-- 日期部分 --> | ||||||
|  |             <tbody> | ||||||
|  |                 <tr class="table-body-row" v-for="(row, index) in dayList" :key="index"> | ||||||
|  |                     <td v-for="col in row" class="table-data" :data-date="col"> | ||||||
|  |                         <div class="td-content-box"> | ||||||
|  |                             <div class="content-border" :class="{ selected: isSelectedDate(col) }" | ||||||
|  |                                 @click="selectDay(col)"> | ||||||
|  |                                 <div :class="['date-number', {'current':col !==''}]"> | ||||||
|  |                                     {{ col }} | ||||||
|  |                                 </div> | ||||||
|  |                             </div> | ||||||
|  |                         </div> | ||||||
|  |                     </td> | ||||||
|  |                 </tr> | ||||||
|  |             </tbody> | ||||||
|  |         </table> | ||||||
|  |     </div> | ||||||
|  | </template> | ||||||
|  | <script setup lang="ts"> | ||||||
|  | const props = defineProps({ | ||||||
|  |     curYear: Number, | ||||||
|  |     curMonth: Number, | ||||||
|  |     curDay: Number, | ||||||
|  | }); | ||||||
|  | const selectDays:Ref<any> = ref(props.curDay); | ||||||
|  | /** | ||||||
|  |  * @description: 获取某年某月的天数 | ||||||
|  |  * @param {*} year | ||||||
|  |  * @param {*} month | ||||||
|  |  * @return {*} | ||||||
|  |  */ | ||||||
|  | function getDaysInMonth(year: number, month: number) { | ||||||
|  |     const daysInMonth = new Date(year, month, 0).getDate(); | ||||||
|  |     const firstDay = new Date(year, month - 1, 1).getDay(); // 获取本月第一天是星期几 | ||||||
|  |     const weeks = Math.ceil((firstDay + daysInMonth) / 7); // 计算本月有几周 | ||||||
|  | 
 | ||||||
|  |     let date = 1; | ||||||
|  |     const result = []; | ||||||
|  |     for (let i = 0; i < weeks; i++) { | ||||||
|  |         const week = []; | ||||||
|  |         for (let j = 0; j < 7; j++) { | ||||||
|  |             if ((i === 0 && j < firstDay) || date > daysInMonth) { | ||||||
|  |                 week.push(''); | ||||||
|  |             } else { | ||||||
|  |                 week.push(date); | ||||||
|  |                 date++; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         result.push(week); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | /** | ||||||
|  |  * 用于展现的日历数据 -- 当前月 | ||||||
|  |  */ | ||||||
|  | const dayList = computed(() => { | ||||||
|  |     if (props.curYear && props.curMonth) { | ||||||
|  |         return getDaysInMonth(props.curYear, props.curMonth) | ||||||
|  |     } else { | ||||||
|  |         return [] | ||||||
|  |     } | ||||||
|  | }) | ||||||
|  | // 选择当前时间 | ||||||
|  | const selectDay = (day: any) => { | ||||||
|  |     if (!day) { | ||||||
|  |         return | ||||||
|  |     } | ||||||
|  |     if (selectDays.value == day) { | ||||||
|  |         selectDays.value = 0 | ||||||
|  |     } else { | ||||||
|  |         selectDays.value = day; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | const emits = defineEmits(["update:curDay"]); | ||||||
|  | watch(selectDays, (newVal) => { | ||||||
|  |     emits("update:curDay", newVal); | ||||||
|  | }); | ||||||
|  | /** | ||||||
|  |  * @description: 判断是否被选择 | ||||||
|  |  * @param {*} day | ||||||
|  |  * @return {*} | ||||||
|  |  */ | ||||||
|  | const isSelectedDate = (day: any) => { | ||||||
|  |     if (!day) { | ||||||
|  |         return false | ||||||
|  |     } | ||||||
|  |     return day === selectDays.value | ||||||
|  | } | ||||||
|  | /** | ||||||
|  | * 有关周几的名称列表 | ||||||
|  | */ | ||||||
|  | const dayNameList = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']; | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style scoped lang='scss'> | ||||||
|  | .box { | ||||||
|  |     width: 100%; | ||||||
|  |     height: 100%; | ||||||
|  |     padding: 20px; | ||||||
|  |     .diy-calendar-table { | ||||||
|  |         width: 100%; | ||||||
|  |         user-select: none; | ||||||
|  |         border-collapse: collapse; | ||||||
|  | 
 | ||||||
|  |         .table-header-row { | ||||||
|  |             height: 32px; | ||||||
|  |             background-color: rgba(95, 147, 238, 0.06); | ||||||
|  | 
 | ||||||
|  |             .table-header { | ||||||
|  |                 font-size: 16px; | ||||||
|  |                 text-align: center; | ||||||
|  |                 font-family: "Lucida Handwriting"; | ||||||
|  |                 font-weight: bold; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .table-body-row { | ||||||
|  |             height: 75px; | ||||||
|  | 
 | ||||||
|  |             .table-data { | ||||||
|  |                 text-align: center; | ||||||
|  | 
 | ||||||
|  |                 .td-content-box { | ||||||
|  |                     width: 100%; | ||||||
|  |                     height: 100%; | ||||||
|  |                     display: flex; | ||||||
|  |                     justify-content: center; | ||||||
|  |                     align-items: center; | ||||||
|  | 
 | ||||||
|  |                     .content-border { | ||||||
|  |                         position: relative; | ||||||
|  |                         width: 60px; | ||||||
|  |                         height: 60px; | ||||||
|  |                         border-radius: 50%; | ||||||
|  |                         transition: all ease 0.3s; | ||||||
|  | 
 | ||||||
|  |                         .table-badge { | ||||||
|  |                             width: 14px; | ||||||
|  |                             height: 14px; | ||||||
|  |                             border-radius: 50%; | ||||||
|  |                             position: absolute; | ||||||
|  |                             right: 3px; | ||||||
|  |                             top: 3px; | ||||||
|  |                             background-color: rgba(20, 167, 59, 0.5); | ||||||
|  |                             color: #ffffff; | ||||||
|  |                             font-size: 10px; | ||||||
|  |                             transition: all ease 0.3s; | ||||||
|  | 
 | ||||||
|  |                             &.current { | ||||||
|  |                                 background-color: #14a73b; | ||||||
|  |                                 font-weight: normal; | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  |                         .date-number { | ||||||
|  |                             width: 100%; | ||||||
|  |                             position: absolute; | ||||||
|  |                             left: 0; | ||||||
|  |                             text-align: center; | ||||||
|  |                             top: 20px; | ||||||
|  |                             font-size: 18px; | ||||||
|  |                             line-height: 20px; | ||||||
|  |                             transition: all ease 0.3s; | ||||||
|  |                             font-family: Magneto; | ||||||
|  |                             font-weight: normal; | ||||||
|  |                             // color: rgba(42, 63, 103, 0.48); | ||||||
|  |                             color: #666; | ||||||
|  | 
 | ||||||
|  |                             &.current { | ||||||
|  |                                 // color: #435069; | ||||||
|  |                                 color: #cdd2d8; | ||||||
|  |                                 cursor: pointer; | ||||||
|  |                                 font-weight: bold; | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  |                         .the-tradition-chinese-calendar { | ||||||
|  |                             width: 40px; | ||||||
|  |                             position: absolute; | ||||||
|  |                             left: 10px; | ||||||
|  |                             top: 34px; | ||||||
|  |                             font-size: 10px; | ||||||
|  |                             transition: all ease 0.2s; | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  |                         &.selected { | ||||||
|  |                             //background: #023f99; | ||||||
|  |                             background: radial-gradient(#2B6CFF, #0062fb); | ||||||
|  |                             border-radius: 50%; | ||||||
|  | 
 | ||||||
|  |                             .table-badge { | ||||||
|  |                                 background: #ffffff; | ||||||
|  |                                 color: #023f99; | ||||||
|  |                             } | ||||||
|  | 
 | ||||||
|  |                             .date-number { | ||||||
|  |                                 color: #ffffff; | ||||||
|  |                             } | ||||||
|  | 
 | ||||||
|  |                             .the-tradition-chinese-calendar { | ||||||
|  |                                 color: #ffffff; | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | </style> | ||||||
|  | @ -0,0 +1,81 @@ | ||||||
|  | <!-- | ||||||
|  |  * @Author: 张宁 18339727226@163.com | ||||||
|  |  * @Date: 2024-05-28 11:56:59 | ||||||
|  |  * @LastEditors: 张宁 18339727226@163.com | ||||||
|  |  * @LastEditTime: 2024-05-29 15:23:57 | ||||||
|  |  * @FilePath: \welcome-system-screen\src\components\datePicker\monthPane.vue | ||||||
|  |  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE | ||||||
|  | --> | ||||||
|  | <template> | ||||||
|  |     <div class="box"> | ||||||
|  |         <div class='box-item' v-for="item, index in MonthList"> | ||||||
|  |             <div class="item-num" :class="{ selected: isSelectedDate(item) }" @click="selectMonth(item)">{{ item }} | ||||||
|  |             </div> | ||||||
|  |         </div> | ||||||
|  |     </div> | ||||||
|  | </template> | ||||||
|  | <script setup lang="ts"> | ||||||
|  | const props = defineProps({ | ||||||
|  |     curMonth: Number, | ||||||
|  | }); | ||||||
|  | const selectMonths:Ref<any> = ref(props.curMonth) | ||||||
|  | const MonthList = computed(() => { | ||||||
|  |     let Months = [] | ||||||
|  |     for (let i = 0; i < 12; i++) { | ||||||
|  |         Months.unshift(12 - i); | ||||||
|  |     } | ||||||
|  |     return Months; | ||||||
|  | }) | ||||||
|  | const selectMonth = (Month: number) => { | ||||||
|  |     if(selectMonths.value === Month){ | ||||||
|  |         selectMonths.value = 0 | ||||||
|  |     }else{ | ||||||
|  |         selectMonths.value = Month; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | // 更新外面的值 | ||||||
|  | const emits = defineEmits(["update:curMonth"]); | ||||||
|  | watch(selectMonths, (newVal) => { | ||||||
|  |     emits("update:curMonth", newVal); | ||||||
|  | }); | ||||||
|  | const isSelectedDate = (Month: any) => { | ||||||
|  |     if (Month == selectMonths.value) { | ||||||
|  |         return true | ||||||
|  |     } else { | ||||||
|  |         return false | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style scoped lang='scss'> | ||||||
|  | .box { | ||||||
|  |     width: 100%; | ||||||
|  |     height: 100%; | ||||||
|  |     display: flex; | ||||||
|  |     flex-wrap: wrap; | ||||||
|  | 
 | ||||||
|  |     .box-item { | ||||||
|  |         margin-right: 10px; | ||||||
|  |         margin-top: 20px; | ||||||
|  |         width: 120px; | ||||||
|  |         height: 70px; | ||||||
|  |         line-height: 70px; | ||||||
|  |         display: flex; | ||||||
|  |         justify-content: center; | ||||||
|  | 
 | ||||||
|  |         .item-num { | ||||||
|  |             width: 70px; | ||||||
|  |             height: 70px; | ||||||
|  |             border-radius: 50%; | ||||||
|  |             color: #fff; | ||||||
|  |             cursor: pointer; | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .selected { | ||||||
|  |             background-color: #007bff; | ||||||
|  |             color: #fff; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | </style> | ||||||
|  | @ -0,0 +1,83 @@ | ||||||
|  | <!-- | ||||||
|  |  * @Author: 张宁 18339727226@163.com | ||||||
|  |  * @Date: 2024-05-28 11:55:39 | ||||||
|  |  * @LastEditors: 张宁 18339727226@163.com | ||||||
|  |  * @LastEditTime: 2024-05-29 15:28:27 | ||||||
|  |  * @FilePath: \welcome-system-screen\src\components\datePicker\yearPane.vue | ||||||
|  |  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE | ||||||
|  | --> | ||||||
|  | <template> | ||||||
|  |     <div class="box"> | ||||||
|  |         <div class='box-item' v-for="item, index in yearList" @click="selectYear(item)"> | ||||||
|  |             <div :class="{ selected: isSelectedDate(item) }" class="item-num">{{ item }}</div> | ||||||
|  |         </div> | ||||||
|  |     </div> | ||||||
|  | </template> | ||||||
|  | <script setup lang="ts"> | ||||||
|  | const props = defineProps({ | ||||||
|  |     curYear: Number, | ||||||
|  | }); | ||||||
|  | const currentYear = ref(new Date().getFullYear()); | ||||||
|  | const selectYears:Ref<any> = ref(props.curYear) | ||||||
|  | // 获取到近六年的年份 | ||||||
|  | const yearList = computed(() => { | ||||||
|  |     let years = [] | ||||||
|  |     for (let i = 0; i < 6; i++) { | ||||||
|  |         years.unshift(currentYear.value - i); | ||||||
|  |     } | ||||||
|  |     return years; | ||||||
|  | }) | ||||||
|  | // 选择年的处理 如果点击的是当前的 就赋值为空 | ||||||
|  | const selectYear = (year: number) => { | ||||||
|  |     if (selectYears.value == year) { | ||||||
|  |         selectYears.value = 0 | ||||||
|  |     } else { | ||||||
|  |         selectYears.value = year; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | const emits = defineEmits(["update:curYear"]); | ||||||
|  | watch(selectYears, (newVal) => { | ||||||
|  |     emits("update:curYear", newVal); | ||||||
|  | }); | ||||||
|  | const isSelectedDate = (year: any) => { | ||||||
|  |     if (year == selectYears.value) { | ||||||
|  |         return true | ||||||
|  |     } else { | ||||||
|  |         return false | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style scoped lang='scss'> | ||||||
|  | .box { | ||||||
|  |     width: 100%; | ||||||
|  |     height: 100%; | ||||||
|  |     display: flex; | ||||||
|  |     flex-wrap: wrap; | ||||||
|  | 
 | ||||||
|  |     .box-item { | ||||||
|  |         margin-right: 10px; | ||||||
|  |         margin-top: 20px; | ||||||
|  |         width: 120px; | ||||||
|  |         height: 70px; | ||||||
|  |         line-height: 70px; | ||||||
|  |         display: flex; | ||||||
|  |         justify-content: center; | ||||||
|  | 
 | ||||||
|  |         .item-num { | ||||||
|  |             width: 70px; | ||||||
|  |             height: 70px; | ||||||
|  |             border-radius: 50%; | ||||||
|  |             color: #fff; | ||||||
|  |             cursor: pointer; | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .selected { | ||||||
|  |             background-color: #007bff; | ||||||
|  |             color: #fff; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | </style> | ||||||
|  | @ -11,7 +11,8 @@ const test = () => { | ||||||
| // const returnHome = () => { | // const returnHome = () => { | ||||||
| //   history.go(-1) | //   history.go(-1) | ||||||
| // }; | // }; | ||||||
| const yearOptions = ref([{ label: '2024年', value: 2024 }, { label: '2023年', value: 2023 }, { label: '2022年', value: 2022 }, { label: '2021年', value: 2021 }, { label: '2020年', value: 2020 }]) | 
 | ||||||
|  | /* const yearOptions = ref([{ label: '2024年', value: 2024 }, { label: '2023年', value: 2023 }, { label: '2022年', value: 2022 }, { label: '2021年', value: 2021 }, { label: '2020年', value: 2020 }]) | ||||||
| const monthOptions = ref([ | const monthOptions = ref([ | ||||||
|   { label: '/', value: null }, |   { label: '/', value: null }, | ||||||
|   { label: '1月', value: 1 }, |   { label: '1月', value: 1 }, | ||||||
|  | @ -47,6 +48,11 @@ const selectNowdays = () => { | ||||||
|     selectMonth.value.clearOption() |     selectMonth.value.clearOption() | ||||||
|   } |   } | ||||||
|   timeStore.setNowDays() |   timeStore.setNowDays() | ||||||
|  | }*/ | ||||||
|  | // 获取选择的日期(年 || 月 ||日) | ||||||
|  | const getDate = (val:any)=>{ | ||||||
|  |   console.log('获取选择的日期',val); | ||||||
|  |    | ||||||
| } | } | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
|  | @ -65,13 +71,15 @@ const selectNowdays = () => { | ||||||
| 
 | 
 | ||||||
|     <div class="change-time"> |     <div class="change-time"> | ||||||
|       <div class="change-year"> |       <div class="change-year"> | ||||||
|  |         <DatePicker @getOption="getDate" ref="selectYear"></DatePicker> | ||||||
|  |       </div> | ||||||
|  |       <!-- <div class="change-year"> | ||||||
|         <Dropdown :options="yearOptions" title="切换年份" @getOption="getYear" ref="selectYear"></Dropdown> |         <Dropdown :options="yearOptions" title="切换年份" @getOption="getYear" ref="selectYear"></Dropdown> | ||||||
|       </div> |       </div> | ||||||
| 
 |  | ||||||
|       <div class="change-year"> |       <div class="change-year"> | ||||||
|         <Dropdown :options="monthOptions" title="切换月份" @getOption="getMonth" ref="selectMonth"></Dropdown> |         <Dropdown :options="monthOptions" title="切换月份" @getOption="getMonth" ref="selectMonth"></Dropdown> | ||||||
|       </div> |       </div> | ||||||
|       <div class="change-year" @click="selectNowdays">选择今日</div> |       <div class="change-year" @click="selectNowdays">选择今日</div> --> | ||||||
|     </div> |     </div> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
|  | @ -135,7 +143,8 @@ const selectNowdays = () => { | ||||||
|   width: 400px; |   width: 400px; | ||||||
|   height: 60px; |   height: 60px; | ||||||
|   display: flex; |   display: flex; | ||||||
|   justify-content: space-between; |   // justify-content: space-between; | ||||||
|  |   flex-direction: row-reverse; | ||||||
|   font-family: 'YouSheBiaoTiHei'; |   font-family: 'YouSheBiaoTiHei'; | ||||||
|   font-size: 16px; |   font-size: 16px; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue