From 886672f820ff9f3f036b5025b6259807e794f869 Mon Sep 17 00:00:00 2001 From: mayiming <1627832236@qq.com> Date: Sun, 2 Nov 2025 23:52:32 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=BE=E7=A8=8B=E6=95=99?= =?UTF-8?q?=E5=B8=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../deletecourseteacherhandler.go | 15 +++- .../course_teacher/getcourseteacherhandler.go | 15 +++- .../course_teacher/listcourseteacherlogic.go | 62 ++++++------- .../updatecourseteacherlogic.go | 86 ++++++++++++++++++- .../internal/model/courseteachermodel_gen.go | 33 ++----- 5 files changed, 146 insertions(+), 65 deletions(-) diff --git a/server/internal/course_teacher/handler/course_teacher/deletecourseteacherhandler.go b/server/internal/course_teacher/handler/course_teacher/deletecourseteacherhandler.go index 4ce25d1f..9fba9ac8 100644 --- a/server/internal/course_teacher/handler/course_teacher/deletecourseteacherhandler.go +++ b/server/internal/course_teacher/handler/course_teacher/deletecourseteacherhandler.go @@ -6,6 +6,8 @@ package course_teacher import ( "fmt" "net/http" + "strconv" + "strings" "github.com/JACKYMYPERSON/hldrCenter/config" "github.com/JACKYMYPERSON/hldrCenter/internal/course_teacher/internal/logic/course_teacher" @@ -18,10 +20,19 @@ import ( func DeleteCourseTeacherHandler(cfg *config.Config) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var req types.DeleteCourseTeacherReq - if err := httpx.Parse(r, &req); err != nil { - httpx.ErrorCtx(r.Context(), w, err) + pathParts := strings.Split(r.URL.Path, "/") + fmt.Println(pathParts) + if len(pathParts) < 3 { // 确保路径格式正确 + httpx.ErrorCtx(r.Context(), w, fmt.Errorf("invalid path format")) return } + idStr := pathParts[3] + id, err := strconv.ParseInt(idStr, 10, 64) + if err != nil { + httpx.ErrorCtx(r.Context(), w, fmt.Errorf("invalid meeting ID")) + return + } + req.Id = int(id) mysqlCfg := cfg.MySQL dsn := fmt.Sprintf( diff --git a/server/internal/course_teacher/handler/course_teacher/getcourseteacherhandler.go b/server/internal/course_teacher/handler/course_teacher/getcourseteacherhandler.go index 2276cdfa..1e6e5a1c 100644 --- a/server/internal/course_teacher/handler/course_teacher/getcourseteacherhandler.go +++ b/server/internal/course_teacher/handler/course_teacher/getcourseteacherhandler.go @@ -6,6 +6,8 @@ package course_teacher import ( "fmt" "net/http" + "strconv" + "strings" "github.com/JACKYMYPERSON/hldrCenter/config" "github.com/JACKYMYPERSON/hldrCenter/internal/course_teacher/internal/logic/course_teacher" @@ -18,10 +20,19 @@ import ( func GetCourseTeacherHandler(cfg *config.Config) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var req types.GetCourseTeacherReq - if err := httpx.Parse(r, &req); err != nil { - httpx.ErrorCtx(r.Context(), w, err) + pathParts := strings.Split(r.URL.Path, "/") + fmt.Println(pathParts) + if len(pathParts) < 3 { // 确保路径格式正确 + httpx.ErrorCtx(r.Context(), w, fmt.Errorf("invalid path format")) return } + idStr := pathParts[3] + id, err := strconv.ParseInt(idStr, 10, 64) + if err != nil { + httpx.ErrorCtx(r.Context(), w, fmt.Errorf("invalid meeting ID")) + return + } + req.Id = int(id) mysqlCfg := cfg.MySQL dsn := fmt.Sprintf( diff --git a/server/internal/course_teacher/internal/logic/course_teacher/listcourseteacherlogic.go b/server/internal/course_teacher/internal/logic/course_teacher/listcourseteacherlogic.go index e13032d2..0ca48e42 100644 --- a/server/internal/course_teacher/internal/logic/course_teacher/listcourseteacherlogic.go +++ b/server/internal/course_teacher/internal/logic/course_teacher/listcourseteacherlogic.go @@ -5,7 +5,6 @@ package course_teacher import ( "context" - "database/sql" "fmt" "github.com/JACKYMYPERSON/hldrCenter/config" @@ -32,57 +31,62 @@ func NewListCourseTeacherLogic(ctx context.Context, cfg *config.Config, model mo } func (l *ListCourseTeacherLogic) ListCourseTeacher(req *types.ListCourseTeacherReq) (resp *types.ListCourseTeacherResp, err error) { - // 1. 参数校验(补充validate标签外的业务校验) + // 1. 强化参数校验(覆盖所有可能的无效参数) if req.Page < 1 { return nil, fmt.Errorf("参数错误:页码必须≥1") } if req.PageSize < 1 || req.PageSize > 100 { return nil, fmt.Errorf("参数错误:每页条数必须在1-100之间") } + if req.CourseId < 0 { // 新增:禁止负数课程ID(无实际业务意义) + return nil, fmt.Errorf("参数错误:课程ID不能为负数") + } - // 2. 转换筛选参数为int64(适配Model层字段类型) - courseId := int64(req.CourseId) - teacherId := int64(req.TeacherId) + // 2. 转换筛选参数(适配Model层int64字段类型) + courseId := int64(req.CourseId) // 0表示不按课程ID筛选,Model层会忽略 - // 3. 计算分页参数(offset = (page-1)*pageSize) + // 3. 计算分页参数(标准分页公式,避免偏移量为负) offset := (req.Page - 1) * req.PageSize + if offset < 0 { // 兜底:防止极端情况下offset为负 + offset = 0 + } - // 4. 调用Model层查询总条数(按筛选条件) - total, err := l.model.CountByConditions(l.ctx, courseId, teacherId) + // 4. 查询符合条件的总条数(无teacher_id筛选,仅可选按course_id) + total, err := l.model.CountByConditions(l.ctx, courseId) if err != nil { return nil, fmt.Errorf("查询教师总条数失败:%w", err) } - // 5. 调用Model层查询当前页数据(按筛选条件+分页+排序) + // 5. 修复调用:参数类型/数量严格对齐Model层函数定义 + // Model层函数签名:FindByConditionsWithPage(ctx, courseId(int64), pageSize(int), offset(int)) teachers, err := l.model.FindByConditionsWithPage( l.ctx, - courseId, // 课程ID筛选(0表示不筛选) - teacherId, // 教师ID筛选(0表示不筛选) - req.PageSize, // 每页条数 - offset, // 偏移量 + courseId, // 课程ID(int64,匹配Model层) + req.PageSize, // 每页条数(int,无需转int64,直接传req.PageSize) + offset, // 偏移量(int,匹配Model层) ) if err != nil { return nil, fmt.Errorf("查询教师列表失败:%w", err) } - // 6. 转换Model数据为响应列表(处理sql.NullString和int64→int) + // 6. 数据转换(统一处理sql.NullString类型,避免空值异常) var list []types.GetCourseTeacherResp for _, t := range teachers { list = append(list, types.GetCourseTeacherResp{ - Id: int(t.Id), // int64→int - CourseId: int(t.CourseId), // int64→int - TeacherId: int(t.TeacherId), // int64→int + Id: int(t.Id), + CourseId: int(t.CourseId), + TeacherId: int(t.TeacherId), Name: t.Name, - Title: t.Title, // sql.NullString→string - Avatar: t.Avatar, // sql.NullString→string - Intro: NullStringToString(t.Intro), // sql.NullString→string - Sort: int(t.Sort), // int64→int + Title: t.Title, + Avatar: t.Avatar, + Intro: NullStringToString(t.Intro), + Sort: int(t.Sort), }) } - // 7. 构造响应 + // 7. 构造标准响应 resp = &types.ListCourseTeacherResp{ - Total: int(total), // 总条数(int64→int) + Total: int(total), List: list, Page: req.Page, PageSize: req.PageSize, @@ -90,15 +94,3 @@ func (l *ListCourseTeacherLogic) ListCourseTeacher(req *types.ListCourseTeacherR return resp, nil } - -func StringToNullString(s string) sql.NullString { - if s != "" { - return sql.NullString{ - String: s, - Valid: true, - } - } - return sql.NullString{ - Valid: false, // 空字符串时标记为无效,数据库存 NULL - } -} diff --git a/server/internal/course_teacher/internal/logic/course_teacher/updatecourseteacherlogic.go b/server/internal/course_teacher/internal/logic/course_teacher/updatecourseteacherlogic.go index 787f2ed3..2d096fe2 100644 --- a/server/internal/course_teacher/internal/logic/course_teacher/updatecourseteacherlogic.go +++ b/server/internal/course_teacher/internal/logic/course_teacher/updatecourseteacherlogic.go @@ -5,6 +5,9 @@ package course_teacher import ( "context" + "database/sql" + "errors" + "fmt" "github.com/JACKYMYPERSON/hldrCenter/config" "github.com/JACKYMYPERSON/hldrCenter/internal/course_teacher/internal/model" @@ -30,7 +33,86 @@ func NewUpdateCourseTeacherLogic(ctx context.Context, cfg *config.Config, model } func (l *UpdateCourseTeacherLogic) UpdateCourseTeacher(req *types.UpdateCourseTeacherReq) (resp *types.UpdateCourseTeacherResp, err error) { - // todo: add your logic here and delete this line + // 1. 基础参数校验(确保ID有效) + if req.Id <= 0 { + return nil, fmt.Errorf("参数错误:关联ID必须为正整数") + } - return + // 2. 查询原记录(确保记录存在) + // 注意:此处假设Model层有FindOne方法(根据ID查询单条记录) + original, err := l.model.FindOne(l.ctx, int64(req.Id)) + if err != nil { + if errors.Is(err, model.ErrNotFound) { // 假设Model层定义了ErrNotFound表示记录不存在 + return nil, fmt.Errorf("课程教师关联记录不存在(ID: %d)", req.Id) + } + return nil, fmt.Errorf("查询原记录失败:%w", err) + } + + // 3. 构建更新数据(仅更新请求中提供的非空/有效字段) + updateData := &model.CourseTeacher{ + Id: int64(req.Id), // 必须携带ID用于WHERE条件 + // 基础字段默认沿用原记录,后续按需覆盖 + CourseId: original.CourseId, + TeacherId: original.TeacherId, + Name: original.Name, + Title: original.Title, + Avatar: original.Avatar, + Intro: original.Intro, + Sort: original.Sort, + } + + // 3.1 可选更新:课程ID(若请求中提供了有效值) + if req.CourseId > 0 { + updateData.CourseId = int64(req.CourseId) + } + + // 3.2 可选更新:教师ID(若请求中提供了有效值) + if req.TeacherId > 0 { + updateData.TeacherId = int64(req.TeacherId) + } + + // 3.3 可选更新:教师姓名(若请求中提供了非空值) + if req.Name != "" { + updateData.Name = req.Name + } + + // 3.4 可选更新:教师头衔(若请求中提供了非空值) + if req.Title != "" { + updateData.Title = req.Title + } + + // 3.5 可选更新:头像URL(若请求中提供了非空值) + if req.Avatar != "" { + updateData.Avatar = req.Avatar + } + + // 3.6 可选更新:教师简介(若请求中提供了非空值,允许清空) + if req.Intro != "" { // 注意:若需允许清空简介,此处直接赋值(空字符串也会更新) + updateData.Intro = StringToNullString(req.Intro) + } + + // 3.7 可选更新:排序值(若请求中提供了有效值) + if req.Sort >= 0 { // 符合validate规则:min=0 + updateData.Sort = int64(req.Sort) + } + + // 4. 调用Model层执行更新 + err = l.model.Update(l.ctx, updateData) + if err != nil { + return nil, fmt.Errorf("更新课程教师关联记录失败:%w", err) + } + + // 5. 构建成功响应 + resp = &types.UpdateCourseTeacherResp{ + Message: fmt.Sprintf("课程教师关联记录(ID: %d)更新成功", req.Id), + } + + return resp, nil +} + +func StringToNullString(s string) sql.NullString { + if s != "" { + return sql.NullString{String: s, Valid: true} + } + return sql.NullString{Valid: false} } diff --git a/server/internal/course_teacher/internal/model/courseteachermodel_gen.go b/server/internal/course_teacher/internal/model/courseteachermodel_gen.go index 09c31671..186a3a78 100644 --- a/server/internal/course_teacher/internal/model/courseteachermodel_gen.go +++ b/server/internal/course_teacher/internal/model/courseteachermodel_gen.go @@ -28,10 +28,10 @@ type ( FindOne(ctx context.Context, id int64) (*CourseTeacher, error) Update(ctx context.Context, data *CourseTeacher) error Delete(ctx context.Context, id int64) error - CountByConditions(ctx context.Context, courseId, teacherId int64) (int64, error) + CountByConditions(ctx context.Context, courseId int64) (int64, error) FindByConditionsWithPage( ctx context.Context, - courseId, teacherId int64, + courseId int64, pageSize, offset int, ) ([]*CourseTeacher, error) } @@ -67,7 +67,7 @@ func (m *defaultCourseTeacherModel) Delete(ctx context.Context, id int64) error } func (m *defaultCourseTeacherModel) FindOne(ctx context.Context, id int64) (*CourseTeacher, error) { - query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", courseTeacherRows, m.table) + query := fmt.Sprintf("select %s from %s where `course_id` = ? limit 1", courseTeacherRows, m.table) var resp CourseTeacher err := m.conn.QueryRowCtx(ctx, &resp, query, id) switch err { @@ -92,74 +92,59 @@ func (m *defaultCourseTeacherModel) Update(ctx context.Context, data *CourseTeac return err } -func (m *defaultCourseTeacherModel) CountByConditions(ctx context.Context, courseId, teacherId int64) (int64, error) { +func (m *defaultCourseTeacherModel) CountByConditions(ctx context.Context, courseId int64) (int64, error) { // 移除teacherId参数 var count int64 baseQuery := fmt.Sprintf("select count(*) from %s", m.table) - // 构造筛选条件(支持单条件/多条件/无筛选) var whereClauses []string var args []interface{} + // 只保留course_id的筛选(如果需要),删除teacher_id的筛选逻辑 if courseId > 0 { whereClauses = append(whereClauses, "`course_id` = ?") args = append(args, courseId) } - if teacherId > 0 { - whereClauses = append(whereClauses, "`teacher_id` = ?") - args = append(args, teacherId) - } - // 拼接完整查询语句 if len(whereClauses) > 0 { baseQuery += " where " + strings.Join(whereClauses, " and ") } - // 执行查询 err := m.conn.QueryRowCtx(ctx, &count, baseQuery, args...) return count, err } - -// FindByConditionsWithPage 实现按条件分页查询 func (m *defaultCourseTeacherModel) FindByConditionsWithPage( ctx context.Context, - courseId, teacherId int64, + courseId int64, // 移除teacherId参数 pageSize, offset int, ) ([]*CourseTeacher, error) { var teachers []*CourseTeacher baseQuery := fmt.Sprintf("select %s from %s", courseTeacherRows, m.table) - // 构造筛选条件(同CountByConditions) var whereClauses []string var args []interface{} + // 只保留course_id的筛选(如果需要),删除teacher_id的筛选逻辑 if courseId > 0 { whereClauses = append(whereClauses, "`course_id` = ?") args = append(args, courseId) } - if teacherId > 0 { - whereClauses = append(whereClauses, "`teacher_id` = ?") - args = append(args, teacherId) - } - // 拼接分页和排序(按sort升序,确保展示顺序一致) + // 分页参数 pageQuery := " order by `sort` asc limit ?, ?" - args = append(args, offset, pageSize) // 补充分页参数 + args = append(args, offset, pageSize) - // 拼接完整查询语句 if len(whereClauses) > 0 { baseQuery += " where " + strings.Join(whereClauses, " and ") + pageQuery } else { baseQuery += pageQuery } - // 执行查询 err := m.conn.QueryRowsCtx(ctx, &teachers, baseQuery, args...) if err != nil { return nil, err } return teachers, nil } - func (m *defaultCourseTeacherModel) tableName() string { return m.table }