Version:0.1.0.dev.260205
feat: 🆕 完善course模块功能并优化批量导入接口 - 调整 task-class 模型代码并增加注释,使其更简洁易读 ✍️ - 结构调整:将课程相关接口从 schedule 分类移至独立的 course 分类 🚀 - 修改接口 URL 从 /schedule 更改为 /course 🔄 fix: 🐛 修复批量导入课程接口重复导入相同课程的 bug - 通过在数据库添加唯一约束解决此问题 🔐 - 这只是初步修复,后续会在 sv 层增加重复/时间冲突检测逻辑 ⚠️ - 引导用户修改课表与任务块时间冲突的机制待实现 ⏳ refactor: 🔨 重构 schedule 表单结构 - 将节次管理策略从字符串存储改为原子化存储(如 1-2 节更改为单独两条记录) - 为后续冲突检查与智能排课做准备 🧠 perf: 🚀 优化批量导入课程接口性能 - 通过数据暂存内存中减少数据插入 MySQL 的次数 ⚡
This commit is contained in:
@@ -3,6 +3,6 @@ package api
|
|||||||
type ApiHandlers struct {
|
type ApiHandlers struct {
|
||||||
UserHandler *UserHandler
|
UserHandler *UserHandler
|
||||||
TaskHandler *TaskHandler
|
TaskHandler *TaskHandler
|
||||||
ScheduleHandler *ScheduleHandler
|
ScheduleHandler *CourseHandler
|
||||||
TaskClassHandler *TaskClassHandler
|
TaskClassHandler *TaskClassHandler
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,19 +12,19 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ScheduleHandler struct {
|
type CourseHandler struct {
|
||||||
// 伸出手:准备接住 Service
|
// 伸出手:准备接住 Service
|
||||||
service *service.ScheduleService
|
service *service.CourseService
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewScheduleHandler 创建 ScheduleHandler 实例
|
// NewCourseHandler 创建 CourseHandler 实例
|
||||||
func NewScheduleHandler(service *service.ScheduleService) *ScheduleHandler {
|
func NewCourseHandler(service *service.CourseService) *CourseHandler {
|
||||||
return &ScheduleHandler{
|
return &CourseHandler{
|
||||||
service: service,
|
service: service,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sa *ScheduleHandler) CheckUserCourse(c *gin.Context) {
|
func (sa *CourseHandler) CheckUserCourse(c *gin.Context) {
|
||||||
//1.从请求中获取课程信息
|
//1.从请求中获取课程信息
|
||||||
var req model.UserCheckCourseRequest
|
var req model.UserCheckCourseRequest
|
||||||
err := c.ShouldBindJSON(&req)
|
err := c.ShouldBindJSON(&req)
|
||||||
@@ -42,7 +42,7 @@ func (sa *ScheduleHandler) CheckUserCourse(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sa *ScheduleHandler) AddUserCourses(c *gin.Context) {
|
func (sa *CourseHandler) AddUserCourses(c *gin.Context) {
|
||||||
//1.从请求中获取课程信息
|
//1.从请求中获取课程信息
|
||||||
var req model.UserImportCoursesRequest
|
var req model.UserImportCoursesRequest
|
||||||
err := c.ShouldBindJSON(&req)
|
err := c.ShouldBindJSON(&req)
|
||||||
@@ -43,23 +43,23 @@ func Start() {
|
|||||||
userRepo := dao.NewUserDAO(db)
|
userRepo := dao.NewUserDAO(db)
|
||||||
cacheRepo := dao.NewCacheDAO(rdb)
|
cacheRepo := dao.NewCacheDAO(rdb)
|
||||||
taskRepo := dao.NewTaskDAO(db)
|
taskRepo := dao.NewTaskDAO(db)
|
||||||
scheduleRepo := dao.NewScheduleDAO(db)
|
courseRepo := dao.NewCourseDAO(db)
|
||||||
taskClassRepo := dao.NewTaskClassDAO(db)
|
taskClassRepo := dao.NewTaskClassDAO(db)
|
||||||
//service 层
|
//service 层
|
||||||
userService := service.NewUserService(userRepo, cacheRepo)
|
userService := service.NewUserService(userRepo, cacheRepo)
|
||||||
taskSv := service.NewTaskService(taskRepo)
|
taskSv := service.NewTaskService(taskRepo)
|
||||||
scheduleService := service.NewScheduleService(scheduleRepo)
|
courseService := service.NewCourseService(courseRepo)
|
||||||
taskClassService := service.NewTaskClassService(taskClassRepo, cacheRepo)
|
taskClassService := service.NewTaskClassService(taskClassRepo, cacheRepo)
|
||||||
//api 层
|
//api 层
|
||||||
userApi := api.NewUserHandler(userService)
|
userApi := api.NewUserHandler(userService)
|
||||||
taskApi := api.NewTaskHandler(taskSv)
|
taskApi := api.NewTaskHandler(taskSv)
|
||||||
scheduleApi := api.NewScheduleHandler(scheduleService)
|
courseApi := api.NewCourseHandler(courseService)
|
||||||
taskClassApi := api.NewTaskClassHandler(taskClassService)
|
taskClassApi := api.NewTaskClassHandler(taskClassService)
|
||||||
|
|
||||||
handlers := &api.ApiHandlers{
|
handlers := &api.ApiHandlers{
|
||||||
UserHandler: userApi,
|
UserHandler: userApi,
|
||||||
TaskHandler: taskApi,
|
TaskHandler: taskApi,
|
||||||
ScheduleHandler: scheduleApi,
|
ScheduleHandler: courseApi,
|
||||||
TaskClassHandler: taskClassApi,
|
TaskClassHandler: taskClassApi,
|
||||||
}
|
}
|
||||||
r := routers.RegisterRouters(handlers, cacheRepo)
|
r := routers.RegisterRouters(handlers, cacheRepo)
|
||||||
|
|||||||
24
backend/dao/course.go
Normal file
24
backend/dao/course.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package dao
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/LoveLosita/smartflow/backend/model"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CourseDAO struct {
|
||||||
|
db *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCourseDAO 创建ScheduleDAO实例
|
||||||
|
func NewCourseDAO(db *gorm.DB) *CourseDAO {
|
||||||
|
return &CourseDAO{
|
||||||
|
db: db,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dao *CourseDAO) AddUserCourses(courses []model.Schedule) error {
|
||||||
|
if err := dao.db.Create(&courses).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package dao
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/LoveLosita/smartflow/backend/model"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ScheduleDAO struct {
|
|
||||||
db *gorm.DB
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewScheduleDAO 创建ScheduleDAO实例
|
|
||||||
func NewScheduleDAO(db *gorm.DB) *ScheduleDAO {
|
|
||||||
return &ScheduleDAO{
|
|
||||||
db: db,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dao *ScheduleDAO) AddUserCourses(courses []model.Schedule) error {
|
|
||||||
if err := dao.db.Create(&courses).Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
18
backend/model/course.go
Normal file
18
backend/model/course.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type UserImportCoursesRequest struct {
|
||||||
|
Courses []UserCheckCourseRequest `json:"courses"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserCheckCourseRequest struct {
|
||||||
|
CourseName string `json:"course_name"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
IsAllowTasks bool `json:"is_allow_tasks"`
|
||||||
|
Arrangements []struct {
|
||||||
|
StartWeek int `json:"start_week"`
|
||||||
|
EndWeek int `json:"end_week"`
|
||||||
|
DayOfWeek int `json:"day_of_week"`
|
||||||
|
StartSection int `json:"start_section"`
|
||||||
|
EndSection int `json:"end_section"`
|
||||||
|
} `json:"arrangements"`
|
||||||
|
}
|
||||||
@@ -3,29 +3,12 @@ package model
|
|||||||
type Schedule struct {
|
type Schedule struct {
|
||||||
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||||
UserID int `gorm:"column:user_id;index" json:"user_id"`
|
UserID int `gorm:"column:user_id;index" json:"user_id"`
|
||||||
Type string `gorm:"type:enum('course','task');comment:'course / task'" json:"type"`
|
Type string `gorm:"type:enum('course','task');comment:course / task" json:"type"`
|
||||||
RelID int `gorm:"column:rel_id;comment:'关联 course_id 或 task_item_id'" json:"rel_id"`
|
RelID int `gorm:"column:rel_id;comment:关联 course_id 或 task_item_id" json:"rel_id"`
|
||||||
CanBeEmbedded bool `gorm:"column:can_be_embedded;comment:'是否允许嵌入水课'" json:"can_be_embedded"`
|
EmbeddedTaskID *int `gorm:"column:embedded_task_id;index;comment:若为水课嵌入,记录任务ID" json:"embedded_task_id"`
|
||||||
EmbeddedTaskID *uint `gorm:"column:embedded_task_id;comment:'若为水课嵌入,记录任务ID'" json:"embedded_task_id"`
|
Week int `gorm:"column:week;uniqueIndex:idx_user_slot_atomic,priority:2;comment:周次 (1-25)" json:"week"`
|
||||||
Week int `gorm:"column:week" json:"week"`
|
DayOfWeek int `gorm:"column:day_of_week;uniqueIndex:idx_user_slot_atomic,priority:3;comment:星期 (1-7)" json:"day_of_week"`
|
||||||
DayOfWeek int `gorm:"column:day_of_week" json:"day_of_week"`
|
Section int `gorm:"column:section;uniqueIndex:idx_user_slot_atomic,priority:4;comment:原子化节次 (1-12)" json:"section"`
|
||||||
Sections string `gorm:"type:varchar(255)" json:"sections"`
|
Status string `gorm:"type:enum('normal','interrupted');default:normal" json:"status"`
|
||||||
Status string `gorm:"type:enum('normal','interrupted');default:'normal'" json:"status"`
|
CanBeEmbedded bool `gorm:"column:can_be_embedded;not null;comment:是否允许嵌入任务" json:"can_be_embedded"`
|
||||||
}
|
|
||||||
|
|
||||||
type UserImportCoursesRequest struct {
|
|
||||||
Courses []UserCheckCourseRequest `json:"courses"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UserCheckCourseRequest struct {
|
|
||||||
CourseName string `json:"course_name"`
|
|
||||||
Location string `json:"location"`
|
|
||||||
IsAllowTasks bool `json:"is_allow_tasks"`
|
|
||||||
Arrangements []struct {
|
|
||||||
StartWeek int `json:"start_week"`
|
|
||||||
EndWeek int `json:"end_week"`
|
|
||||||
DayOfWeek int `json:"day_of_week"`
|
|
||||||
StartSection int `json:"start_section"`
|
|
||||||
EndSection int `json:"end_section"`
|
|
||||||
} `json:"arrangements"`
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TaskClass 用于和数据库中的 task_classes 表进行映射
|
||||||
type TaskClass struct {
|
type TaskClass struct {
|
||||||
//section 1
|
//section 1
|
||||||
ID int `gorm:"column:id;primaryKey;autoIncrement"`
|
ID int `gorm:"column:id;primaryKey;autoIncrement"`
|
||||||
@@ -24,33 +25,7 @@ type TaskClass struct {
|
|||||||
Items []TaskClassItem `gorm:"foreignKey:CategoryID;references:ID"` // 一对多关联:一个 TaskClass 有多个 TaskClassItem
|
Items []TaskClassItem `gorm:"foreignKey:CategoryID;references:ID"` // 一对多关联:一个 TaskClass 有多个 TaskClassItem
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName 设定 TaskClass 的表名为 task_classes
|
// TaskClassItem 用于和数据库中的 task_items 表进行映射
|
||||||
func (TaskClass) TableName() string {
|
|
||||||
return "task_classes"
|
|
||||||
}
|
|
||||||
|
|
||||||
type UserAddTaskClassRequest struct {
|
|
||||||
Name string `json:"name" binding:"required"`
|
|
||||||
StartDate string `json:"start_date" binding:"required"` // YYYY-MM-DD
|
|
||||||
EndDate string `json:"end_date" binding:"required"` // YYYY-MM-DD
|
|
||||||
Mode string `json:"mode" binding:"required,oneof=auto manual"`
|
|
||||||
Config UserAddTaskClassConfig `json:"config" binding:"required"`
|
|
||||||
Items []UserAddTaskClassItemRequest `json:"items" binding:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UserAddTaskClassConfig struct {
|
|
||||||
TotalSlots int `json:"total_slots" binding:"required,min=1"`
|
|
||||||
AllowFillerCourse bool `json:"allow_filler_course"`
|
|
||||||
Strategy string `json:"strategy" binding:"required,oneof=steady rapid"`
|
|
||||||
ExcludedSlots []int `json:"excluded_slots"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UserAddTaskClassItemRequest struct {
|
|
||||||
Order int `json:"order" binding:"required,min=1"`
|
|
||||||
Content string `json:"content" binding:"required"`
|
|
||||||
EmbeddedTime *TargetTime `json:"embedded_time"` // 例: 2025-12-22 1-2节; nil 表示未安排
|
|
||||||
}
|
|
||||||
|
|
||||||
type TaskClassItem struct {
|
type TaskClassItem struct {
|
||||||
//section 1
|
//section 1
|
||||||
ID int `gorm:"column:id;primaryKey;autoIncrement"`
|
ID int `gorm:"column:id;primaryKey;autoIncrement"`
|
||||||
@@ -62,12 +37,55 @@ type TaskClassItem struct {
|
|||||||
Status *int `gorm:"column:status;comment:1:未安排, 2:已应用"`
|
Status *int `gorm:"column:status;comment:1:未安排, 2:已应用"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UserAddTaskClassRequest 用于处理用户添加任务类别的请求
|
||||||
|
type UserAddTaskClassRequest struct {
|
||||||
|
Name string `json:"name" binding:"required"`
|
||||||
|
StartDate string `json:"start_date" binding:"required"` // YYYY-MM-DD
|
||||||
|
EndDate string `json:"end_date" binding:"required"` // YYYY-MM-DD
|
||||||
|
Mode string `json:"mode" binding:"required,oneof=auto manual"`
|
||||||
|
Config UserAddTaskClassConfig `json:"config" binding:"required"`
|
||||||
|
Items []UserAddTaskClassItemRequest `json:"items" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAddTaskClassConfig 用于处理用户添加任务类别时的配置部分
|
||||||
|
type UserAddTaskClassConfig struct {
|
||||||
|
TotalSlots int `json:"total_slots" binding:"required,min=1"`
|
||||||
|
AllowFillerCourse bool `json:"allow_filler_course"`
|
||||||
|
Strategy string `json:"strategy" binding:"required,oneof=steady rapid"`
|
||||||
|
ExcludedSlots []int `json:"excluded_slots"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAddTaskClassItemRequest 用于处理用户添加任务类别时的任务块部分
|
||||||
|
type UserAddTaskClassItemRequest struct {
|
||||||
|
Order int `json:"order" binding:"required,min=1"`
|
||||||
|
Content string `json:"content" binding:"required"`
|
||||||
|
EmbeddedTime *TargetTime `json:"embedded_time"` // 例: 2025-12-22 1-2节; nil 表示未安排
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetTime 表示任务块的目标时间
|
||||||
type TargetTime struct {
|
type TargetTime struct {
|
||||||
Date string `json:"date"` // 例: 2025-12-22
|
Date string `json:"date"` // 例: 2025-12-22
|
||||||
SectionFrom int `json:"section_from"` // 起始节次
|
SectionFrom int `json:"section_from"` // 起始节次
|
||||||
SectionTo int `json:"section_to"` // 结束节次
|
SectionTo int `json:"section_to"` // 结束节次
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UserGetTaskClassesResponse 用于返回用户的任务类列表,展示简要信息
|
||||||
|
type UserGetTaskClassesResponse struct {
|
||||||
|
TaskClasses []TaskClassSummary `json:"task_classes"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TaskClassSummary 提供任务类别的简要信息
|
||||||
|
type TaskClassSummary struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Mode string `json:"mode"`
|
||||||
|
Strategy string `json:"strategy"`
|
||||||
|
StartDate time.Time `json:"start_date"`
|
||||||
|
EndDate time.Time `json:"end_date"`
|
||||||
|
TotalSlots int `json:"total_slots"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value 实现 driver.Valuer 接口,负责将 TargetTime 转换为数据库存储的格式
|
||||||
func (t *TargetTime) Value() (driver.Value, error) {
|
func (t *TargetTime) Value() (driver.Value, error) {
|
||||||
if t == nil {
|
if t == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@@ -77,6 +95,7 @@ func (t *TargetTime) Value() (driver.Value, error) {
|
|||||||
return json.Marshal(t)
|
return json.Marshal(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scan 实现 sql.Scanner 接口,负责将数据库中的值转换为 TargetTime 结构体
|
||||||
func (t *TargetTime) Scan(value any) error {
|
func (t *TargetTime) Scan(value any) error {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
// 如果数据库是 NULL,保持指针对应的对象为零值即可
|
// 如果数据库是 NULL,保持指针对应的对象为零值即可
|
||||||
@@ -97,25 +116,18 @@ func (t *TargetTime) Scan(value any) error {
|
|||||||
return json.Unmarshal(data, t)
|
return json.Unmarshal(data, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TableName 指定 TaskClass 对应的数据库表名
|
||||||
|
func (TaskClass) TableName() string {
|
||||||
|
return "task_classes"
|
||||||
|
}
|
||||||
|
|
||||||
|
// TableName 指定 TaskClassItem 对应的数据库表名
|
||||||
func (TaskClassItem) TableName() string {
|
func (TaskClassItem) TableName() string {
|
||||||
return "task_items"
|
return "task_items"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 任务块状态常量
|
||||||
const (
|
const (
|
||||||
TaskItemStatusUnscheduled = 1
|
TaskItemStatusUnscheduled = 1 // 未安排
|
||||||
TaskItemStatusApplied = 2
|
TaskItemStatusApplied = 2 // 已应用
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserGetTaskClassesResponse struct {
|
|
||||||
TaskClasses []TaskClassSummary `json:"task_classes"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TaskClassSummary struct {
|
|
||||||
ID int `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Mode string `json:"mode"`
|
|
||||||
Strategy string `json:"strategy"`
|
|
||||||
StartDate time.Time `json:"start_date"`
|
|
||||||
EndDate time.Time `json:"end_date"`
|
|
||||||
TotalSlots int `json:"total_slots"`
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -54,11 +54,11 @@ func RegisterRouters(handlers *api.ApiHandlers, cache *dao.CacheDAO) *gin.Engine
|
|||||||
taskGroup.POST("/create", handlers.TaskHandler.AddTask)
|
taskGroup.POST("/create", handlers.TaskHandler.AddTask)
|
||||||
taskGroup.GET("/get", handlers.TaskHandler.GetUserTasks)
|
taskGroup.GET("/get", handlers.TaskHandler.GetUserTasks)
|
||||||
}
|
}
|
||||||
scheduleGroup := apiGroup.Group("/schedule")
|
courseGroup := apiGroup.Group("/course")
|
||||||
{
|
{
|
||||||
scheduleGroup.Use(middleware.JWTTokenAuth(cache))
|
courseGroup.Use(middleware.JWTTokenAuth(cache))
|
||||||
scheduleGroup.POST("/validate", handlers.ScheduleHandler.CheckUserCourse)
|
courseGroup.POST("/validate", handlers.ScheduleHandler.CheckUserCourse)
|
||||||
scheduleGroup.POST("/import-courses", handlers.ScheduleHandler.AddUserCourses)
|
courseGroup.POST("/import", handlers.ScheduleHandler.AddUserCourses)
|
||||||
}
|
}
|
||||||
taskClassGroup := apiGroup.Group("/task-class")
|
taskClassGroup := apiGroup.Group("/task-class")
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,21 +2,20 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/LoveLosita/smartflow/backend/dao"
|
"github.com/LoveLosita/smartflow/backend/dao"
|
||||||
"github.com/LoveLosita/smartflow/backend/model"
|
"github.com/LoveLosita/smartflow/backend/model"
|
||||||
"github.com/LoveLosita/smartflow/backend/respond"
|
"github.com/LoveLosita/smartflow/backend/respond"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ScheduleService struct {
|
type CourseService struct {
|
||||||
// 伸出手:准备接住 DAO
|
// 伸出手:准备接住 DAO
|
||||||
dao *dao.ScheduleDAO
|
dao *dao.CourseDAO
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewScheduleService 创建 ScheduleService 实例
|
// NewCourseService 创建 CourseService 实例
|
||||||
func NewScheduleService(dao *dao.ScheduleDAO) *ScheduleService {
|
func NewCourseService(dao *dao.CourseDAO) *CourseService {
|
||||||
return &ScheduleService{
|
return &CourseService{
|
||||||
dao: dao,
|
dao: dao,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -34,7 +33,7 @@ func CheckSingleCourse(req model.UserCheckCourseRequest) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddUserCourses 添加用户课程表
|
// AddUserCourses 添加用户课程表
|
||||||
func (ss *ScheduleService) AddUserCourses(ctx context.Context, req model.UserImportCoursesRequest, userID int) error {
|
func (ss *CourseService) AddUserCourses(ctx context.Context, req model.UserImportCoursesRequest, userID int) error {
|
||||||
//1.先校验参数是否正确
|
//1.先校验参数是否正确
|
||||||
for _, course := range req.Courses {
|
for _, course := range req.Courses {
|
||||||
result := CheckSingleCourse(course)
|
result := CheckSingleCourse(course)
|
||||||
@@ -43,30 +42,32 @@ func (ss *ScheduleService) AddUserCourses(ctx context.Context, req model.UserImp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//2.转换为 Schedule 切片
|
//2.转换为 Schedule 切片
|
||||||
|
var finalSchedules []model.Schedule
|
||||||
for _, course := range req.Courses {
|
for _, course := range req.Courses {
|
||||||
var schedules []model.Schedule
|
var schedules []model.Schedule
|
||||||
for _, arrangement := range course.Arrangements {
|
for _, arrangement := range course.Arrangements {
|
||||||
for week := arrangement.StartWeek; week <= arrangement.EndWeek; week++ {
|
for week := arrangement.StartWeek; week <= arrangement.EndWeek; week++ {
|
||||||
sections := fmt.Sprintf("%d-%d", arrangement.StartSection, arrangement.EndSection)
|
for section := arrangement.StartSection; section <= arrangement.EndSection; section++ {
|
||||||
schedule := model.Schedule{
|
schedule := model.Schedule{
|
||||||
Type: "course",
|
Type: "course",
|
||||||
Week: week,
|
Week: week,
|
||||||
DayOfWeek: arrangement.DayOfWeek,
|
DayOfWeek: arrangement.DayOfWeek,
|
||||||
Sections: sections,
|
Section: section,
|
||||||
Status: "normal",
|
Status: "normal",
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
CanBeEmbedded: course.IsAllowTasks,
|
CanBeEmbedded: course.IsAllowTasks,
|
||||||
|
}
|
||||||
|
schedules = append(schedules, schedule)
|
||||||
}
|
}
|
||||||
schedules = append(schedules, schedule)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//3.调用 DAO 方法添加课程
|
finalSchedules = append(finalSchedules, schedules...)
|
||||||
err := ss.dao.AddUserCourses(schedules)
|
}
|
||||||
if err != nil {
|
//3.调用 DAO 方法添加课程
|
||||||
return err
|
err := ss.dao.AddUserCourses(finalSchedules)
|
||||||
}
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//4.返回结果
|
//4.返回结果
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user