diff --git a/app/Models/UserBot.php b/app/Models/UserBot.php index 56dbe0ab3..a007fb722 100644 --- a/app/Models/UserBot.php +++ b/app/Models/UserBot.php @@ -391,8 +391,8 @@ class UserBot extends AbstractModel $errorTime = false; if (!$targetDate) { $displayDelay = date("H:i", $todayTimeDelay % 86400); - $nextDay = ($todayTimeDelay > strtotime("{$nowDate} 23:59:59")) ? "(次日)" : ""; - $errorTime = "不在有效时间内,有效时间为:" . date("H:i", $timeAdvance) . "-{$nextDay}{$displayDelay}"; + $nextDay = ($todayTimeDelay > strtotime("{$nowDate} 23:59:59")) ? "(+1)" : ""; + $errorTime = "不在有效时间内,有效时间为:" . date("H:i", $timeAdvance) . "-{$displayDelay}{$nextDay}"; } // $macs = explode(",", $mac); @@ -485,7 +485,7 @@ class UserBot extends AbstractModel $typeContent = $type == "up" ? "上班" : "下班"; if (Cache::get($cacheKey) === "yes") { if ($alreadyTip) { - $dateHint = ($displayDate != $nowDate) ? "({$displayDate})" : "今日"; + $dateHint = ($displayDate != $nowDate) ? "({$displayDate}) " : "今日"; $text = "{$dateHint}已{$typeContent}打卡,无需重复打卡。"; $text .= $checkin['remark'] ? " ({$checkin['remark']})": ""; WebSocketDialogMsg::sendMsg(null, $dialog->id, 'template', [ @@ -500,7 +500,7 @@ class UserBot extends AbstractModel $hi = date("H:i"); $remark = $checkin['remark'] ? " ({$checkin['remark']})": ""; $subcontent = $getJokeSoup($type, $checkin['userid']); - $dateInfo = ($displayDate != $nowDate) ? "(记录归属 {$displayDate})" : ""; + $dateInfo = ($displayDate != $nowDate) ? " ({$displayDate})" : ""; $title = "{$typeContent}打卡成功,打卡时间: {$hi}{$remark}{$dateInfo}"; WebSocketDialogMsg::sendMsg(null, $dialog->id, 'template', [ 'type' => 'content', diff --git a/resources/assets/js/pages/manage/setting/components/SystemCheckin.vue b/resources/assets/js/pages/manage/setting/components/SystemCheckin.vue index 3ca362a87..99c1f6f26 100644 --- a/resources/assets/js/pages/manage/setting/components/SystemCheckin.vue +++ b/resources/assets/js/pages/manage/setting/components/SystemCheckin.vue @@ -29,15 +29,17 @@
- +
+
{{ earliestCheckinTime }}
- +
+
{{ latestCheckinTime }}
{{$L('签到前后时间收到消息通知')}}
@@ -405,31 +407,54 @@ export default { computed: { ...mapState(['formOptions']), + + earliestCheckinTime() { + const times = this.formData.time; + if (!times || times.length < 1 || !times[0]) return ''; + const advance = parseInt(this.formData.advance) || 0; + if (advance <= 0) return ''; + + const startMinutes = this.timeToMinutes(times[0]); + let earliestMinutes = startMinutes - advance; + + // 处理跨天(负数表示前一天) + let prefix = ''; + if (earliestMinutes < 0) { + earliestMinutes += 24 * 60; + prefix = '(' + this.$L('前日') + ') '; + } + + const hours = Math.floor(earliestMinutes / 60); + const mins = earliestMinutes % 60; + return prefix + String(hours).padStart(2, '0') + ':' + String(mins).padStart(2, '0'); + }, + + latestCheckinTime() { + const times = this.formData.time; + if (!times || times.length < 2 || !times[1]) return ''; + const delay = parseInt(this.formData.delay) || 0; + if (delay <= 0) return ''; + + const endMinutes = this.timeToMinutes(times[1]); + let latestMinutes = endMinutes + delay; + + // 处理跨天(超过24小时表示次日) + let prefix = ''; + if (latestMinutes >= 24 * 60) { + latestMinutes -= 24 * 60; + prefix = '(' + this.$L('次日') + ') '; + } + + const hours = Math.floor(latestMinutes / 60); + const mins = latestMinutes % 60; + return prefix + String(hours).padStart(2, '0') + ':' + String(mins).padStart(2, '0'); + }, }, methods: { submitForm() { this.$refs.formData.validate((valid) => { if (valid) { - // 验证提前和延后时间是否重叠 - if (this.formData.open === 'open') { - const times = this.formData.time; - if (times && times.length >= 2) { - const startMinutes = this.timeToMinutes(times[0]); - const endMinutes = this.timeToMinutes(times[1]); - let shiftDuration = endMinutes - startMinutes; - if (shiftDuration <= 0) shiftDuration += 24 * 60; - - const advance = parseInt(this.formData.advance) || 120; - const delay = parseInt(this.formData.delay) || 120; - const maxAllowed = 24 * 60 - shiftDuration; - - if (advance + delay >= maxAllowed) { - $A.modalError('提前和延后时间设置存在重叠,最大提前+延后时间不能超过 ' + (maxAllowed - 1) + ' 分钟', {language: false}); - return; - } - } - } this.systemSetting(true); } }) @@ -441,6 +466,44 @@ export default { return parseInt(parts[0]) * 60 + parseInt(parts[1]); }, + getMaxAllowed() { + const times = this.formData.time; + if (!times || times.length < 2) return null; + const startMinutes = this.timeToMinutes(times[0]); + const endMinutes = this.timeToMinutes(times[1]); + let shiftDuration = endMinutes - startMinutes; + if (shiftDuration <= 0) shiftDuration += 24 * 60; + return 24 * 60 - shiftDuration; + }, + + onAdvanceBlur() { + const maxAllowed = this.getMaxAllowed(); + if (maxAllowed === null) return; + + const delay = parseInt(this.formData.delay) || 0; + const maxAdvance = maxAllowed - delay - 1; + + if (maxAdvance < 0) { + this.formData.advance = 0; + } else if (this.formData.advance > maxAdvance) { + this.formData.advance = maxAdvance; + } + }, + + onDelayBlur() { + const maxAllowed = this.getMaxAllowed(); + if (maxAllowed === null) return; + + const advance = parseInt(this.formData.advance) || 0; + const maxDelay = maxAllowed - advance - 1; + + if (maxDelay < 0) { + this.formData.delay = 0; + } else if (this.formData.delay > maxDelay) { + this.formData.delay = maxDelay; + } + }, + resetForm() { this.formData = $A.cloneJSON(this.formDatum_bak); }, diff --git a/resources/assets/sass/pages/common.scss b/resources/assets/sass/pages/common.scss index 016c226a6..3c3fe9bc6 100755 --- a/resources/assets/sass/pages/common.scss +++ b/resources/assets/sass/pages/common.scss @@ -900,6 +900,8 @@ body.window-portrait { .ivu-form-item-content { display: flex; align-items: center; + flex-wrap: wrap; + gap: 8px; } } }