Prechádzať zdrojové kódy

feat(checkIn):打卡历史记录新增下拉刷新和上拉加载功能
fix(clockIn):打卡页面业务逻辑修改,解决未授权打卡的问题
feat:页面导航栏数字角标

HMY 1 rok pred
rodič
commit
2e74c5cf5c

+ 19 - 0
api/mine.js

@@ -107,4 +107,23 @@ export function changePWD(params) {
 			}
 		}
 	})
+}
+
+//打卡历史记录
+export function getMyQDQtAttendance(params) {
+	return request({
+		url: preUrl,
+		method: 'post',
+		data: {
+			serviceId: 'hr_2018V01GetMyQDQtAttendance',
+			params: {
+				type: params.type,//1.不限时间2.限制时间
+				universalid: params.universalid,
+				ks_att_time: params.ks_att_time,
+				js_att_time: params.js_att_time,
+				pSize: params.pSize,
+				p: params.p
+			}
+		}
+	})
 }

+ 1 - 1
components/ygoa/messageList.vue

@@ -5,7 +5,7 @@
 				<template v-slot:title>
 					<uni-section :title="title" type="line" titleFontSize="1.3rem">
 						<template v-slot:right>
-							<uni-badge :text="unReadNum" style="margin-left: 5px;" v-if="unReadNum!==undefined&&unReadNum>0"></uni-badge>
+							<uni-badge :text="unReadNum" style="margin-left: -10px;" v-if="unReadNum!==undefined&&unReadNum>0"></uni-badge>
 						</template>
 					</uni-section>
 				</template>

+ 24 - 0
pages/contacts/index.vue

@@ -47,8 +47,12 @@ import headImg from "@/static/images/mine/headImg.jpg";
 import $tab from '@/plugins/tab.js'
 import { getContactAllUser } from '@/api/contacts.js'
 import { useUserStore } from '@/store/user.js'
+import { getUnProcessNum } from '@/api/process';
+import { getUnReadMessageNum } from '@/api/message';
 const userStore = useUserStore()
+
 onMounted(() => {
+	showTarBarBadge()
 	// 获取 通讯录 索引列表
 	let unitId = userStore.user.unitId
 	if ( unitId === 0 ) unitId = userStore.user.groupid
@@ -57,6 +61,26 @@ onMounted(() => {
 		getContactList(res.returnParams)
 	})
 })
+function showTarBarBadge(){
+		let unReadMsgNum=0;
+		let unProcessNum=0;
+		getUnProcessNum(userStore.user.useId,"").then(res=>{
+			unProcessNum=parseInt(res.returnParams.total, 10);
+			getUnReadMessageNum(userStore.user.useId).then(res=>{
+				unReadMsgNum=parseInt(res.returnParams, 10)+unProcessNum;
+				if(unReadMsgNum==0){
+					uni.removeTabBarBadge({
+						index:0
+					})
+				}else{
+					uni.setTabBarBadge({
+					  index: 0,
+					  text: String(unReadMsgNum)
+					})
+				}
+			})
+		})		
+	}
 // 索引列表
 const indexList = ref([])
 const itemArr = ref([])

+ 1 - 1
pages/message/index.vue

@@ -7,7 +7,7 @@
 				<template v-slot:title>
 					<uni-section title="待办" type="line" titleFontSize="1.3rem">
 						<template v-slot:right>
-							<uni-badge :text="unProcessNum" style="margin-left: 5px;" v-if="unProcessNum>0"></uni-badge>
+							<uni-badge :text="unProcessNum" style="margin-left: -10px;" v-if="unProcessNum>0"></uni-badge>
 						</template>
 					</uni-section>
 				</template>

+ 676 - 496
pages/mine/checkIn/checkIn.vue

@@ -10,7 +10,67 @@
 			</picker>
 		</view>
 
-		<!-- 数据统计区域 -->
+		<!-- 今日签到信息区域 -->
+		<view class="todayCheckIn" :class="{ 'show': shouldShow }">
+			<view class="check-in-container">
+				<text class="todayAttTitle">今日签到信息</text>
+				<view class="info-row">
+					<view>
+						<text class="ygoa-icon icon-date"></text>
+						<text class="value">日期:</text>
+					</view>
+
+					<text class="label">{{ todayData.day }}</text>
+				</view>
+				<view class="info-row">
+					<view>
+						<text class="ygoa-icon icon-day"></text>
+						<text class="value">晨签时间:</text>
+					</view>
+					<text class="label">{{ todayData.startTime || '未打卡' }} </text>
+				</view>
+				<view class="info-row">
+					<view>
+						<text class="ygoa-icon icon-night"></text>
+						<text class="value">晚签时间:</text>
+					</view>
+
+					<text class="label">{{ todayData.endTime || '未打卡' }} </text>
+				</view>
+
+			</view>
+			<view class="divider"></view>
+
+			<!-- 打卡记录 -->
+			<view class="container">
+				<view class="header">
+					<text class="clockRecordTitle">打卡记录</text>
+				</view>
+
+				<view class="content" style="height: 41vh;">
+					<z-paging :fixed="false" :default-page-size="pSize" default-page-no="1" @query="queryData"
+						ref="paging">
+						<view class="clockRecord" v-for="clockRecord in clockRecords" :key="clockRecord.date">
+							<text class="date">{{ clockRecord.date }}</text>
+							<view class="shifts">
+								<view class="shift">
+									<text class="shift-label">晨签:</text>
+									<text class="shift-time">{{ clockRecord.morning||'没有该记录'}}</text>
+								</view>
+								<view class="shift">
+									<text class="shift-label">晚签:</text>
+									<text class="shift-time">{{ clockRecord.evening ||'没有该记录'}}</text>
+								</view>
+							</view>
+						</view>
+					</z-paging>
+
+				</view>
+			</view>
+		</view>
+
+
+		<!-- 周,月数据统计区域 -->
 		<view class="statistics" :class="{ 'show': chartShow }">
 			<view class="statistic-card">
 				<view class="statistic-title">{{ selectedTimeRange }}考勤统计</view>
@@ -53,43 +113,6 @@
 			</view>
 		</view>
 
-		<!-- 今日签到信息区域 -->
-		<view class="todayCheckIn" :class="{ 'show': shouldShow }">
-			<view class="check-in-container">
-				<text class="title2">今日签到信息</text>
-				<view class="info-row">
-					<view>
-						<text class="ygoa-icon icon-date"></text>
-						<text class="value">日期:</text>
-					</view>
-
-					<text class="label">{{ todayData.day }}</text>
-				</view>
-				<view class="info-row">
-					<view>
-						<text class="ygoa-icon icon-day"></text>
-						<text class="value">晨签时间:</text>
-					</view>
-					<text class="label">{{ todayData.startTime || '未打卡' }} </text>
-				</view>
-				<view class="info-row">
-					<view>
-						<text class="ygoa-icon icon-night"></text>
-						<text class="value">晚签时间:</text>
-					</view>
-
-					<text class="label">{{ todayData.endTime || '未打卡' }} </text>
-				</view>
-				<view class="info-row">
-					<view>
-						<text class="ygoa-icon icon-checkInStatus"></text>
-						<text class="value">状态:</text>
-					</view>
-
-					<text class="label">{{ todayData.status }}</text>
-				</view>
-			</view>
-		</view>
 
 		<!-- 图表区域 -->
 		<view class="chart-container" :class="{ 'show': chartShow }">
@@ -105,484 +128,641 @@
 </template>
 
 <script setup>
-import { ref, onMounted, reactive } from 'vue';
-import { checkAttendance, getMyTotalCount } from '@/api/mine.js'
-import { useUserStore } from '@/store/user.js';
-const userStore = useUserStore();
-
-// 创建一个响应式对象记录今天的考勤数据
-const todayData = reactive({
-	day: '2024-11-11', // 当前日期
-	startTime: '', // 晨签到时间
-	endTime: '', // 晚签到时间
-	status: '未打卡' // 签到状态
-})
-
-// 控制今日签到信息和图表显示的状态
-const shouldShow = ref(true) // 今日签到信息是否显示
-const chartShow = ref(false) // 图表是否显示
-
-// 图表类型的响应式引用
-const chartsType = ref('')
-
-// 图表要填充的数据
-const chartData = ref({})
-
-// 图表配置选项
-const opts = ref({
-	color: ["#1890FF", "#91CB74", "#FAC858", "#EE6666", "#73C0DE", "#3CA272", "#FC8452", "#9A60B4",
-		"#ea7ccc"
-	], // 设定图表颜色
-	padding: [15, 15, 0, 5],
-	enableScroll: false, // 禁用滚动
-	legend: {}, // 图例设置
-	xAxis: {
-		disableGrid: true // 禁用网格线
-	},
-	yAxis: {
-		data: [{
-			min: 0 // y轴最小值
-		}]
-	},
-	extra: {
-		column: {
-			type: "group",
-			width: 30,
-			activeBgColor: "#000000",
-			activeBgOpacity: 0.08
+	import {
+		ref,
+		onMounted,
+		reactive
+	} from 'vue';
+	import {
+		checkAttendance,
+		getMyTotalCount,
+		getMyQDQtAttendance
+	} from '@/api/mine.js'
+	import {
+		useUserStore
+	} from '@/store/user.js';
+	const userStore = useUserStore();
+
+	// 创建一个响应式对象记录今天的考勤数据
+	const todayData = reactive({
+		day: '', // 当前日期
+		startTime: '', // 晨签到时间
+		endTime: '', // 晚签到时间
+	})
+
+
+
+	// 控制今日签到信息和图表显示的状态
+	const shouldShow = ref(true) // 今日签到信息是否显示
+	const chartShow = ref(false) // 图表是否显示
+
+	// 图表类型的响应式引用
+	const chartsType = ref('')
+
+	// 图表要填充的数据
+	const chartData = ref({})
+
+	// 图表配置选项
+	const opts = ref({
+		color: ["#1890FF", "#91CB74", "#FAC858", "#EE6666", "#73C0DE", "#3CA272", "#FC8452", "#9A60B4",
+			"#ea7ccc"
+		], // 设定图表颜色
+		padding: [15, 15, 0, 5],
+		enableScroll: false, // 禁用滚动
+		legend: {}, // 图例设置
+		xAxis: {
+			disableGrid: true // 禁用网格线
+		},
+		yAxis: {
+			data: [{
+				min: 0 // y轴最小值
+			}]
+		},
+		extra: {
+			column: {
+				type: "group",
+				width: 30,
+				activeBgColor: "#000000",
+				activeBgOpacity: 0.08
+			}
 		}
+	});
+
+	// 时间范围选择数组
+	const timeRanges = ref(['日', '周', '月']);
+	const selectedTimeRange = ref('日'); // 初始化选择的时间范围为“日”
+
+	// 考勤相关统计数据
+	const attendanceCount = ref(0); // 出勤次数
+	const goOutCount = ref(0); // 外出次数
+	const lateCount = ref(0); // 迟到次数
+	const leaveEarlyCount = ref(0); // 早退次数
+	const absenteeismCount = ref(0); // 缺勤次数
+
+	//用户id
+	const userId = userStore.user.useId; //拿到用户id
+	//当前周的周一日期
+	const thisMondayDate = ref('');
+
+	onMounted(() => {
+		initAttData(); //初始化日考勤数据
+	});
+
+	//初始化考勤数据
+	function initAttData() {
+		const nowDate = new Date();
+		todayData.day = formatDate(nowDate);
+		getthisMondayDate(nowDate);
+		getDayAttData();
+
 	}
-});
-
-// 时间范围选择数组
-const timeRanges = ref(['日', '周', '月']);
-const selectedTimeRange = ref('日'); // 初始化选择的时间范围为“日”
-
-// 考勤相关统计数据
-const attendanceCount = ref(0); // 出勤次数
-const goOutCount = ref(0); // 外出次数
-const lateCount = ref(0); // 迟到次数
-const leaveEarlyCount = ref(0); // 早退次数
-const absenteeismCount = ref(0); // 缺勤次数
-
-//用户id
-const userId = ref('');
-//当前周的周一日期
-const thisMondayDate = ref('');
-
-onMounted(() => {
-	userId.value = userStore.user.useId;//拿到用户id
-	initAttData(); //初始化日考勤数据
-});
-
-//初始化考勤数据
-function initAttData() {
-	const nowDate = new Date();
-	todayData.day = formatDate(nowDate);
-	getDayAttData();
-	getthisMondayDate();
-}
-
-//格式化日期
-function formatDate(date) {
-	const year = date.getFullYear(); // 获取年份
-	const month = date.getMonth() + 1; // 获取月份
-	const day = date.getDate(); // 获取日期
-	// 格式化月份和日期为两位数
-	const formattedMonth = month < 10 ? '0' + month : month;
-	const formattedDay = day < 10 ? '0' + day : day;
-	return `${year}-${formattedMonth}-${formattedDay}`;
-}
-
-//获取日考勤数据
-function getDayAttData() {
-	const params = {
-		universalid: userId.value,
-		rizi: todayData.day
-	}
-	checkAttendance(params).then(res => {
-		if ("success" == res.returnMsg) {
-			const attList = res.returnParams.list;
-			const time1 = attList.find(item => item.att_type_id === '1');
-			const time2 = attList.filter(item => item.att_type_id === '2').pop();
-			if (time1 !== undefined) {
-				todayData.startTime = time1.att_time.split(' ')[1];
-				todayData.status = '早签完成'
-			}
-			if (time2 !== undefined) {
-				todayData.endTime = time2.att_time.split(' ')[1];
-				todayData.status = '晚签完成'
+
+	//格式化日期
+	function formatDate(date) {
+		const year = date.getFullYear(); // 获取年份
+		const month = date.getMonth() + 1; // 获取月份
+		const day = date.getDate(); // 获取日期
+		// 格式化月份和日期为两位数
+		const formattedMonth = month < 10 ? '0' + month : month;
+		const formattedDay = day < 10 ? '0' + day : day;
+		return `${year}-${formattedMonth}-${formattedDay}`;
+	}
+
+	//获取日考勤数据
+	function getDayAttData() {
+		const params = {
+			universalid: userId,
+			rizi: todayData.day
+		}
+		checkAttendance(params).then(res => {
+			if ("success" == res.returnMsg) {
+				const attList = res.returnParams.list;
+				const time1 = attList.find(item => item.att_type_id === '1');
+				const time2 = attList.filter(item => item.att_type_id === '2').pop();
+				if (time1 !== undefined) {
+					todayData.startTime = time1.att_time.split(' ')[1];
+					// todayData.status = '早签完成'
+				}
+				if (time2 !== undefined) {
+					todayData.endTime = time2.att_time.split(' ')[1];
+					// todayData.status = '晚签完成'
+				}
 			}
+		})
+	}
+
+	const paging = ref(null)
+	const pSize = ref(5)
+
+	function complete(list, total, pageNo) {
+		console.log('000', pageNo);
+		if (pageNo == 1) {
+			paging.value.complete(list);
+			return
 		}
-	})
-}
-
-// 时间范围切换事件
-function onTimeRangeChange(event) {
-	const selectedIndex = event.detail.value;
-	selectedTimeRange.value = timeRanges.value[selectedIndex]; // 设置选择的时间范围(日周月)
-	// fetchAttendanceData(); // 获取考勤数据
-	// 根据选择的时间范围更新展示内容
-	switch (selectedTimeRange.value) {
-		case '日':
-			getDayAttData();
-			showDay(); // 显示今日考勤
-			break;
-		case '周':
-			chartsType.value = 'pie'; // 设置图表类型为饼图
-			fetchWeekAttData().then(message => {
-				console.log(message);
-				showWeekAndMonth();
-				updateChart(message);
-			})
-				.catch(error => {
-					console.error(error); // 如果失败,打印错误消息
-				});
-			break;
-		case '月':
-			chartsType.value = 'column'; // 设置图表类型为柱状图
-			fetchMonthAttData().then(message => {
-				console.log('message', message);
-				showWeekAndMonth();
-				updateChart(message);
-			})
-				.catch(error => {
-					console.error(error); // 如果失败,打印错误消息
-				});
-			break;
-	}
-};
-
-// 显示今日考勤数据
-function showDay() {
-	shouldShow.value = true; // 显示今日签到信息
-	chartShow.value = false; // 隐藏图表
-}
-
-// 显示周或者月考勤
-function showWeekAndMonth() {
-	shouldShow.value = false; // 隐藏今日签到信息
-	chartShow.value = true; // 显示图表
-}
-
-
-//计算本周周一日期
-function getthisMondayDate() {
-	const today = new Date();
-	const dayOfWeek = today.getDay(); // 0 (周日) 到 6 (周六)
-	const dayOfMonth = today.getDate();
-	// 计算本周周一的日期
-	const offset = dayOfWeek === 0 ? -6 : 1; // 如果今天是周日,则偏移量为-6,否则为1
-	const thisMonday = new Date(today);
-	thisMonday.setDate(dayOfMonth - dayOfWeek + offset);
-	thisMondayDate.value = formatDate(thisMonday);
-}
-
-//获取周考勤记录
-function fetchWeekAttData() {
-	return new Promise((resolve, reject) => {
+		// 防止重复获取最后一次信息
+		if (pSize.value * pageNo < total) {
+			paging.value.complete(list)
+		} else {
+			console.log('complete([])');
+			paging.value.complete([])
+		}
+	}
+	//日考勤历史记录
+	const clockRecords = ref([])
+
+	//获取日考勤历史
+	function getDayAttHistory() {
 		const params = {
-			staffId: userId.value,
-			start_date: thisMondayDate.value,
-			end_date: todayData.day
+			type: 1, //不设时间区间
+			universalid: userId,
+			ks_att_time: '',
+			js_att_time: '',
+			pSize: pSize.value,
+			p: 1
 		}
-		getMyTotalCount(params).then(res => {
-			const myWeekAttData = res.returnParams;
-			const mockData = {
-				series: [{
-					data: [{
-						"name": "出勤",
-						"value": myWeekAttData.type0,
-						"labelText": "出勤:" + myWeekAttData.type0 + "次"
-					},
-					{
-						"name": "外出",
-						"value": myWeekAttData.type1
-					},
-					{
-						"name": "公休",
-						"value": myWeekAttData.type2
-					},
-					{
-						"name": "未排班",
-						"value": myWeekAttData.type3,
-					},
-					{
-						"name": "迟到",
-						"value": myWeekAttData.type4
-					},
-					{
-						"name": "早退",
-						"value": myWeekAttData.type5
-					},
-					{
-						"name": "缺勤",
-						"value": myWeekAttData.type6
-					}
-					]
-				}],
-
-			};
-			const weekData = mockData.series[0].data;
-			attendanceCount.value = weekData[0].value;
-			goOutCount.value = weekData[2].value;
-			lateCount.value = weekData[4].value;
-			leaveEarlyCount.value = weekData[5].value;
-			absenteeismCount.value = weekData[6].value;
-			resolve(mockData)
-		}).catch(error => {
-			reject(error)
+		getMyQDQtAttendance(params).then(({
+			returnParams
+		}) => {
+			const list = returnParams.list;
+			const records = [];
+			list.forEach(item => {
+				const record = {
+					date: item.att_date.substring(0, 10),
+					morning: item.time.split(',')[item.type.split(',').indexOf("1")],
+					evening: item.time.split(',')[item.type.split(',').indexOf("2")],
+				};
+				records.push(record);
+			});
+			clockRecords.value = records;
+			complete(clockRecords.value, returnParams.total, returnParams.current)
 		})
-	})
+	}
 
-}
-
-// 获取月考勤记录
-function fetchMonthAttData() {
-	return new Promise((resolve, reject) => {
-		const weekNodeList = [];
-		weekNodeList.unshift(thisMondayDate.value, todayData.day);
-		while (weekNodeList.length !== 8) {
-			const weekNode = getOneDaysAgo(weekNodeList[0]);
-			weekNodeList.unshift(weekNode);
-			weekNodeList.unshift(getSixDaysAgo(weekNode));
+	// 刷新
+	function queryData(pageNo, pSize, queryType) {
+		switch (queryType) {
+			case 0: // 下拉刷新
+			case 1: // 初始加载
+				getDayAttHistory()
+				break
+			case 3: // 上拉加载
+				scrollQuery(pageNo, pSize)
+				break
+			default: // 默认刷新
+				getDayAttHistory()
+				break
 		}
+	}
 
-		const data1 = [];
-		const data2 = [];
-		const data3 = [];
-		const dataFetchPromises = [];// 存储所有数据请求的promise
-
-		for (let i = 0; i < weekNodeList.length - 1; i += 2) {
-			const params = {
-				staffId: userId.value,
-				start_date: weekNodeList[i],
-				end_date: weekNodeList[i + 1]
-			};
-			const fetchPromise = getMyTotalCount(params).then(res => {
-				// for (const type in res.returnParams) {
-				// 	console.log('type', type);
-				// }
-				console.log('res.returnParams', res.returnParams);
-
-				data1.push(res.returnParams.type0);
-				data2.push(res.returnParams.type1);
-				data3.push(res.returnParams.type4);
+	function scrollQuery(pageNo, pSize) {
+		const params = {
+			type: 1, //不设时间区间
+			universalid: userId,
+			ks_att_time: '',
+			js_att_time: '',
+			pSize: pSize,
+			p: pageNo
+		}
+		getMyQDQtAttendance(params).then(({
+			returnParams
+		}) => {
+
+			const list = returnParams.list.map(item => {
+				return {
+					date: item.att_date.substring(0, 10),
+					morning: item.time.split(',')[item.type.split(',').indexOf("1")],
+					evening: item.time.split(',')[item.type.split(',').indexOf("2")],
+				}
 			});
-			dataFetchPromises.push(fetchPromise);
+			console.log('list', list);
+
+			// clockRecords.value.push(...list);
+			// complete(list,returnParams.total,pageNo)
+			
+			// 去重逻辑
+			const existingDates = new Set(clockRecords.value.map(record => record.date));
+			const newRecords = list.filter(item => !existingDates.has(item.date));
+
+			// 更新 clockRecords
+			clockRecords.value.push(...newRecords);
+
+			// 调用 complete 函数,传入新记录和总数
+			complete(newRecords, returnParams.total, pageNo);
+
+		})
+	}
+
+	// 时间范围切换事件
+	function onTimeRangeChange(event) {
+		const selectedIndex = event.detail.value;
+		selectedTimeRange.value = timeRanges.value[selectedIndex]; // 设置选择的时间范围(日周月)
+		// fetchAttendanceData(); // 获取考勤数据
+		// 根据选择的时间范围更新展示内容
+		switch (selectedTimeRange.value) {
+			case '日':
+				getDayAttData();
+				showDay(); // 显示今日考勤
+				break;
+			case '周':
+				chartsType.value = 'pie'; // 设置图表类型为饼图
+				fetchWeekAttData().then(message => {
+						console.log(message);
+						showWeekAndMonth();
+						updateChart(message);
+					})
+					.catch(error => {
+						console.error(error); // 如果失败,打印错误消息
+					});
+				break;
+			case '月':
+				chartsType.value = 'column'; // 设置图表类型为柱状图
+				fetchMonthAttData().then(message => {
+						console.log('message', message);
+						showWeekAndMonth();
+						updateChart(message);
+					})
+					.catch(error => {
+						console.error(error); // 如果失败,打印错误消息
+					});
+				break;
 		}
+	};
 
-		// 等待所有数据请求完成
-		Promise.all(dataFetchPromises).then(() => {
+	// 显示今日考勤数据
+	function showDay() {
+		shouldShow.value = true; // 显示今日签到信息
+		chartShow.value = false; // 隐藏图表
+	}
+
+	// 显示周或者月考勤
+	function showWeekAndMonth() {
+		shouldShow.value = false; // 隐藏今日签到信息
+		chartShow.value = true; // 显示图表
+	}
+
+
+	//计算本周周一日期
+	function getthisMondayDate(today) {
+		const dayOfWeek = today.getDay(); // 0 (周日) 到 6 (周六)
+		const dayOfMonth = today.getDate();
+		// 计算本周周一的日期
+		const offset = dayOfWeek === 0 ? -6 : 1; // 如果今天是周日,则偏移量为-6,否则为1
+		const thisMonday = new Date(today);
+		thisMonday.setDate(dayOfMonth - dayOfWeek + offset);
+		thisMondayDate.value = formatDate(thisMonday);
+	}
+
+	//获取周考勤记录
+	function fetchWeekAttData() {
+		return new Promise((resolve, reject) => {
 			const params = {
-				staffId: userId.value,
-				start_date: weekNodeList[0],
-				end_date: weekNodeList[weekNodeList.length - 1]
-			};
-			return getMyTotalCount(params);
-		}).then(res => {
-			const myMonthAttData = res.returnParams;
-			attendanceCount.value = myMonthAttData.type0;
-			goOutCount.value = myMonthAttData.type2;
-			lateCount.value = myMonthAttData.type4;
-			leaveEarlyCount.value = myMonthAttData.type5;
-			absenteeismCount.value = myMonthAttData.type6;
-
-			const mockData = {
-				categories: ["第1周", "第2周", "第3周", "第4周"],
-				series: [{
-					name: "出勤",
-					data: data1
-				}, {
-					name: "出差",
-					data: data2
-				}, {
-					name: "迟到",
-					data: data3
-				}]
-			};
-			// console.log(data1); // 打印data1检查内容
-			resolve(mockData);
-		}).catch(error => {
-			reject(error);
-		});
-	});
-}
+				staffId: userId,
+				start_date: thisMondayDate.value,
+				end_date: todayData.day
+			}
+			getMyTotalCount(params).then(res => {
+				const myWeekAttData = res.returnParams;
+				const mockData = {
+					series: [{
+						data: [{
+								"name": "出勤",
+								"value": myWeekAttData.type0,
+								"labelText": "出勤:" + myWeekAttData.type0 + "次"
+							},
+							{
+								"name": "外出",
+								"value": myWeekAttData.type1
+							},
+							{
+								"name": "公休",
+								"value": myWeekAttData.type2
+							},
+							{
+								"name": "未排班",
+								"value": myWeekAttData.type3,
+							},
+							{
+								"name": "迟到",
+								"value": myWeekAttData.type4
+							},
+							{
+								"name": "早退",
+								"value": myWeekAttData.type5
+							},
+							{
+								"name": "缺勤",
+								"value": myWeekAttData.type6
+							}
+						]
+					}],
+
+				};
+				const weekData = mockData.series[0].data;
+				attendanceCount.value = weekData[0].value;
+				goOutCount.value = weekData[2].value;
+				lateCount.value = weekData[4].value;
+				leaveEarlyCount.value = weekData[5].value;
+				absenteeismCount.value = weekData[6].value;
+				resolve(mockData)
+			}).catch(error => {
+				reject(error)
+			})
+		})
 
+	}
 
-//获取六天前的日期
-function getSixDaysAgo(dateStr) {
-	const date = new Date(dateStr);
-	date.setDate(date.getDate() - 6);
-	return date.toISOString().split('T')[0]; // 返回格式为'YYYY-MM-DD'的字符串
-}
-//获取一天前的日期
-function getOneDaysAgo(dateStr) {
-	const date = new Date(dateStr);
-	date.setDate(date.getDate() - 1);
-	return date.toISOString().split('T')[0]; // 返回格式为'YYYY-MM-DD'的字符串
-}
+	// 获取月考勤记录
+	function fetchMonthAttData() {
+		return new Promise((resolve, reject) => {
+			const weekNodeList = [];
+			weekNodeList.unshift(thisMondayDate.value, todayData.day);
+			while (weekNodeList.length !== 8) {
+				const weekNode = getOneDaysAgo(weekNodeList[0]);
+				weekNodeList.unshift(weekNode);
+				weekNodeList.unshift(getSixDaysAgo(weekNode));
+			}
 
+			const data1 = [];
+			const data2 = [];
+			const data3 = [];
+			const dataFetchPromises = []; // 存储所有数据请求的promise
+
+			for (let i = 0; i < weekNodeList.length - 1; i += 2) {
+				const params = {
+					staffId: userId,
+					start_date: weekNodeList[i],
+					end_date: weekNodeList[i + 1]
+				};
+				const fetchPromise = getMyTotalCount(params).then(res => {
+					// for (const type in res.returnParams) {
+					// 	console.log('type', type);
+					// }
+					console.log('res.returnParams', res.returnParams);
+
+					data1.push(res.returnParams.type0);
+					data2.push(res.returnParams.type1);
+					data3.push(res.returnParams.type4);
+				});
+				dataFetchPromises.push(fetchPromise);
+			}
 
-// 更新图表数据
-function updateChart(res) {
-	chartData.value = JSON.parse(JSON.stringify(res)); // 更新图表数据
-}
+			// 等待所有数据请求完成
+			Promise.all(dataFetchPromises).then(() => {
+				const params = {
+					staffId: userId,
+					start_date: weekNodeList[0],
+					end_date: weekNodeList[weekNodeList.length - 1]
+				};
+				return getMyTotalCount(params);
+			}).then(res => {
+				const myMonthAttData = res.returnParams;
+				attendanceCount.value = myMonthAttData.type0;
+				goOutCount.value = myMonthAttData.type2;
+				lateCount.value = myMonthAttData.type4;
+				leaveEarlyCount.value = myMonthAttData.type5;
+				absenteeismCount.value = myMonthAttData.type6;
+
+				const mockData = {
+					categories: ["第1周", "第2周", "第3周", "第4周"],
+					series: [{
+						name: "出勤",
+						data: data1
+					}, {
+						name: "出差",
+						data: data2
+					}, {
+						name: "迟到",
+						data: data3
+					}]
+				};
+				// console.log(data1); // 打印data1检查内容
+				resolve(mockData);
+			}).catch(error => {
+				reject(error);
+			});
+		});
+	}
+
+
+	//获取六天前的日期
+	function getSixDaysAgo(dateStr) {
+		const date = new Date(dateStr);
+		date.setDate(date.getDate() - 6);
+		return date.toISOString().split('T')[0]; // 返回格式为'YYYY-MM-DD'的字符串
+	}
+	//获取一天前的日期
+	function getOneDaysAgo(dateStr) {
+		const date = new Date(dateStr);
+		date.setDate(date.getDate() - 1);
+		return date.toISOString().split('T')[0]; // 返回格式为'YYYY-MM-DD'的字符串
+	}
 
+
+	// 更新图表数据
+	function updateChart(res) {
+		chartData.value = JSON.parse(JSON.stringify(res)); // 更新图表数据
+	}
 </script>
 
 
-<style scoped>
-@import "@/static/font/ygoa/iconfont.css";
-
-.ygoa-icon {
-	margin-right: 0.5rem;
-	font-size: 2.1rem;
-	vertical-align: middle;
-	/* 确保图标与文本竖直居中 */
-}
-
-.attendance-page {
-	padding: 20px;
-	background-color: #f9f9f9;
-}
-
-.header {
-	display: flex;
-	justify-content: space-between;
-	align-items: center;
-	margin-bottom: 20px;
-}
-
-.title {
-	font-size: 24px;
-	font-weight: bold;
-	color: #333;
-}
-
-.picker {
-	border: 1px solid #3498db;
-	border-radius: 5px;
-	padding: 10px;
-	background-color: #ecf6fc;
-	color: #3498db;
-}
-
-.statistics {
-	display: flex;
-	justify-content: center;
-}
-
-.statistic-card {
-	background: white;
-	border-radius: 10px;
-	padding: 20px;
-	box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
-	/* width: 100%; */
-	max-width: 600px;
-}
-
-.statistic-title {
-	text-align: center;
-	font-size: 20px;
-	font-weight: bold;
-	color: #333;
-}
-
-.statistic-item {
-	display: flex;
-	justify-content: space-between;
-	border-bottom: 1px solid #eee;
-	padding: 10px 0;
-}
-
-.label {
-	color: #666;
-}
-
-.value {
-	font-size: 18px;
-	font-weight: bold;
-	color: #333;
-}
-
-.value,
-.label {
-	line-height: 50rpx;
-	/* 与图标高度一致,确保垂直对齐 */
-}
-
-.chart-container {
-	margin-top: 20px;
-}
-
-.chart-title {
-	font-size: 20px;
-	font-weight: bold;
-	text-align: center;
-	margin-bottom: 10px;
-	color: #333;
-}
-
-.charts-box {
-	width: 100%;
-	height: 300px;
-}
-
-
-.todayCheckIn {
-
-	background-color: #ffffff;
-	padding: 20px;
-	box-sizing: border-box;
-}
-
-
-
-.check-in-container {
-	width: 100%;
-	height: 100%;
-	display: flex;
-	flex-direction: column;
-	align-items: center;
-	justify-content: center;
-}
-
-.title2 {
-	font-size: 22px;
-	font-weight: bold;
-	margin-bottom: 20px;
-}
-
-
-.info-row {
-	width: 100%;
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-	margin-bottom: 10px;
-}
-
-
-.todayCheckIn,
-.chart-container,
-.statistics {
-	/* 默认隐藏 */
-	display: none;
-}
-
-/* 当需要显示时,可以添加一个额外的类 */
-.todayCheckIn.show,
-.chart-container.show,
-.statistics.show {
-	display: block;
-}
-
-.icon {
-	width: 50rpx;
-	height: 50rpx;
-	margin-right: 20rpx;
-	vertical-align: middle;
-	/* 确保图标与文本竖直居中 */
-}
+<style lang="scss" scoped>
+	@import "@/static/font/ygoa/iconfont.css";
+
+	.ygoa-icon {
+		margin-right: 0.5rem;
+		font-size: 2.1rem;
+		vertical-align: middle;
+		/* 确保图标与文本竖直居中 */
+	}
+
+	.attendance-page {
+		padding: 20px;
+		background-color: #f9f9f9;
+	}
+
+	.header {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		margin-bottom: 20px;
+
+		.clockRecordTitle {
+			font-size: 1.25rem;
+			margin: auto;
+		}
+	}
+
+	.title {
+		font-size: 24px;
+		font-weight: bold;
+		color: #333;
+	}
+
+	.picker {
+		border: 1px solid #3498db;
+		border-radius: 5px;
+		padding: 10px;
+		background-color: #ecf6fc;
+		color: #3498db;
+	}
+
+	.statistics {
+		display: flex;
+		justify-content: center;
+	}
+
+	.statistic-card {
+		background: white;
+		border-radius: 10px;
+		padding: 20px;
+		box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+		/* width: 100%; */
+		max-width: 600px;
+	}
+
+	.statistic-title {
+		text-align: center;
+		font-size: 20px;
+		font-weight: bold;
+		color: #333;
+	}
+
+	.statistic-item {
+		display: flex;
+		justify-content: space-between;
+		border-bottom: 1px solid #eee;
+		padding: 10px 0;
+	}
+
+	.label {
+		color: #666;
+	}
+
+	.value {
+		font-size: 18px;
+		font-weight: bold;
+		color: #333;
+	}
+
+	.value,
+	.label {
+		line-height: 50rpx;
+		/* 与图标高度一致,确保垂直对齐 */
+	}
+
+	.chart-container {
+		margin-top: 20px;
+	}
+
+	.chart-title {
+		font-size: 20px;
+		font-weight: bold;
+		text-align: center;
+		margin-bottom: 10px;
+		color: #333;
+	}
+
+	.charts-box {
+		width: 100%;
+		height: 300px;
+	}
+
+
+	.todayCheckIn {
+		background-color: #ffffff;
+		padding: 20px;
+		box-sizing: border-box;
+		border-radius: 10px;
+		box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+	}
+
+
+
+	.check-in-container {
+		width: 100%;
+		height: 100%;
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.todayAttTitle {
+		font-size: 22px;
+		font-weight: bold;
+		margin-bottom: 20px;
+	}
+
+
+	.info-row {
+		width: 100%;
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		margin-bottom: 10px;
+	}
+
+
+	.todayCheckIn,
+	.chart-container,
+	.statistics {
+		/* 默认隐藏 */
+		display: none;
+	}
+
+	/* 当需要显示时,可以添加一个额外的类 */
+	.todayCheckIn.show,
+	.chart-container.show,
+	.statistics.show {
+		display: block;
+	}
+
+	.icon {
+		width: 50rpx;
+		height: 50rpx;
+		margin-right: 20rpx;
+		vertical-align: middle;
+		/* 确保图标与文本竖直居中 */
+	}
+
+
+
+
+
+	.clockRecord {
+		margin-bottom: 20px;
+		padding: 10px;
+		border: 1px solid #ccc;
+		border-radius: 8px;
+	}
+
+	.date {
+		font-size: 16px;
+		font-weight: bold;
+		margin-bottom: 5px;
+	}
+
+	.name {
+		font-size: 14px;
+		color: #666;
+		margin-bottom: 10px;
+	}
+
+	.divider {
+		border-bottom: 5px dashed #ccc; //虚线
+		margin: 10px 0;
+	}
+
+
+
+	.shift-label {
+		font-size: 14px;
+		color: #333;
+	}
+
+	.shift-time {
+		font-size: 14px;
+		color: #333;
+	}
 </style>

+ 73 - 51
pages/mine/clockIn/clockIn.vue

@@ -18,7 +18,8 @@
 				<text class="ygoa-icon icon-afterWork"></text>
 				<text class="title">下班</text>
 				<text class="time">{{ signOutTime || '未打卡' }}</text>
-				<text class="signStatus" v-if="!isSignOutStatusDisabled">({{signOutStatusName}})</text>
+				<text class="signStatus" v-if="!isSignOutStatusDisabled"
+					style="color: #e64340;">({{signOutStatusName}})</text>
 			</view>
 			<view class="record-item" @click="getAddress">
 				<text class="ygoa-icon icon-location"></text>
@@ -33,8 +34,10 @@
 		</atl-map>
 		<!-- 打卡按钮 -->
 		<view class="footer">
-			<button type="default" @click="signInOrOut" style="background-color: #3c9cff; color: #fcfcfc;" v-if="signName=='上班签到'">上班签到</button>	
-			<button type="default" @click="signInOrOut" style="background-color: #1aad19; color: #fcfcfc;" v-else-if="signName=='下班签退'">下班签退</button>	
+			<button type="default" @click="signInOrOut" style="background-color: #3c9cff; color: #fcfcfc;"
+				v-if="signName=='上班签到'">上班签到</button>
+			<button type="default" @click="signInOrOut" style="background-color: #1aad19; color: #fcfcfc;"
+				v-else-if="signName=='下班签退'">下班签退</button>
 		</view>
 	</view>
 </template>
@@ -145,23 +148,25 @@
 				const time1 = attList.find(item => item.att_type_id === '1');
 				//拿到所有签退数据后,用pop取最后一个
 				const time2 = attList.filter(item => item.att_type_id === '2').pop();
-				console.log('time2',time2);
+				console.log('time2', time2);
 				if (time1 !== undefined) {
 					// console.log('getTime1',time1);
 					signInTime.value = time1.att_time.split(' ')[1];
 					signName.value = '下班签退';
-					if (Array.isArray(config.lateTimeRange) && isTimeInRange(signInTime.value, config.lateTimeRange[0],'23:59:59')) {
+					if (Array.isArray(config.lateTimeRange) && isTimeInRange(signInTime.value, config
+							.lateTimeRange[0], '23:59:59')) {
 						isSignInStatusDisabled.value = false; //迟到
 					}
-				}else{
+				} else {
 					signName.value = '上班签到';
 				}
 				if (time2 !== undefined) {
 					signOutTime.value = time2.att_time.split(' ')[1];
-					if (Array.isArray(config.signOutTimeRange) && isTimeInRange(signOutTime.value, "00:00:00",config.signOutTimeRange[0])) {
+					if (Array.isArray(config.signOutTimeRange) && isTimeInRange(signOutTime.value, "00:00:00",
+							config.signOutTimeRange[0])) {
 						isSignOutStatusDisabled.value = false; //早退
-					}else{
-						isSignOutStatusDisabled.value = true;//隐藏早退状态
+					} else {
+						isSignOutStatusDisabled.value = true; //隐藏早退状态
 					}
 				}
 			}
@@ -185,13 +190,14 @@
 		const now = getNowTime();
 		//判断打卡时间是否符合
 		if (!isTimeInRange(now, ...config.signInTimeRange)) {
-			$modal.msg('不在签到时间8:30--10:00内,请前往补卡')
+			$modal.msg('不在签到时间8:30--9:30内,请前往补卡')
 			return;
 		}
 		// attType.value=1;
-		var attType = 1;
-		getAddress();
-		clockIn(attType)
+		const signIn = 1;
+		getAddress().then(() => {
+			clockIn(signIn); 
+		});
 	};
 
 	// 下班签退
@@ -203,13 +209,15 @@
 		if (!isTimeInRange(now, ...config.signOutTimeRange)) {
 			$modal.confirm('当前非正常签退时间,是否继续?').then(res => {
 				if (res) {
-					getAddress();
-					clockIn(signOut); // 执行打卡并获取结果
+					getAddress().then(() => {
+						clockIn(signOut); // 执行打卡并获取结果
+					});
 				}
 			})
 		} else {
-			getAddress();
-			clockIn(signOut);
+			getAddress().then(() => {
+				clockIn(signOut); 
+			});
 		}
 
 
@@ -261,38 +269,41 @@
 					// 如果用户未授权
 					if (!res.authSetting['scope.userLocation']) {
 						$modal.confirm('需要您授权获取地理位置信息').then(res => {
-							if (res) {
-								// 打开权限设置页面
-								uni.openSetting({
-									success: (settingData) => {
-										if (settingData.authSetting[
-												'scope.userLocation']) {
-											$modal.msg('授权后请重新打开此页面')
-											reject(new Error("用户未授权"));
+								if (res) {
+									// 打开权限设置页面
+									uni.openSetting({
+										success: (settingData) => {
+											if (settingData.authSetting[
+													'scope.userLocation']) {
+												$modal.msg('授权后请重新打开此页面')
+												// reject("用户未授权");
+											}
 										}
-									}
-								});
-							} else {
-								uni.showToast({
-									title: '获取地理位置授权失败',
-									icon: 'none',
-									success: () => {
-										// 返回上一页
-										setTimeout(() => {
-											$tab.navigateBack()
-										}, 1000);
-									}
-								});
-								reject(new Error("用户未授权"));
-							}
-						});
+									});
+								}
+							})
+							.catch(err => {
+								//用户点击取消
+								if (!err) {
+									uni.showToast({
+										title: '获取地理位置授权失败',
+										icon: 'none',
+										success: () => {
+											// 返回上一页
+											setTimeout(() => {
+												$tab.navigateBack()
+											}, 1000);
+										}
+									});
+									// reject("用户未授权");
+								}
+							})
 					} else {
 						// 已授权,获取位置
 						fetchLocation(resolve, reject);
 					}
 				},
 				fail(err) {
-					console.error('获取设置失败', err);
 					reject(err); // 拒绝 Promise
 				}
 			});
@@ -310,7 +321,7 @@
 			fail: (err) => {
 				if (err.errMsg.includes("频繁调用")) {
 					$modal.msg('请勿频繁调用');
-					reject(new Error("频繁调用错误"));
+					// reject("频繁调用错误");
 					return;
 				}
 				console.log('getLocationErr', err);
@@ -322,13 +333,24 @@
 
 	// 获取当前位置地址
 	function getAddress() {
-		getlocation()
-			.then(() => {
-				tranLocationToAddress(); // 执行地址转换
-			})
-			.catch(err => {
-				console.error('获取地址失败', err);
-			});
+		// getlocation()
+		// 	.then(() => {
+		// 		tranLocationToAddress(); // 执行地址转换
+		// 	})
+		// 	.catch(err => {
+		// 		console.error('获取地址失败', err);
+		// 	});
+		return new Promise((resolve, reject) => {
+			getlocation()
+				.then(() => {
+					tranLocationToAddress(); // 执行地址转换
+					resolve(); // 地址获取成功
+				})
+				.catch(err => {
+					// console.error('获取地址失败', err);
+					reject(err); // 地址获取失败
+				});
+		});
 	}
 
 	// 经纬度转地址
@@ -339,7 +361,7 @@
 				address.value = res.result.address; // 保存地址
 			})
 			.catch(err => {
-				console.error('地址转换请求失败', err); // 请求错误处理
+				console('地址转换请求失败', err); // 请求错误处理
 			})
 	}
 

+ 28 - 2
pages/process/index.vue

@@ -45,10 +45,36 @@
 
 <script setup lang="ts">
 import processList from '@/components/ygoa/processList.vue'
-import { reactive, ref } from 'vue';
+import { reactive, ref,onMounted } from 'vue';
 import $tab from '@/plugins/tab.js'
-import { getUserProcess, getUserProcessed, getUserProcessing, getUserAllProcess } from '@/api/process';
+import { getUserProcess, getUserProcessed, getUserProcessing, getUserAllProcess,getUnProcessNum } from '@/api/process';
 import { useUserStore } from '@/store/user';
+import { getUnReadMessageNum } from '@/api/message';
+
+onMounted(()=>{
+	showTarBarBadge();
+})
+function showTarBarBadge(){
+		let unReadMsgNum=0;
+		let unProcessNum=0;
+		getUnProcessNum(userStore.user.useId,"").then(res=>{
+			unProcessNum=parseInt(res.returnParams.total, 10);
+			getUnReadMessageNum(userStore.user.useId).then(res=>{
+				unReadMsgNum=parseInt(res.returnParams, 10)+unProcessNum;
+				if(unReadMsgNum==0){
+					uni.removeTabBarBadge({
+						index:0
+					})
+				}else{
+					uni.setTabBarBadge({
+					  index: 0,
+					  text: String(unReadMsgNum)
+					})
+				}
+			})
+		})
+		
+	}
 const userStore = useUserStore();
 // 分段器选项
 const items = reactive(['我的', '待办', '在办', '办结'])

+ 24 - 1
pages/work/index.vue

@@ -123,12 +123,35 @@ import $tab from "@/plugins/tab.js"
 import { getUserInfo } from '@/utils/auth'
 import { useUserStore } from '@/store/user.js'
 import { getProcessList } from '@/api/work.js'
-
+import { getUnProcessNum } from "@/api/process"
+import { getUnReadMessageNum } from "@/api/message"
 const userStore = useUserStore()
 
 onMounted(() => {
 	initProcessList()
+	showTarBarBadge()
 })
+
+function showTarBarBadge(){
+		let unReadMsgNum=0;
+		let unProcessNum=0;
+		getUnProcessNum(userStore.user.useId,"").then(res=>{
+			unProcessNum=parseInt(res.returnParams.total, 10);
+			getUnReadMessageNum(userStore.user.useId).then(res=>{
+				unReadMsgNum=parseInt(res.returnParams, 10)+unProcessNum;
+				if(unReadMsgNum==0){
+					uni.removeTabBarBadge({
+						index:0
+					})
+				}else{
+					uni.setTabBarBadge({
+					  index: 0,
+					  text: String(unReadMsgNum)
+					})
+				}
+			})
+		})		
+	}
 // 流程列表
 const processList = ref({
 	fList: [],