|
|
@@ -111,7 +111,7 @@ import $modal from '@/plugins/modal.js'
|
|
|
import $tab from '@/plugins/tab.js'
|
|
|
import { convertToChineseCurrency } from '@/utils/ygoa.js'
|
|
|
import { calCommonExp } from '@/utils/rpn.js'
|
|
|
-import { getProcessInfo, getProcessForm, submitProcessForm, uploadFile } from '@/api/work.js'
|
|
|
+import { getProcessInfo, getProcessForm, submitProcessForm, uploadFile, getAttendanceSegment } from '@/api/work.js'
|
|
|
const fieldTypeDict = {
|
|
|
'0': 'text',
|
|
|
'1': 'number'
|
|
|
@@ -200,6 +200,15 @@ function bindTimeRangeData() {
|
|
|
|
|
|
// 只有找到 startName 和 endName 后,才检查 bindName
|
|
|
if (startIndex !== -1 && endIndex !== -1) {
|
|
|
+ formElements.value[startIndex].defaultValue = new Date(Date.now()).toLocaleString('zh-CN', {
|
|
|
+ year: 'numeric',
|
|
|
+ month: '2-digit',
|
|
|
+ day: '2-digit',
|
|
|
+ hour: '2-digit',
|
|
|
+ minute: '2-digit',
|
|
|
+ second: '2-digit',
|
|
|
+ hour12: false
|
|
|
+ }).replace(/\//g, '-').replace(/, /g, ' ');
|
|
|
if (bindName) {
|
|
|
const bindIndex = formElements.value.findIndex((item) => item.elementName === bindName);
|
|
|
if (bindIndex !== -1) {
|
|
|
@@ -210,6 +219,7 @@ function bindTimeRangeData() {
|
|
|
startIndex,
|
|
|
endIndex
|
|
|
};
|
|
|
+ setAttendanceSegment() // 获取班次信息
|
|
|
}
|
|
|
} else {
|
|
|
// 没有 bindName,仅保存 start 和 end 的索引
|
|
|
@@ -228,15 +238,17 @@ function calculateTimeDifference(item, form) {
|
|
|
const { startIndex, endIndex } = item.bindTimeRange;
|
|
|
const startTime = new Date(form[startIndex].defaultValue);
|
|
|
const endTime = new Date(form[endIndex].defaultValue);
|
|
|
-
|
|
|
+
|
|
|
// 检查时间是否合法
|
|
|
if (isNaN(startTime.getTime()) || isNaN(endTime.getTime())) {
|
|
|
return item.defaultValue = 0
|
|
|
}
|
|
|
-
|
|
|
+ // 改为配置选择
|
|
|
+ const type = item.elementName == '多少小时'?'请假':'加班'
|
|
|
// 计算时间差
|
|
|
- const timeDifferenceInMs = endTime - startTime;
|
|
|
- let timeDifferenceInHours = (timeDifferenceInMs / (1000 * 60 * 60)).toFixed(1);
|
|
|
+ const timeDifferenceInHours = calculateWorkingHours(startTime, endTime, type);
|
|
|
+ // const timeDifferenceInMs = endTime - startTime;
|
|
|
+ // let timeDifferenceInHours = (timeDifferenceInMs / (1000 * 60 * 60)).toFixed(1);
|
|
|
// let timeDifferenceInHours = (timeDifferenceInMs / (1000 * 60 * 60))
|
|
|
// // 计算小数部分
|
|
|
// const decimalPart = timeDifferenceInHours - Math.floor(timeDifferenceInHours)
|
|
|
@@ -250,6 +262,106 @@ function calculateTimeDifference(item, form) {
|
|
|
// 保存到 defaultValue
|
|
|
return item.defaultValue = timeDifferenceInHours;
|
|
|
}
|
|
|
+let workingPeriods = []
|
|
|
+let workDays = [] // 0为周日
|
|
|
+function setAttendanceSegment() {
|
|
|
+ getAttendanceSegment(userStore.user.unitId).then(({returnParams}) => {
|
|
|
+ const workTime = returnParams[0].work_time.split(';')
|
|
|
+ for (const time of workTime) {
|
|
|
+ if (time == '') continue
|
|
|
+ const times = time.split(',')
|
|
|
+ const obj = {
|
|
|
+ start: times[0],
|
|
|
+ end: times[1]
|
|
|
+ }
|
|
|
+ workingPeriods.push(obj)
|
|
|
+ }
|
|
|
+ if (workingPeriods.length == 0) {
|
|
|
+ workingPeriods = [
|
|
|
+ { start: "09:00", end: "12:00" }, // 上午
|
|
|
+ { start: "13:30", end: "17:30" }, // 下午
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ if (workDays.length == 0) {
|
|
|
+ workDays = [1,2,3,4,5,6] // 0为周日
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+function calculateWorkingHours(startTime, endTime, type) {
|
|
|
+ // 将时间字符串解析为分钟数
|
|
|
+ const formatTime = (timeString) => {
|
|
|
+ const [hours, minutes] = timeString.split(":").map(Number)
|
|
|
+ return hours * 60 + minutes
|
|
|
+ };
|
|
|
+ // 计算两个时间段的重叠部分
|
|
|
+ const calculateOverlap = (start1, end1, start2, end2) => {
|
|
|
+ const overlapStart = Math.max(start1, start2)
|
|
|
+ const overlapEnd = Math.min(end1, end2)
|
|
|
+ return Math.max(0, overlapEnd - overlapStart) // 如果无重叠返回 0
|
|
|
+ };
|
|
|
+ // 将 Date 转化为当天的分钟数
|
|
|
+ const dateToMinutes = (date) => date.getHours() * 60 + date.getMinutes()
|
|
|
+ // 判断日期是否是工作日
|
|
|
+ const isRestdays = (date) => !workDays.includes(date.getDay())
|
|
|
+ // 确保 startTime 和 endTime 是 Date 类型
|
|
|
+ if (!(startTime instanceof Date) || !(endTime instanceof Date)) {
|
|
|
+ throw new Error("startTime 和 endTime 必须是 Date 类型")
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将时间范围分解为每天的计算
|
|
|
+ const startDate = new Date(startTime)
|
|
|
+ const endDate = new Date(endTime)
|
|
|
+ startDate.setHours(0, 0, 0, 0)
|
|
|
+ endDate.setHours(0, 0, 0, 0)
|
|
|
+
|
|
|
+ let totalMinutes = 0
|
|
|
+
|
|
|
+ // 遍历时间范围的每一天
|
|
|
+ for (
|
|
|
+ let currentDate = new Date(startDate);
|
|
|
+ currentDate <= endDate;
|
|
|
+ currentDate.setDate(currentDate.getDate() + 1)
|
|
|
+ ) {
|
|
|
+ // 如果当前日期不是工作日,跳过
|
|
|
+ if (isRestdays(currentDate)) continue;
|
|
|
+
|
|
|
+ const isStartDay = currentDate.getTime() === startDate.getTime();
|
|
|
+ const isEndDay = currentDate.getTime() === endDate.getTime();
|
|
|
+
|
|
|
+ // 当天的起始和结束时间
|
|
|
+ const dayStart = isStartDay ? dateToMinutes(startTime) : 0;
|
|
|
+ const dayEnd = isEndDay ? dateToMinutes(endTime) : 1440; // 1440 = 24 * 60
|
|
|
+ // TODO 改为配置选择
|
|
|
+ if (type === "请假") {
|
|
|
+ // 计算工作时间段内的时间
|
|
|
+ workingPeriods.forEach((period) => {
|
|
|
+ const periodStart = formatTime(period.start);
|
|
|
+ const periodEnd = formatTime(period.end);
|
|
|
+ totalMinutes += calculateOverlap(dayStart, dayEnd, periodStart, periodEnd);
|
|
|
+ });
|
|
|
+ } else if (type === "加班") {
|
|
|
+ // 计算非工作时间段的时间
|
|
|
+ let nonWorkingMinutes = 0;
|
|
|
+ let current = dayStart;
|
|
|
+ for (const period of workingPeriods) {
|
|
|
+ const periodStart = formatTime(period.start);
|
|
|
+ const periodEnd = formatTime(period.end);
|
|
|
+
|
|
|
+ if (current < periodStart) {
|
|
|
+ nonWorkingMinutes += calculateOverlap(current, dayEnd, current, periodStart);
|
|
|
+ }
|
|
|
+ current = Math.max(current, periodEnd);
|
|
|
+ }
|
|
|
+ if (current < dayEnd) {
|
|
|
+ nonWorkingMinutes += dayEnd - current;
|
|
|
+ }
|
|
|
+ totalMinutes += nonWorkingMinutes;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 转换为小时
|
|
|
+ return totalMinutes / 60;
|
|
|
+}
|
|
|
|
|
|
function setTimeRange(e) {
|
|
|
// console.log('setTimeRange', e)
|
|
|
@@ -440,9 +552,10 @@ function getValidateRules() {
|
|
|
{
|
|
|
required: true,
|
|
|
},
|
|
|
- {
|
|
|
- formatTypeDict: formatTypeDict[elem.fieldType.value] || 'string',
|
|
|
- }
|
|
|
+ // {
|
|
|
+ // 类型判断 数值型使用string会出错
|
|
|
+ // formatTypeDict: formatTypeDict[elem.fieldType.value] || 'string',
|
|
|
+ // }
|
|
|
],
|
|
|
label: elem.elementName.slice(3)
|
|
|
};
|
|
|
@@ -458,9 +571,9 @@ function getValidateRules() {
|
|
|
{
|
|
|
required: '1' == elem.noNull,
|
|
|
},
|
|
|
- {
|
|
|
- format: formatTypeDict[elem.fieldType] || 'string',
|
|
|
- }
|
|
|
+ // {
|
|
|
+ // format: formatTypeDict[elem.fieldType] || 'string',
|
|
|
+ // }
|
|
|
],
|
|
|
label: elem.elementName
|
|
|
};
|