Version: 0.3.6.dev.260223
feat: 🚀 新增智能编排日程接口与算法模块 * 新增智能编排日程接口,实现自动生成周维度课程安排 * 抽离核心算法至 `Logic` 包,统一存放调度与排课相关算法逻辑,优化项目结构分层 * 大多数用例测试通过,当前存在少量边界用例下“排课时间是否充足”的误判问题 * 返回的周视图数据在极端场景下存在数量偏差,待进一步完善边界控制 fix: 🐛 修复批量导入课程接口 500 错误 * 修复批量导入课程接口中未在 `event` 结构体填写时间字段的问题 * 解决因时间字段为空导致的服务端 500 错误,保证数据完整性 refactor: ♻️ 新增入参校验逻辑保障调度稳定性 * 在添加任务类时新增入参校验逻辑 * 避免非法数据进入调度流程,确保自动编排日程接口执行稳定 docs: 📚 更新 README 智能编排算法说明 * 补充智能编排日程算法的设计思路与实现说明 undo: ⚠️ 追加导入课程后缓存未自动失效 * 追加导入课程后未自动删除对应周安排缓存,存在数据不一致风险 * 当前未能稳定复现,计划后续定位缓存失效时序与触发条件问题
This commit is contained in:
@@ -24,7 +24,7 @@ type Schedule struct {
|
||||
EmbeddedTaskID *int `gorm:"column:embedded_task_id;comment:若为水课嵌入,记录具体的任务项ID" json:"embedded_task_id"`
|
||||
Status string `gorm:"column:status;type:enum('normal','interrupted');default:'normal';comment:状态: 正常/因故中断" json:"status"`
|
||||
// 💡 必须加上这一行,告诉 GORM 如何关联元数据
|
||||
Event ScheduleEvent `gorm:"foreignKey:EventID" json:"event"`
|
||||
Event *ScheduleEvent `gorm:"foreignKey:EventID" json:"event"`
|
||||
EmbeddedTask *TaskClassItem `gorm:"foreignKey:EmbeddedTaskID" json:"embedded_task"`
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ type WeeklyEventBrief struct {
|
||||
Location string `json:"location"`
|
||||
Type string `json:"type"`
|
||||
Span int `json:"span"` // 跨越的节数,给前端用来渲染宽度/高度
|
||||
Status string `json:"status"`
|
||||
EmbeddedTaskInfo TaskBrief `json:"embedded_task_info,omitempty"`
|
||||
}
|
||||
|
||||
|
||||
@@ -21,10 +21,45 @@ type TaskClass struct {
|
||||
TotalSlots *int `gorm:"column:total_slots;comment:分配的总节数"`
|
||||
AllowFillerCourse *bool `gorm:"column:allow_filler_course;default:true"`
|
||||
Strategy *string `gorm:"column:strategy;type:enum('steady','rapid')"`
|
||||
ExcludedSlots *string `gorm:"column:excluded_slots;type:json;comment:不想要的时段切片"`
|
||||
ExcludedSlots IntSlice `gorm:"column:excluded_slots;type:json;comment:不想要的时段切片"`
|
||||
Items []TaskClassItem `gorm:"foreignKey:CategoryID;references:ID"` // 一对多关联:一个 TaskClass 有多个 TaskClassItem
|
||||
}
|
||||
|
||||
// IntSlice 用于把 []int 以 JSON 形式存入/读出数据库 json 字段
|
||||
type IntSlice []int
|
||||
|
||||
func (s IntSlice) Value() (driver.Value, error) {
|
||||
// nil -> NULL;空切片 -> "[]"
|
||||
if s == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return json.Marshal([]int(s))
|
||||
}
|
||||
|
||||
func (s *IntSlice) Scan(value any) error {
|
||||
if value == nil {
|
||||
*s = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
var data []byte
|
||||
switch v := value.(type) {
|
||||
case []byte:
|
||||
data = v
|
||||
case string:
|
||||
data = []byte(v)
|
||||
default:
|
||||
return fmt.Errorf("IntSlice: 不支持的扫描类型: %T", value)
|
||||
}
|
||||
|
||||
var out []int
|
||||
if err := json.Unmarshal(data, &out); err != nil {
|
||||
return err
|
||||
}
|
||||
*s = IntSlice(out)
|
||||
return nil
|
||||
}
|
||||
|
||||
// TaskClassItem 用于和数据库中的 task_items 表进行映射
|
||||
type TaskClassItem struct {
|
||||
//section 1
|
||||
|
||||
Reference in New Issue
Block a user