微信小程序 工作日历 周计划日报 修改等提报和状态展示功能,支持h5,Android ,ios,基于uniapp,适配vue2和vue3

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 = canlender
    let 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.mondayStatus
          dayPlan.dayStatus = this.isEmptyWithZero(weekplan.mondayStatus) ? weekplan.mondayStatus : 2
          dayPlan.isHoliday = weekplan.mondayIsHoliday
          break;
        case 1:

          // dayPlan.dayStatus = weekplan.tuesdayStatus
          dayPlan.dayStatus = this.isEmptyWithZero(weekplan.tuesdayStatus) ? weekplan.tuesdayStatus : 2
          dayPlan.isHoliday = weekplan.tuesdayIsHoliday
          break;
        case 2:
          // dayPlan.dayStatus = weekplan.wednesdayStatus
          dayPlan.dayStatus = this.isEmptyWithZero(weekplan.wednesdayStatus) ? weekplan.wednesdayStatus : 2
          dayPlan.isHoliday = weekplan.wednesdayIsHoliday
          break;
        case 3:
          // dayPlan.dayStatus = weekplan.thursdayStatus
          dayPlan.dayStatus = this.isEmptyWithZero(weekplan.thursdayStatus) ? weekplan.thursdayStatus : 2
          dayPlan.isHoliday = weekplan.thursdayIsHoliday
          break;
        case 4:
          // dayPlan.dayStatus = weekplan.fridayStatus
          dayPlan.dayStatus = this.isEmptyWithZero(weekplan.fridayStatus) ? weekplan.fridayStatus : 2
          dayPlan.isHoliday = weekplan.fridayIsHoliday
          break;
        case 5:
          // dayPlan.dayStatus = weekplan.saturdayStatus
          dayPlan.dayStatus = this.isEmptyWithZero(weekplan.saturdayStatus) ? weekplan.saturdayStatus : 2
          dayPlan.isHoliday = weekplan.saturdayIsHoliday
          break;
        case 6:
          // dayPlan.dayStatus = weekplan.sundayStatus
          dayPlan.dayStatus = this.isEmptyWithZero(weekplan.sundayStatus) ? weekplan.sundayStatus : 2
          dayPlan.isHoliday = weekplan.sundayIsHoliday
          break;
      }

      // console.log('swich',dayPlan)
      weekTemp[parseInt(i / 7)].weeks[i % 7] = {
        ...canlender[i],
        ...dayPlan
      }
    }

    this.weeks = weekTemp
    console.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,...,周六是 6
		currentWeekMonday.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市场连接 工作日历

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木易 士心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值