赞
踩
实现一个日历组件,可以在对应的日期下显示其他数据;可以切换上月下月;回到今天;点击日期为其他月份的时候自动切换到该月。
<template> <div class="w-full calender-com"> <h2 class="w-full flex justify-between items-center "> <span class="text-333">{{ year + "年" + month + "月" }}</span> <div class="btn-wrap flex justify-between"> <button class="btn" @click="changeMonth(-1)"> <span>{{ '<<' }}上个月</span> </button> <button class="btn" @click="changeMonth(1)"> <span>下个月{{ '>>' }}</span> </button> </div> <button class="btn" @click="getNowDate()">回到今天</button> </h2> <!-- <div class="w-full flex justify-between items-end calender-head"> <div class="select-con cursor-pointer"> <div @click="showOption">{{ currMonth }}<span class="arrow" :class="[isDrop ? 'arrow-top' : 'arrow-bottom']"></span> </div> <ul v-show="isDrop" class="option-con"> <li v-for="item in timeoptions" :key="item['value']" @click="selectMonth(item['value'])">{{ item.label }}</li> </ul> </div> </div> --> <div class="shadow-con"> <div class="w-full flex flex-wrap justify-start calender-zhou"> <div class="w-item">周一</div> <div class="w-item">周二</div> <div class="w-item">周三</div> <div class="w-item">周四</div> <div class="w-item">周五</div> <div class="w-item">周六</div> <div class="w-item">周日</div> </div> <div class="w-full flex flex-wrap justify-start calender-main"> <div class="w-item" v-for="item in daylist" :key="item.timestamp" :class="item.month !== month ? 'bg-ee' : ''" @click="clickevent(item)"> <div class="w-full flex justify-center items-center text-center"> <span class="day-mum">{{ item.day }}</span> <span v-if="item.day === xianzaitime['day'] && item.month === xianzaitime['month'] && item.year === xianzaitime['year']" class="text-red">今天</span> <!-- <span>{{ item.zhou }}</span> --> </div> <!-- <div>{{ item.number }}</div> --> <slot :name="`${item.year}-${item.month}-${item.day}`" :year="item.year" :month="item.month" :day="item.day" :week="item.week"></slot> </div> </div> </div> </div> </template> <script lang="ts" setup> export interface ObjConfig { timestamp: any, year: any month: any, day: any, number: any } const emit = defineEmits(["handleclick", "changemonth"]) // 需要展示的所有日期列表 const daylist: any = ref([]) // 年月日数据暂存 const shijian = ref(null) const year = ref(0) const month = ref(0) const day = ref(0) // let timeoptions: any = ref([ // { value: '2023-2', label: '2023年02月', id: '2' }, // { value: '2023-3', label: '2023年03月', id: '3' } // ]) // const currMonth = ref('') let isDrop = ref(false) const getNowDate = (canshu = null) => { // 置空日期列表 daylist.value = [] if (canshu) { shijian.value = new Date(canshu) } else { shijian.value = new Date(); } year.value = shijian.value.getFullYear() month.value = shijian.value.getMonth() + 1 day.value = shijian.value.getDate() // 当前显示月份改变后,需要向父组件抛出,父组件可以根据月份更新日程 emit("changemonth", { year: year.value, month: month.value }) getDaylist() } // 计算需要展示的第一个日期 const startandendday = () => { const cloneNowDate = new Date(shijian.value); // 先获取这个月的第一天 const firstdaytime = cloneNowDate.setDate(1) // 获取第一天是周几 let firstdayweek = new Date(firstdaytime).getDay() if (firstdayweek === 0) { firstdayweek = 7 } // 展示时间的第一天 return firstdaytime - (firstdayweek - 1) * 24 * 60 * 60 * 1000 } // 向列表填充数据 const getDaylist = () => { const starttime = startandendday() for (let i = 0; i <= 60; i++) { let shuju: any = {} const shijianchuo = starttime + i * 24 * 60 * 60 * 1000 const sj = new Date(shijianchuo) const year1 = sj.getFullYear() const month1 = sj.getMonth() + 1 const day1 = sj.getDate() const week = sj.getDay() if (month.value === 1) { if (month1 > month.value && month1 !== 12) { if (week === 1 || week === 7) { break } } } else if (month.value === 12) { if (month1 - month.value === -11) { if (week === 1 || week === 7) { break } } } else { if (month1 > month.value) { if (week === 1 || week === 7) { break } } } shuju["timestamp"] = shijianchuo shuju["year"] = year1 shuju["month"] = month1 shuju["day"] = day1 shuju["week"] = week // shuju["zhou"] = dict2(week) daylist.value.push(shuju) } } // 日期点击事件 const clickevent = (item: any) => { // const id = timeoptions.value.find((it: any) => it.label === currMonth.value).id // if (item.month !== Number(id)) return false // emit("handleclick", item) // --------------------以上是下拉选择月份形式,对于日期的点击,不是当前月的日期无交互 // 如果点击的日期不是当前月的,修改当前时间 if (item.month !== month.value) { getNowDate(item.timestamp) currMonth.value = timeoptions.value.find(it => Number(it.id) === item.month)?.label } /emit("handleclick", item) } // 点击上个月或者下个月 const changeMonth = (num: any) => { let newmonth = month.value + num // 如果大于12,转到下一年 if (newmonth > 12) { year.value += 1 newmonth = 1 } if (newmonth < 1) { year.value -= 1 newmonth = 12 } const sj = new Date(Date.parse(year.value + "/" + newmonth + "/" + day.value)).getTime() getNowDate(sj) } // 获取今天的时间 const xianzaitime = ref({}) const getnow = () => { const sj = new Date() xianzaitime.value['year'] = sj.getFullYear() xianzaitime.value["month"] = sj.getMonth() + 1 xianzaitime.value["day"] = sj.getDate() const maxId = timeoptions.value[timeoptions.value.length - 1].id if (Number(maxId) < xianzaitime.value["month"]) { for (let i = Number(maxId) + 1; i <= xianzaitime.value["month"]; i++) { let obj if (i <= 9) { obj = { value: `${xianzaitime.value["year"]}-${i}`, label: `${xianzaitime.value["year"]}年0${i}月`, id: i.toString() } } else { obj = { value: `${xianzaitime.value["year"]}-${i}`, label: `${xianzaitime.value["year"]}年${i}月`, id: i.toString() } } timeoptions.value.push(obj) } } currMonth.value = timeoptions.value.find(item => Number(item.id) === xianzaitime.value["month"])?.label } // 初始化区域 getnow() getNowDate() const showOption = () => { isDrop.value = !isDrop.value } const selectMonth = (val: any) => { isDrop.value = false currMonth.value = timeoptions.value.find((item: any) => item.value === val).label year.value = Number(val.split('-')[0]) let newmonth = Number(val.split('-')[1]) const sj = new Date(Date.parse(year.value + "/" + newmonth + "/" + day.value)).getTime() getNowDate(sj) // emit("changemonth", { year: year.value, month: newmonth }) } </script> <style scoped> .calender-com { width: 100%; background-color: #fff; } .text-center { text-align: center; } .flex { display: flex; } .justify-start { justify-content: start; } .justify-between { justify-content: space-between; } .justify-center { justify-content: center; } .calender-com .shadow-con { box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.09); border-left: 1px solid #ccc; border-top: 1px solid #ccc; } .calender-com h2 { font-size: 16px; line-height: 20px; padding-bottom: 10px; } .shadow-con .btn-wrap { border: 1px solid #ccc; padding: 2px 5px; border-radius: 10px; width: 180px; } .btn-wrap .btn { width: 90px; } .btn:first-child { border-right: 1px solid #ccc; } .btn-wrap .btn:hover { color: #aa0000; } .calender-com .calender-head { padding-bottom: 10px; color: #333; } .calender-com .calender-head p { font-size: 18px; line-height: 24px; color: #333333; padding-top: 20px; } .select-con { width: 136px; height: 26px; line-height: 26px; border: 1px solid #EEEEEE; border-radius: 13px; text-align: center; position: relative; } .select-con .arrow { display: inline-block; width: 8px; height: 8px; border-top: 1px solid #333; border-left: 1px solid #333; margin-left: 3px; margin-top: -6px; vertical-align: middle; transform: rotate(-135deg); } .select-con .arrow.arrow-top { margin-top: 4px; transform: rotate(45deg); } .option-con { position: absolute; width: 100%; padding: 10px 0; border: 1px solid #eee; z-index: 9999; background-color: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); } .option-con li { line-height: 26px; font-size: 14px; } .option-con li:hover { background-color: #eee; } .calender-zhou .w-item { width: 14.285%; height: 50px; line-height: 50px; text-align: center; background-color: #fff; flex: 0 0 14.285%; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; box-sizing: border-box; } .calender-main .w-item { width: 14.285%; height: 80px; position: relative; flex: 0 0 14.285%; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; box-sizing: border-box; } .items-center { align-items: center; } .flex-wrap { flex-wrap: wrap; } .w-full { width: 100%; } .calender-main .w-item.day-mum { position: absolute; z-index: 99; left: 0; right: 0; padding-top: 30px; text-align: center; } .text-red { color: red; } .bg-ee { background-color: #eee; } </style> 使用------------------------------------------------------------------------ <template> <div> <Calendar @changemonth="changemonth" @handleclick="dayClick"> <template v-for="item in list" v-slot:[item.label]> <div :class="[Number(item['num']) >= 0 ? 'bg-pink' : 'bg-green']">+{{ Number(item['num'] * 100).toFixed(2) }}% </div> </template> </Calendar> </div> </template> <script lang="ts" setup> let list = ref([ { label: '2023-4-4', num: 0.066 }, { label: '2023-4-20', num: 0.0389 }, { label: '2023-4-21', num: -0.0289 } ]) // 月份改变 const changemonth = (val) => { console.log(val) } // 日期点击 const dayClick = (item) => { console.log(item) } </script>
组件里注释的部分代码是实现的下拉,下拉选择项的月份根据当前的月份,把当前月以及之前的月push进去,但是只实现了当前年的,前一年的就无法选择;并且点击日历中某一天的时候,若不是当前月,不做任何处理
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。