Work-calendar
介绍 (底部附链接)
基于uni-calendar做的定制化开发,主要功能为工作日历展示和提报组件
1.支持周计划日报状态展示且可配置
2.支持农历展示配置,回到当日,月份切换
3.日历,周报,日报等点击事件封装
4.支持休假展示
使用说明
1.下载插件到工程中,并在业务代码中引入
import Calendar from '@/components/calendar-zhikuany/calendar.vue'
2.布局中引入插件,并配置所需要的展示信息
<template><view><calendar ref="calendar" :date="date" @monthSwitch="monthSwitch" @change="handleSelect"@weekPlanClick="weekPlanClick" @datePlanClick="datePlanClick" lunar :showDay="prop.showDay":showPlan="prop.showPlan" :showMonth="prop.showMonth" :needState="prop.needState" /></view>
</template>/*** Calendar 日历* @property {String} date 自定义当前时间,默认为今天* @property {String} text.size 文字大小* @property {String} text.color 文字颜色* @property {Boolean} lunar 显示农历* @property {Boolean} showPlan 展示周计划* @property {Boolean} showDay 展示日报* @property {String} startDate 日期选择范围-开始日期* @property {String} endDate 日期选择范围-结束日期* @property {Boolean} range 范围选择* @property {Boolean} showMonth 是否选择月份为背景* @property {Boolean} needState 周计划日报是否需要审核* @event {Function} change 日期改变,* @event {Function} monthSwitch 切换月份时触发*/
3.设置本月周报日报假期数据
/*** 设置数据*/const setDate = (year : number, month : number) => {// 获取当月第一天和最后一天// const firstDay = new Date(year, month, 1);// const lastDay = new Date(year, month + 1, 0); // 下个月第0天 = 本月最后一天uni.showLoading({title: ''})//仿照调用接口 设置工作日历数据setTimeout(() => {uni.hideLoading()//测试周报和日报数据 为 9月12号date.value = '2025-09-12'calendar.value.setPlanList(planList)}, 1000)}
4.核心数据设置逻辑
/*** 获取每周数据* @param {Object} dateData*/_getWeek(dateData) {const {year,month} = this.getDate(dateData)let firstDay = new Date(year, month - 1, 1).getDay()// 调整为周一作为第一天(0=周一,6=周日)let adjustedFirstDay = firstDay === 0 ? 6 : firstDay - 1;let currentDay = new Date(year, month, 0).getDate()let dates = {lastMonthDays: this._getLastMonthDays(adjustedFirstDay, this.getDate(dateData)), // 上个月末尾几天currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数nextMonthDays: [], // 下个月开始几天weeks: []}let canlender = []const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length)dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData))canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays)this.canlender = canlenderlet weekTemp = {}let weekplan = {} //每周的周计划// 拼接数组 上个月开始几天 + 本月天数+ 下个月开始几天for (let i = 0; i < canlender.length; i++) {//获取本周的周计划数据if (i % 7 === 0) {//本周开始日期const weekBeginDate = canlender[i].fullDate// console.log('开始',weekBeginDate)//获取计划状态weekplan = {}for (let i = 0; i < this.planList.length; i++) {if (this.planList[i]) {const item = this.planList[i]// console.log(item.monday)if (item.beginDate == weekBeginDate) {weekplan = item// console.log('weekplan', weekplan)break}}}weekTemp[parseInt(i / 7)] = {weeks: new Array(7),planCode: weekplan.planCode,planId: weekplan.planId,attachIds: weekplan.attachIds,// fileUrl: weekplan.fileUrl,weekWorkPlan: weekplan.weekWorkPlan,workSummary: weekplan.workSummary,coordinateHelp: weekplan.coordinateHelp,dataState: this.isEmpty(weekplan.dataState) ? weekplan.dataState : 1,// dataState: weekplan.dataState //周计划 状态}}//每天的计划状态var dayPlan = {}switch (i % 7) {case 0: //周一// dayPlan.dayStatus = weekplan.mondayStatusdayPlan.dayStatus = this.isEmptyWithZero(weekplan.mondayStatus) ? weekplan.mondayStatus : 2dayPlan.isHoliday = weekplan.mondayIsHolidaybreak;case 1:// dayPlan.dayStatus = weekplan.tuesdayStatusdayPlan.dayStatus = this.isEmptyWithZero(weekplan.tuesdayStatus) ? weekplan.tuesdayStatus : 2dayPlan.isHoliday = weekplan.tuesdayIsHolidaybreak;case 2:// dayPlan.dayStatus = weekplan.wednesdayStatusdayPlan.dayStatus = this.isEmptyWithZero(weekplan.wednesdayStatus) ? weekplan.wednesdayStatus : 2dayPlan.isHoliday = weekplan.wednesdayIsHolidaybreak;case 3:// dayPlan.dayStatus = weekplan.thursdayStatusdayPlan.dayStatus = this.isEmptyWithZero(weekplan.thursdayStatus) ? weekplan.thursdayStatus : 2dayPlan.isHoliday = weekplan.thursdayIsHolidaybreak;case 4:// dayPlan.dayStatus = weekplan.fridayStatusdayPlan.dayStatus = this.isEmptyWithZero(weekplan.fridayStatus) ? weekplan.fridayStatus : 2dayPlan.isHoliday = weekplan.fridayIsHolidaybreak;case 5:// dayPlan.dayStatus = weekplan.saturdayStatusdayPlan.dayStatus = this.isEmptyWithZero(weekplan.saturdayStatus) ? weekplan.saturdayStatus : 2dayPlan.isHoliday = weekplan.saturdayIsHolidaybreak;case 6:// dayPlan.dayStatus = weekplan.sundayStatusdayPlan.dayStatus = this.isEmptyWithZero(weekplan.sundayStatus) ? weekplan.sundayStatus : 2dayPlan.isHoliday = weekplan.sundayIsHolidaybreak;}// console.log('swich',dayPlan)weekTemp[parseInt(i / 7)].weeks[i % 7] = {...canlender[i],...dayPlan}}this.weeks = weekTempconsole.log(this.weeks)}
完整示例
<template><view><calendar ref="calendar" :date="date" @monthSwitch="monthSwitch" @change="handleSelect"@weekPlanClick="weekPlanClick" @datePlanClick="datePlanClick" lunar :showDay="prop.showDay":showPlan="prop.showPlan" :showMonth="prop.showMonth" :needState="prop.needState" /></view>
</template><script setup lang="ts">import { ref, onMounted } from 'vue'import { onLoad, onShow } from '@dcloudio/uni-app'import { planList } from './data.js'import Calendar from '@/components/calendar-zhikuany/calendar.vue'/*** 本组件是基于uni-calendar(V1.5.5)之上增加了一些个性化功能点,如打卡日历,日历日程,日历排班,打卡排班等功能* 小点的位置 point.position [1, 2, 3, 4, 5, 6] 红点位置,[左上角, 右上角, 右下角, 左下角, 上中间, 下中间]* 小点的颜色 point.color 如 #000 #fff* 日期数字下方的自定义文本 info* text.size 自定义文本字体大小 如 12 14 16* text.color 自定义文本颜色 如 #000 #fff*/const calendar = ref({})const date = ref('')const query = defineProps<{ prop : string }>()const prop : any = ref({})//页面加载onLoad(() => {//解析配置参数prop.value = JSON.parse(query.prop)})onShow(() => {initDate()})//获取当月所有日期的数组 初始化数据const initDate = () => {const now = new Date();const year = now.getFullYear();const month = now.getMonth() + 1; // 月份从 0 开始(0=1月)setDate(year, month);}/*** 设置数据*/const setDate = (year : number, month : number) => {// 获取当月第一天和最后一天// const firstDay = new Date(year, month, 1);// const lastDay = new Date(year, month + 1, 0); // 下个月第0天 = 本月最后一天uni.showLoading({title: ''})//仿照调用接口 设置工作日历数据setTimeout(() => {uni.hideLoading()//测试周报和日报数据 为 9月12号date.value = '2025-09-12'calendar.value.setPlanList(planList)}, 1000)}/*** 选中*/const handleSelect = (e : any) => {console.log(e)if (e.extraInfo.date) {// do something}}//周计划点击const weekPlanClick = (item : any) => {console.log(item)if (item.dataState == 1 || item.dataState == 0) {//审核中或者审核通过uni.showToast({title: JSON.stringify(item),icon: 'none',duration: 2000})} else {if (!checkWeekRange(item.beginDate, item.endDate)) {uni.showToast({title: '只能提交当本周或下周的周计划',icon: 'none'})return}uni.showToast({title: '跳转周计划填报页面',icon: 'none',duration: 2000})}}/*** 判断给定的日期范围是否属于本周或下周* @param {string} beginDate - 开始日期,格式为 "YYYY-MM-DD"* @param {string} endDate - 结束日期,格式为 "YYYY-MM-DD"* @returns {string} - 返回 "本周"、"下周" 或 "不在本周或下周"*/function checkWeekRange(beginDate : any, endDate : any) : Boolean {// 将字符串日期转换为Date对象const begin = new Date(beginDate);const end = new Date(endDate);begin.setHours(0, 0, 0, 0)end.setHours(0, 0, 0, 0)console.log(begin + ' ' + end)// 获取当前日期const today = new Date();today.setHours(0, 0, 0, 0); // 清除时间部分// 计算当前周的起始和结束日期(周一至周日)const currentWeekStart = new Date(today);const dayOfWeek = today.getDay(); // 0是周日,1是周一,...,6是周六const diffToMonday = dayOfWeek === 0 ? -6 : 1 - dayOfWeek; // 调整为周一作为一周的第一天currentWeekStart.setDate(today.getDate() + diffToMonday);currentWeekStart.setHours(0, 0, 0, 0);const currentWeekEnd = new Date(currentWeekStart);currentWeekEnd.setDate(currentWeekStart.getDate() + 6);// 计算下周的起始和结束日期const nextWeekStart = new Date(currentWeekStart);nextWeekStart.setDate(currentWeekStart.getDate() + 7);const nextWeekEnd = new Date(currentWeekEnd);nextWeekEnd.setDate(currentWeekEnd.getDate() + 7);console.log(currentWeekStart + ' ' + currentWeekEnd)// 检查日期范围是否完全在本周内const isCurrentWeek = begin >= currentWeekStart && end <= currentWeekEnd;console.log(nextWeekStart + ' ' + nextWeekEnd)// 检查日期范围是否完全在下周内const isNextWeek = begin >= nextWeekStart && end <= nextWeekEnd;// 检查日期范围是否跨越本周和下周(部分在本周,部分在下周)const isOverlapping = (begin <= currentWeekEnd && end >= nextWeekStart);if (isCurrentWeek) {console.log('本周')return true;} else if (isNextWeek || isOverlapping) {console.log('下周')return true;} else {console.log('非本周或下周')return false;}}//是否属于当前周const isInRange = (bengin : any, end : any) => {const benginDate = new Date(bengin)const endDate = new Date(end)const currentDate = new Date()return currentDate >= benginDate && currentDate <= endDate}//日报点击const datePlanClick = (item : any) => {console.log(item)//展示周计划的时候需要校验周计划状态if (prop.showPlan) {if (item.dataState == null || item.dataState == 'undefined') {uni.showToast({title: '请先提交周计划',icon: 'none'})return}if (item.dataState == 0) {uni.showToast({title: '周计划审核中...',icon: 'none'})return}}//审批中 已通过if (item.dayStatus == 1 || item.dayStatus == 2) {uni.showToast({title: '跳转日报详情页面',icon: 'none',duration: 2000})} else {//未提交或者驳回if (!isDateInCurrentWeek(item.fullDate)) {uni.showToast({title: '只能提交本周内的日报',icon: 'none'})return}uni.showToast({title: '跳转日报填写页面',icon: 'none',duration: 2000})}}/*** 判断某个日期是否属于本周* @param {Date|string} targetDate - 目标日期(Date 对象或 "YYYY-MM-DD" 字符串)* @returns {boolean} - 是否属于本周*/function isDateInCurrentWeek(targetDate : any) : Boolean {// 如果传入的是字符串,转换为 Date 对象const date = typeof targetDate === 'string' ? new Date(targetDate) : new Date(targetDate);// 获取当前日期const today = new Date();// 计算本周一的日期(以周一作为一周的第一天)const currentWeekMonday = new Date(today);currentWeekMonday.setDate(today.getDate() - today.getDay() + 1); // getDay() 周日是 0,周一是 1,...,周六是 6currentWeekMonday.setHours(0, 0, 0, 0); // 清除时间部分,确保比较的是日期// 计算本周日的日期const currentWeekSunday = new Date(currentWeekMonday);currentWeekSunday.setDate(currentWeekMonday.getDate() + 6);currentWeekSunday.setHours(23, 59, 59, 999); // 设置为周日最后一刻// 判断目标日期是否在本周范围内return date >= currentWeekMonday && date <= currentWeekSunday;}//月份切换const monthSwitch = (e : any) => {console.log(e)setDate(e.year, e.month)}//日期转字符串格式const dateToStr = (date : any) => {var year = date.getFullYear() //年var month = date.getMonth() //月var day = date.getDate() //日var hours = date.getHours() //时var min = date.getMinutes() //分var second = date.getSeconds() //秒return year + "-" +((month + 1) > 9 ? (month + 1) : "0" + (month + 1)) + "-" +(day > 9 ? day : ("0" + day)) + " " +(hours > 9 ? hours : ("0" + hours)) + ":" +(min > 9 ? min : ("0" + min))}//字符串转日期const strToDate = (str : string) => {var date = new Date(str)return date.getTime()}
</script><style></style>
周计划日报数据示例
含用户信息 ,周计划信息和状态,日报信息和状态,是否休假
const planList = [{//计划编码和id"planId": 58,"planCode": "1015297758478274563",//本周开始 截止时间"beginDate": "2025-09-08","endDate": "2025-09-14","planPeriod": "2025-09-08~2025-09-14",//用户信息"userCode": "1009761934881456147","username": "员工001","departCode": "951784785749401608","departName": "xxx总公司",//周一到周日状态信息"monday": "2025-09-08","mondayStatus": 0,"tuesday": "2025-09-09","tuesdayStatus": 1,"wednesday": "2025-09-10","wednesdayStatus": 1,"thursday": "2025-09-11","thursdayStatus": 0,"friday": "2025-09-12","fridayStatus": 0,"saturday": "2025-09-13","saturdayStatus": 0,"sunday": "2025-09-14","sundayStatus": 0,//"weekWorkPlan": "工作计划","workSummary": '跟最后工作总结',"coordinateHelp": "需要协调需帮助",//附件列表 字符串 逗号分隔"attachIds": "",//创建更新时间"gmtCreate": "2025-09-03 08:27:25","gmtModified": "2025-09-03 08:27:25",//周计划状态 "dataState": 0,//是否请假 周一到周五"mondayIsHoliday": null,"tuesdayIsHoliday": 1,"wednesdayIsHoliday": 0,"thursdayIsHoliday": null,"fridayIsHoliday": null,"saturdayIsHoliday": null,"sundayIsHoliday": null
}]
uniapp市场连接 工作日历