refactor: ♻️ 基于 gorm 钩子实现自动缓存失效机制,再也不用牵一发而动全身写删缓存逻辑了~ - 通过 gorm hook 监听 MySQL 数据变更 🧩 - 自动删除对应表相关缓存,实现缓存失效自动化 🔄 - 移除原本写在 sv 层的手动删缓存逻辑 🧹 - 解耦业务逻辑与缓存控制,结构更加清晰 ✅ fix: 🐛 修复将任务类加入日程接口的时间字段遗漏问题 - 由于前版本 MySQL 表结构更新 - 漏写插入起始时间字段逻辑,导致500报错,现已补充 ⏱️ fix: 🐛 修复获取最近已完成任务列表接口的多个问题 - 移除不应存在的幂等键 🔁 - 修复“一个event输出多次”的问题(原因出自 dto 转换函数) 🔧 undo: ⚠️ 删除任务类接口未处理已安排任务块的解除逻辑 - 当前删除任务类时,未解除已被安排的任务块 - 该逻辑存在缺陷,计划在后续版本内修复 🛠️
124 lines
4.1 KiB
Go
124 lines
4.1 KiB
Go
package conv
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
"time"
|
||
|
||
"github.com/LoveLosita/smartflow/backend/respond"
|
||
"github.com/spf13/viper"
|
||
)
|
||
|
||
// DateFormat 此处定义基准学期的开始和结束日期
|
||
const DateFormat = "2006-01-02"
|
||
|
||
// RealDateToRelativeDate 将绝对日期转换为相对日期(格式: "week-day")
|
||
func RealDateToRelativeDate(realDate string) (int, int, error) {
|
||
SemesterStartDate := viper.GetString("time.semesterStartDate") // 从配置文件中读取学期开始日期
|
||
SemesterEndDate := viper.GetString("time.semesterEndDate") // 从配置文件中读取学期结束日期
|
||
t, err := time.Parse(DateFormat, realDate)
|
||
if err != nil {
|
||
return 0, 0, err
|
||
}
|
||
start, err := time.Parse(DateFormat, SemesterStartDate)
|
||
if err != nil {
|
||
return 0, 0, err
|
||
}
|
||
end, err := time.Parse(DateFormat, SemesterEndDate)
|
||
if err != nil {
|
||
return 0, 0, err
|
||
}
|
||
// 边界校验:日期必须在学期范围内
|
||
if t.Before(start) || t.After(end) {
|
||
return 0, 0, errors.New("日期超出学期范围")
|
||
}
|
||
// 计算天数差值(注意:24小时为一个基准天)
|
||
days := int(t.Sub(start).Hours() / 24)
|
||
// 计算周数和星期
|
||
// 假设 SemesterStartDate 对应第 1 周,周 1
|
||
week := (days / 7) + 1
|
||
dayOfWeek := (days % 7) + 1
|
||
return week, dayOfWeek, nil
|
||
}
|
||
|
||
// RelativeDateToRealDate 将相对日期转换为绝对日期(输入格式: "week-day")
|
||
func RelativeDateToRealDate(week, dayOfWeek int) (string, error) {
|
||
SemesterStartDate := viper.GetString("time.semesterStartDate") // 从配置文件中读取学期开始日期
|
||
SemesterEndDate := viper.GetString("time.semesterEndDate") // 从配置文件中读取学期结束日期
|
||
start, _ := time.Parse(DateFormat, SemesterStartDate)
|
||
// 核心转换逻辑:(周-1)*7 + (天-1)
|
||
offsetDays := (week-1)*7 + (dayOfWeek - 1)
|
||
targetDate := start.AddDate(0, 0, offsetDays)
|
||
// 校验计算出的日期是否超出学期结束日期
|
||
end, _ := time.Parse(DateFormat, SemesterEndDate)
|
||
if targetDate.After(end) {
|
||
return "", respond.TimeOutOfRangeOfThisSemester
|
||
}
|
||
return targetDate.Format(DateFormat), nil
|
||
}
|
||
|
||
type SectionTime struct {
|
||
Start string // 第一个开始
|
||
End string // 第一个结束
|
||
}
|
||
|
||
var sectionTimeMap2 = map[int]SectionTime{
|
||
1: {Start: "08:00", End: "08:45"},
|
||
2: {Start: "08:55", End: "09:40"},
|
||
3: {Start: "10:15", End: "11:00"},
|
||
4: {Start: "11:10", End: "11:55"},
|
||
5: {Start: "14:00", End: "14:45"},
|
||
6: {Start: "14:55", End: "15:40"},
|
||
7: {Start: "16:15", End: "17:00"},
|
||
8: {Start: "17:10", End: "17:55"},
|
||
9: {Start: "19:00", End: "19:45"},
|
||
10: {Start: "19:55", End: "20:40"},
|
||
11: {Start: "20:50", End: "21:35"},
|
||
12: {Start: "21:45", End: "22:30"},
|
||
}
|
||
|
||
func RelativeTimeToRealTime(week, dayOfWeek, startSection, endSection int) (time.Time, time.Time, error) {
|
||
// 1. 安全校验
|
||
if startSection > endSection {
|
||
return time.Time{}, time.Time{}, respond.InvalidSectionRange
|
||
}
|
||
|
||
startTimeInfo, okStart := sectionTimeMap2[startSection]
|
||
endTimeInfo, okEnd := sectionTimeMap2[endSection]
|
||
if !okStart || !okEnd {
|
||
return time.Time{}, time.Time{}, respond.InvalidSectionNumber
|
||
}
|
||
|
||
if week < 1 || dayOfWeek < 1 || dayOfWeek > 7 {
|
||
return time.Time{}, time.Time{}, respond.InvalidWeekOrDayOfWeek
|
||
}
|
||
|
||
// 2. 计算目标日期
|
||
// 偏移天数 = (周数-1)*7 + (周几-1)
|
||
daysOffset := (week-1)*7 + (dayOfWeek - 1)
|
||
TermStartDate := viper.GetString("time.semesterStartDate") // 从配置文件中读取学期开始日期
|
||
baseDate, _ := time.Parse("2006-01-02", TermStartDate)
|
||
targetDate := baseDate.AddDate(0, 0, daysOffset)
|
||
dateStr := targetDate.Format("2006-01-02")
|
||
|
||
// 3. 锁定时区 (Asia/Shanghai)
|
||
timeZone := viper.GetString("time.zone") // 从配置文件中读取时区
|
||
loc, _ := time.LoadLocation(timeZone)
|
||
|
||
// 拼接:起始节次的 Start 和 结束节次的 End
|
||
startFullStr := fmt.Sprintf("%s %s", dateStr, startTimeInfo.Start)
|
||
endFullStr := fmt.Sprintf("%s %s", dateStr, endTimeInfo.End)
|
||
|
||
startTime, err := time.ParseInLocation("2006-01-02 15:04", startFullStr, loc)
|
||
if err != nil {
|
||
return time.Time{}, time.Time{}, err
|
||
}
|
||
|
||
endTime, err := time.ParseInLocation("2006-01-02 15:04", endFullStr, loc)
|
||
if err != nil {
|
||
return time.Time{}, time.Time{}, err
|
||
}
|
||
|
||
return startTime, endTime, nil
|
||
}
|