From bb7df7e7b3ae98387f1a3fbaf060d57e27bb2d51 Mon Sep 17 00:00:00 2001 From: mayiming <1627832236@qq.com> Date: Fri, 31 Oct 2025 13:26:49 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0course=E7=9A=84=E4=B8=9A?= =?UTF-8?q?=E5=8A=A1=E5=B1=82=E5=92=8C=E5=AE=9E=E7=8E=B0=E5=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handler/course/createcoursehandler.go | 50 ++++++ .../handler/course/deletecoursehandler.go | 61 +++++++ .../course/handler/course/getcoursehandler.go | 61 +++++++ .../handler/course/listcoursehandler.go | 50 ++++++ .../handler/course/updatecoursehandler.go | 50 ++++++ .../logic/course/createcourselogic.go | 94 +++++++++++ .../logic/course/deletecourselogic.go | 78 +++++++++ .../internal/logic/course/getcourselogic.go | 85 ++++++++++ .../internal/logic/course/listcourselogic.go | 107 ++++++++++++ .../logic/course/updatecourselogic.go | 89 ++++++++++ .../course/internal/model/coursemodel.go | 29 ++++ .../course/internal/model/coursemodel_gen.go | 157 ++++++++++++++++++ server/internal/course/internal/model/vars.go | 5 + .../internal/course/internal/types/types.go | 57 +++++++ .../course_content/addcontenthandler.go | 31 ++++ .../course_content/deletecontenthandler.go | 31 ++++ .../course_content/getcontenthandler.go | 31 ++++ .../course_content/getcontentlisthandler.go | 31 ++++ .../course_content/updatecontenthandler.go | 31 ++++ .../logic/course_content/addcontentlogic.go | 33 ++++ .../course_content/deletecontentlogic.go | 33 ++++ .../course_content/getcontentlistlogic.go | 33 ++++ .../logic/course_content/getcontentlogic.go | 33 ++++ .../course_content/updatecontentlogic.go | 33 ++++ .../internal/model/coursecontentmodel.go | 29 ++++ .../internal/model/coursecontentmodel_gen.go | 89 ++++++++++ .../course_content/internal/model/vars.go | 5 + .../course_content/internal/types/types.go | 70 ++++++++ 28 files changed, 1486 insertions(+) create mode 100644 server/internal/course/handler/course/createcoursehandler.go create mode 100644 server/internal/course/handler/course/deletecoursehandler.go create mode 100644 server/internal/course/handler/course/getcoursehandler.go create mode 100644 server/internal/course/handler/course/listcoursehandler.go create mode 100644 server/internal/course/handler/course/updatecoursehandler.go create mode 100644 server/internal/course/internal/logic/course/createcourselogic.go create mode 100644 server/internal/course/internal/logic/course/deletecourselogic.go create mode 100644 server/internal/course/internal/logic/course/getcourselogic.go create mode 100644 server/internal/course/internal/logic/course/listcourselogic.go create mode 100644 server/internal/course/internal/logic/course/updatecourselogic.go create mode 100644 server/internal/course/internal/model/coursemodel.go create mode 100644 server/internal/course/internal/model/coursemodel_gen.go create mode 100644 server/internal/course/internal/model/vars.go create mode 100644 server/internal/course/internal/types/types.go create mode 100644 server/internal/course_content/handler/course_content/addcontenthandler.go create mode 100644 server/internal/course_content/handler/course_content/deletecontenthandler.go create mode 100644 server/internal/course_content/handler/course_content/getcontenthandler.go create mode 100644 server/internal/course_content/handler/course_content/getcontentlisthandler.go create mode 100644 server/internal/course_content/handler/course_content/updatecontenthandler.go create mode 100644 server/internal/course_content/internal/logic/course_content/addcontentlogic.go create mode 100644 server/internal/course_content/internal/logic/course_content/deletecontentlogic.go create mode 100644 server/internal/course_content/internal/logic/course_content/getcontentlistlogic.go create mode 100644 server/internal/course_content/internal/logic/course_content/getcontentlogic.go create mode 100644 server/internal/course_content/internal/logic/course_content/updatecontentlogic.go create mode 100644 server/internal/course_content/internal/model/coursecontentmodel.go create mode 100644 server/internal/course_content/internal/model/coursecontentmodel_gen.go create mode 100644 server/internal/course_content/internal/model/vars.go create mode 100644 server/internal/course_content/internal/types/types.go diff --git a/server/internal/course/handler/course/createcoursehandler.go b/server/internal/course/handler/course/createcoursehandler.go new file mode 100644 index 00000000..9ae9cb3e --- /dev/null +++ b/server/internal/course/handler/course/createcoursehandler.go @@ -0,0 +1,50 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course + +import ( + "fmt" + "net/http" + + "github.com/JACKYMYPERSON/hldrCenter/config" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/logic/course" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/model" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/types" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func CreateCourseHandler(cfg *config.Config) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.CreateCourseReq + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + mysqlCfg := cfg.MySQL + dsn := fmt.Sprintf( + "%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=true&loc=Local", + mysqlCfg.Username, + mysqlCfg.Password, + mysqlCfg.Host, + mysqlCfg.Port, + mysqlCfg.Database, + mysqlCfg.Charset, + ) + fmt.Println("接收到articlePost请求") + + conn := sqlx.NewSqlConn("mysql", dsn) + + baseModel := model.NewCourseModel(conn) + + l := course.NewCreateCourseLogic(r.Context(), cfg, baseModel) + resp, err := l.CreateCourse(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/server/internal/course/handler/course/deletecoursehandler.go b/server/internal/course/handler/course/deletecoursehandler.go new file mode 100644 index 00000000..4145e372 --- /dev/null +++ b/server/internal/course/handler/course/deletecoursehandler.go @@ -0,0 +1,61 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course + +import ( + "fmt" + "net/http" + "strconv" + "strings" + + "github.com/JACKYMYPERSON/hldrCenter/config" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/logic/course" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/model" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/types" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func DeleteCourseHandler(cfg *config.Config) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.DeleteCourseReq + pathParts := strings.Split(r.URL.Path, "/") + 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 + } + fmt.Println("idStr:", idStr) + req.Id = id + + mysqlCfg := cfg.MySQL + dsn := fmt.Sprintf( + "%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=true&loc=Local", + mysqlCfg.Username, + mysqlCfg.Password, + mysqlCfg.Host, + mysqlCfg.Port, + mysqlCfg.Database, + mysqlCfg.Charset, + ) + fmt.Println("接收到articlePost请求") + + conn := sqlx.NewSqlConn("mysql", dsn) + + baseModel := model.NewCourseModel(conn) + + l := course.NewDeleteCourseLogic(r.Context(), cfg, baseModel) + resp, err := l.DeleteCourse(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/server/internal/course/handler/course/getcoursehandler.go b/server/internal/course/handler/course/getcoursehandler.go new file mode 100644 index 00000000..32ee5b85 --- /dev/null +++ b/server/internal/course/handler/course/getcoursehandler.go @@ -0,0 +1,61 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course + +import ( + "fmt" + "net/http" + "strconv" + "strings" + + "github.com/JACKYMYPERSON/hldrCenter/config" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/logic/course" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/model" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/types" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func GetCourseHandler(cfg *config.Config) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.GetCourseReq + pathParts := strings.Split(r.URL.Path, "/") + 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 + } + fmt.Println("idStr:", idStr) + req.Id = id + + mysqlCfg := cfg.MySQL + dsn := fmt.Sprintf( + "%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=true&loc=Local", + mysqlCfg.Username, + mysqlCfg.Password, + mysqlCfg.Host, + mysqlCfg.Port, + mysqlCfg.Database, + mysqlCfg.Charset, + ) + fmt.Println("接收到articlePost请求") + + conn := sqlx.NewSqlConn("mysql", dsn) + + baseModel := model.NewCourseModel(conn) + + l := course.NewGetCourseLogic(r.Context(), cfg, baseModel) + resp, err := l.GetCourse(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/server/internal/course/handler/course/listcoursehandler.go b/server/internal/course/handler/course/listcoursehandler.go new file mode 100644 index 00000000..90f5b388 --- /dev/null +++ b/server/internal/course/handler/course/listcoursehandler.go @@ -0,0 +1,50 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course + +import ( + "fmt" + "net/http" + + "github.com/JACKYMYPERSON/hldrCenter/config" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/logic/course" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/model" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/types" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func ListCourseHandler(cfg *config.Config) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.ListCourseReq + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + mysqlCfg := cfg.MySQL + dsn := fmt.Sprintf( + "%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=true&loc=Local", + mysqlCfg.Username, + mysqlCfg.Password, + mysqlCfg.Host, + mysqlCfg.Port, + mysqlCfg.Database, + mysqlCfg.Charset, + ) + fmt.Println("接收到articlePost请求") + + conn := sqlx.NewSqlConn("mysql", dsn) + + baseModel := model.NewCourseModel(conn) + + l := course.NewListCourseLogic(r.Context(), cfg, baseModel) + resp, err := l.ListCourse(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/server/internal/course/handler/course/updatecoursehandler.go b/server/internal/course/handler/course/updatecoursehandler.go new file mode 100644 index 00000000..42412030 --- /dev/null +++ b/server/internal/course/handler/course/updatecoursehandler.go @@ -0,0 +1,50 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course + +import ( + "fmt" + "net/http" + + "github.com/JACKYMYPERSON/hldrCenter/config" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/logic/course" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/model" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/types" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func UpdateCourseHandler(cfg *config.Config) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.UpdateCourseReq + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + mysqlCfg := cfg.MySQL + dsn := fmt.Sprintf( + "%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=true&loc=Local", + mysqlCfg.Username, + mysqlCfg.Password, + mysqlCfg.Host, + mysqlCfg.Port, + mysqlCfg.Database, + mysqlCfg.Charset, + ) + fmt.Println("接收到articlePost请求") + + conn := sqlx.NewSqlConn("mysql", dsn) + + baseModel := model.NewCourseModel(conn) + + l := course.NewUpdateCourseLogic(r.Context(), cfg, baseModel) + resp, err := l.UpdateCourse(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/server/internal/course/internal/logic/course/createcourselogic.go b/server/internal/course/internal/logic/course/createcourselogic.go new file mode 100644 index 00000000..66e628b1 --- /dev/null +++ b/server/internal/course/internal/logic/course/createcourselogic.go @@ -0,0 +1,94 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course + +import ( + "context" + "database/sql" + "fmt" + + "github.com/JACKYMYPERSON/hldrCenter/config" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/model" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/types" + "github.com/go-playground/validator/v10" + + "github.com/zeromicro/go-zero/core/logx" +) + +type CreateCourseLogic struct { + logx.Logger + ctx context.Context + cfg *config.Config + model model.CourseModel +} + +func NewCreateCourseLogic(ctx context.Context, cfg *config.Config, model model.CourseModel) *CreateCourseLogic { + return &CreateCourseLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + cfg: cfg, + model: model, + } +} + +func (l *CreateCourseLogic) CreateCourse(req *types.CreateCourseReq) (resp *types.BaseResp, err error) { + // 初始化验证器 + validate := validator.New() + + // 验证请求参数 + if err := validate.Struct(req); err != nil { + // 收集所有验证错误 + var errMsg string + for _, e := range err.(validator.ValidationErrors) { + errMsg += fmt.Sprintf("参数 %s 验证失败: %s; ", e.Field(), e.Tag()) + } + return &types.BaseResp{ + Code: 400, // 非0表示失败 + Msg: "参数验证失败: " + errMsg, + }, nil + } + + // 构造课程数据对象 + course := &model.Course{ + Title: req.Title, + Subtitle: req.Subtitle, + CoverUrl: req.CoverUrl, + Intro: stringToNullString(req.Intro), + Status: int64(req.Status), + } + + // 调用模型层插入数据 + result, err := l.model.Insert(l.ctx, course) + if err != nil { + return &types.BaseResp{ + Code: 500, // 非0表示失败 + Msg: "创建课程失败: " + err.Error(), + }, nil + } + + // 获取插入的课程ID + courseId, err := result.LastInsertId() + if err != nil { + return &types.BaseResp{ + Code: 500, // 非0表示失败 + Msg: "获取课程ID失败: " + err.Error(), + }, nil + } + + // 返回成功响应(0表示成功) + return &types.BaseResp{ + Code: 0, + Msg: fmt.Sprintf("课程创建成功,ID: %d", courseId), + }, nil +} + +func stringToNullString(s string) sql.NullString { + if s == "" { + return sql.NullString{Valid: false} + } + return sql.NullString{ + String: s, + Valid: true, + } +} diff --git a/server/internal/course/internal/logic/course/deletecourselogic.go b/server/internal/course/internal/logic/course/deletecourselogic.go new file mode 100644 index 00000000..6a309761 --- /dev/null +++ b/server/internal/course/internal/logic/course/deletecourselogic.go @@ -0,0 +1,78 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course + +import ( + "context" + "fmt" + + "github.com/JACKYMYPERSON/hldrCenter/config" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/model" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/types" + "github.com/go-playground/validator/v10" + + "github.com/zeromicro/go-zero/core/logx" +) + +type DeleteCourseLogic struct { + logx.Logger + ctx context.Context + cfg *config.Config + model model.CourseModel +} + +func NewDeleteCourseLogic(ctx context.Context, cfg *config.Config, model model.CourseModel) *DeleteCourseLogic { + return &DeleteCourseLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + cfg: cfg, + model: model, + } +} + +func (l *DeleteCourseLogic) DeleteCourse(req *types.DeleteCourseReq) (resp *types.BaseResp, err error) { + // 1. 参数验证 + validate := validator.New() + if err := validate.Struct(req); err != nil { + var errMsg string + for _, e := range err.(validator.ValidationErrors) { + errMsg += fmt.Sprintf("参数 %s 验证失败: %s; ", e.Field(), e.Tag()) + } + return &types.BaseResp{ + Code: 400, + Msg: "参数验证失败: " + errMsg, + }, nil + } + + // 2. 复用FindOne方法检查课程是否存在 + _, err = l.model.FindOne(l.ctx, req.Id) + if err != nil { + if err == model.ErrNotFound { // 注意:这里需要匹配你实际的ErrNotFound定义 + return &types.BaseResp{ + Code: 404, + Msg: fmt.Sprintf("课程ID=%d不存在", req.Id), + }, nil + } + // 其他查询错误 + return &types.BaseResp{ + Code: 500, + Msg: "查询课程信息失败: " + err.Error(), + }, nil + } + + // 3. 执行逻辑删除(更新is_delete为1) + err = l.model.Delete(l.ctx, req.Id) + if err != nil { + return &types.BaseResp{ + Code: 500, + Msg: "删除课程失败: " + err.Error(), + }, nil + } + + // 4. 返回成功响应 + return &types.BaseResp{ + Code: 0, + Msg: fmt.Sprintf("课程ID=%d删除成功", req.Id), + }, nil +} diff --git a/server/internal/course/internal/logic/course/getcourselogic.go b/server/internal/course/internal/logic/course/getcourselogic.go new file mode 100644 index 00000000..33059956 --- /dev/null +++ b/server/internal/course/internal/logic/course/getcourselogic.go @@ -0,0 +1,85 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course + +import ( + "context" + "database/sql" + "fmt" + "time" + + "github.com/JACKYMYPERSON/hldrCenter/config" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/model" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/types" + "github.com/go-playground/validator/v10" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetCourseLogic struct { + logx.Logger + ctx context.Context + cfg *config.Config + model model.CourseModel +} + +func NewGetCourseLogic(ctx context.Context, cfg *config.Config, model model.CourseModel) *GetCourseLogic { + return &GetCourseLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + cfg: cfg, + model: model, + } +} + +func (l *GetCourseLogic) GetCourse(req *types.GetCourseReq) (resp *types.CourseResp, err error) { + // 1. 参数验证(匹配结构体中的validate标签) + validate := validator.New() + if err := validate.Struct(req); err != nil { + var errMsg string + for _, e := range err.(validator.ValidationErrors) { + errMsg += fmt.Sprintf("参数 %s 验证失败: %s; ", e.Field(), e.Tag()) + } + return nil, fmt.Errorf("参数验证失败: %s", errMsg) + } + + // 2. 调用模型层查询课程 + course, err := l.model.FindOne(l.ctx, req.Id) + if err != nil { + if err == model.ErrNotFound { + return nil, fmt.Errorf("课程不存在") + } + return nil, fmt.Errorf("查询课程失败: %w", err) + } + + // 3. 转换模型数据到响应结构体 + resp = &types.CourseResp{ + Id: course.Id, + Title: course.Title, + Subtitle: course.Subtitle, + CoverUrl: course.CoverUrl, + Intro: nullStringToString(course.Intro), + Status: int8(course.Status), + CreateTime: formatTime(course.CreateTime), + UpdateTime: formatTime(course.UpdateTime), + } + + return resp, nil +} + +// 辅助函数:将sql.NullString转换为string(处理数据库NULL值) +func nullStringToString(ns sql.NullString) string { + if ns.Valid { + return ns.String + } + return "" +} + +// 辅助函数:格式化时间为字符串(处理可能的零值时间) +func formatTime(t time.Time) string { + if t.IsZero() { + return "" + } + return t.Format("2006-01-02 15:04:05") +} diff --git a/server/internal/course/internal/logic/course/listcourselogic.go b/server/internal/course/internal/logic/course/listcourselogic.go new file mode 100644 index 00000000..2c1aa905 --- /dev/null +++ b/server/internal/course/internal/logic/course/listcourselogic.go @@ -0,0 +1,107 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course + +import ( + "context" + "fmt" + + "github.com/JACKYMYPERSON/hldrCenter/config" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/model" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/types" + "github.com/zeromicro/go-zero/core/logx" +) + +type ListCourseLogic struct { + logx.Logger + ctx context.Context + cfg *config.Config + model model.CourseModel +} + +func NewListCourseLogic(ctx context.Context, cfg *config.Config, model model.CourseModel) *ListCourseLogic { + return &ListCourseLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + cfg: cfg, + model: model, + } +} + +func (l *ListCourseLogic) ListCourse(req *types.ListCourseReq) (resp *types.ListCourseResp, err error) { + // 1. 参数验证与默认值处理 + if err := validateListCourseReq(req); err != nil { + return nil, err + } + + // 处理分页默认值(根据结构体tag的default定义) + page := req.Page + size := req.Size + if page <= 0 { + page = 1 // 默认第一页 + } + if size <= 0 { + size = 10 // 默认每页10条 + } + offset := (page - 1) * size + + // 2. 构建查询条件 + filter := model.CourseFilter{ + Status: req.Status, + Keyword: req.Keyword, + Offset: offset, + Limit: size, + } + + // 3. 查询课程列表数据 + courses, err := l.model.List(l.ctx, filter) + if err != nil { + return nil, fmt.Errorf("查询课程列表失败: %w", err) + } + + // 4. 查询符合条件的总条数 + total, err := l.model.Count(l.ctx, filter) + if err != nil { + return nil, fmt.Errorf("查询课程总数失败: %w", err) + } + + // 5. 转换数据格式(model -> types) + var courseList []types.CourseResp + for _, course := range courses { + courseList = append(courseList, types.CourseResp{ + Id: course.Id, + Title: course.Title, + Subtitle: course.Subtitle, + CoverUrl: course.CoverUrl, + Intro: nullStringToString(course.Intro), // 包含简介信息 + Status: int8(course.Status), + CreateTime: formatTime(course.CreateTime), + UpdateTime: formatTime(course.UpdateTime), // 包含更新时间 + }) + } + + // 6. 组装响应数据 + resp = &types.ListCourseResp{ + Total: total, + List: courseList, + } + + return resp, nil +} + +// 参数验证函数 +func validateListCourseReq(req *types.ListCourseReq) error { + // 自定义验证规则:页码和每页数量不能为负数 + if req.Page < 0 { + return fmt.Errorf("页码不能为负数") + } + if req.Size < 0 { + return fmt.Errorf("每页数量不能为负数") + } + // 状态值验证(根据业务实际允许的状态值调整) + if req.Status < 0 && req.Status != -1 { // 假设-1表示不筛选状态 + return fmt.Errorf("无效的状态值") + } + return nil +} diff --git a/server/internal/course/internal/logic/course/updatecourselogic.go b/server/internal/course/internal/logic/course/updatecourselogic.go new file mode 100644 index 00000000..0479760f --- /dev/null +++ b/server/internal/course/internal/logic/course/updatecourselogic.go @@ -0,0 +1,89 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course + +import ( + "context" + "fmt" + + "github.com/JACKYMYPERSON/hldrCenter/config" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/model" + "github.com/JACKYMYPERSON/hldrCenter/internal/course/internal/types" + "github.com/go-playground/validator/v10" + + "github.com/zeromicro/go-zero/core/logx" +) + +type UpdateCourseLogic struct { + logx.Logger + ctx context.Context + cfg *config.Config + model model.CourseModel +} + +func NewUpdateCourseLogic(ctx context.Context, cfg *config.Config, model model.CourseModel) *UpdateCourseLogic { + return &UpdateCourseLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + cfg: cfg, + model: model, + } +} + +func (l *UpdateCourseLogic) UpdateCourse(req *types.UpdateCourseReq) (resp *types.BaseResp, err error) { + // 1. 参数验证 + validate := validator.New() + if err := validate.Struct(req); err != nil { + var errMsg string + for _, e := range err.(validator.ValidationErrors) { + errMsg += fmt.Sprintf("参数 %s 验证失败: %s; ", e.Field(), e.Tag()) + } + return &types.BaseResp{ + Code: 400, + Msg: "参数验证失败: " + errMsg, + }, nil + } + + // 2. 检查课程是否存在 + existingCourse, err := l.model.FindOne(l.ctx, req.Id) + if err != nil { + if err == model.ErrNotFound { + return &types.BaseResp{ + Code: 404, + Msg: fmt.Sprintf("课程ID=%d不存在", req.Id), + }, nil + } + return &types.BaseResp{ + Code: 500, + Msg: "查询课程信息失败: " + err.Error(), + }, nil + } + + // 3. 构造更新数据(保留原有字段,仅更新请求中提供的字段) + updatedCourse := &model.Course{ + Id: req.Id, // 必须指定更新的课程ID + Title: req.Title, // 标题(如果为空会覆盖原有值,根据业务需求调整) + Subtitle: req.Subtitle, // 副标题 + CoverUrl: req.CoverUrl, // 封面图URL + Intro: stringToNullString(req.Intro), // 课程简介 + Status: int64(req.Status), // 课程状态 + CreateTime: existingCourse.CreateTime, // 保留原始创建时间 + UpdateTime: existingCourse.UpdateTime, // 可由数据库自动更新,这里暂用原有值 + } + + // 4. 执行更新操作 + err = l.model.Update(l.ctx, updatedCourse) + if err != nil { + return &types.BaseResp{ + Code: 500, + Msg: "更新课程失败: " + err.Error(), + }, nil + } + + // 5. 返回成功响应 + return &types.BaseResp{ + Code: 0, + Msg: fmt.Sprintf("课程ID=%d更新成功", req.Id), + }, nil +} diff --git a/server/internal/course/internal/model/coursemodel.go b/server/internal/course/internal/model/coursemodel.go new file mode 100644 index 00000000..5b8b1591 --- /dev/null +++ b/server/internal/course/internal/model/coursemodel.go @@ -0,0 +1,29 @@ +package model + +import "github.com/zeromicro/go-zero/core/stores/sqlx" + +var _ CourseModel = (*customCourseModel)(nil) + +type ( + // CourseModel is an interface to be customized, add more methods here, + // and implement the added methods in customCourseModel. + CourseModel interface { + courseModel + withSession(session sqlx.Session) CourseModel + } + + customCourseModel struct { + *defaultCourseModel + } +) + +// NewCourseModel returns a model for the database table. +func NewCourseModel(conn sqlx.SqlConn) CourseModel { + return &customCourseModel{ + defaultCourseModel: newCourseModel(conn), + } +} + +func (m *customCourseModel) withSession(session sqlx.Session) CourseModel { + return NewCourseModel(sqlx.NewSqlConnFromSession(session)) +} diff --git a/server/internal/course/internal/model/coursemodel_gen.go b/server/internal/course/internal/model/coursemodel_gen.go new file mode 100644 index 00000000..fca32e5e --- /dev/null +++ b/server/internal/course/internal/model/coursemodel_gen.go @@ -0,0 +1,157 @@ +// Code generated by goctl. DO NOT EDIT. +// versions: +// goctl version: 1.9.2 + +package model + +import ( + "context" + "database/sql" + "fmt" + "strings" + "time" + + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" +) + +var ( + courseFieldNames = builder.RawFieldNames(&Course{}) + courseRows = strings.Join(courseFieldNames, ",") + courseRowsExpectAutoSet = strings.Join(stringx.Remove(courseFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",") + courseRowsWithPlaceHolder = strings.Join(stringx.Remove(courseFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?" +) + +type ( + courseModel interface { + Insert(ctx context.Context, data *Course) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*Course, error) + Update(ctx context.Context, data *Course) error + Delete(ctx context.Context, id int64) error + List(ctx context.Context, filter CourseFilter) ([]*Course, error) + Count(ctx context.Context, filter CourseFilter) (int64, error) + } + + defaultCourseModel struct { + conn sqlx.SqlConn + table string + } + + Course struct { + Id int64 `db:"id"` // 课程ID(主键) + Title string `db:"title"` // 课程标题 + Subtitle string `db:"subtitle"` // 课程副标题 + CoverUrl string `db:"cover_url"` // 课程封面图URL + Intro sql.NullString `db:"intro"` // 课程简介(对应“课程简介”模块) + Status int64 `db:"status"` // 课程状态(0删除,1-已发布) + CreateTime time.Time `db:"create_time"` // 创建时间 + UpdateTime time.Time `db:"update_time"` // 更新时间 + } + + CourseFilter struct { + Status int8 // 状态筛选 + Keyword string // 关键词搜索 + Offset int // 分页偏移量 + Limit int // 分页数量 + } +) + +func newCourseModel(conn sqlx.SqlConn) *defaultCourseModel { + return &defaultCourseModel{ + conn: conn, + table: "`course`", + } +} + +func (m *defaultCourseModel) Delete(ctx context.Context, id int64) error { + query := fmt.Sprintf("update %s set `status` = 0, `update_time` = CURRENT_TIMESTAMP where `id` = ?", m.table) + _, err := m.conn.ExecCtx(ctx, query, id) + return err +} + +func (m *defaultCourseModel) FindOne(ctx context.Context, id int64) (*Course, error) { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", courseRows, m.table) + var resp Course + err := m.conn.QueryRowCtx(ctx, &resp, query, id) + switch err { + case nil: + return &resp, nil + case sqlx.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultCourseModel) Insert(ctx context.Context, data *Course) (sql.Result, error) { + query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?)", m.table, courseRowsExpectAutoSet) + ret, err := m.conn.ExecCtx(ctx, query, data.Title, data.Subtitle, data.CoverUrl, data.Intro, data.Status) + return ret, err +} + +func (m *defaultCourseModel) Update(ctx context.Context, data *Course) error { + query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, courseRowsWithPlaceHolder) + _, err := m.conn.ExecCtx(ctx, query, data.Title, data.Subtitle, data.CoverUrl, data.Intro, data.Status, data.Id) + return err +} + +func (m *defaultCourseModel) List(ctx context.Context, filter CourseFilter) ([]*Course, error) { + query := fmt.Sprintf("select %s from %s where 1=1", courseRows, m.table) + args := []interface{}{} + + // 状态筛选逻辑: + // - 如果未指定filter.Status(默认值),默认只查询"已发布"(status=1) + // - 如果指定了filter.Status(0或1),则按指定值筛选(支持查询已删除的课程) + if filter.Status == -1 { + // 默认筛选:只查已发布(status=1) + query += " and `status` = 1" + } else { + // 按指定status筛选(0=删除,1=发布) + query += " and `status` = ?" + args = append(args, filter.Status) + } + + // 关键词搜索(标题和副标题模糊匹配) + if filter.Keyword != "" { + query += " and (`title` like ? or `subtitle` like ?)" + args = append(args, "%"+filter.Keyword+"%", "%"+filter.Keyword+"%") + } + + // 分页处理 + query += " limit ?, ?" + args = append(args, filter.Offset, filter.Limit) + + // 执行查询 + var courses []*Course + err := m.conn.QueryRowsCtx(ctx, &courses, query, args...) + return courses, err +} + +// 配套的Count方法也需要同步修改(确保总数计算正确) +func (m *defaultCourseModel) Count(ctx context.Context, filter CourseFilter) (int64, error) { + query := fmt.Sprintf("select count(1) from %s where 1=1", m.table) + args := []interface{}{} + + // 与List方法保持一致的status筛选逻辑 + if filter.Status == -1 { + query += " and `status` = 1" + } else { + query += " and `status` = ?" + args = append(args, filter.Status) + } + + // 关键词搜索条件 + if filter.Keyword != "" { + query += " and (`title` like ? or `subtitle` like ?)" + args = append(args, "%"+filter.Keyword+"%", "%"+filter.Keyword+"%") + } + + var total int64 + err := m.conn.QueryRowCtx(ctx, &total, query, args...) + return total, err +} + +func (m *defaultCourseModel) tableName() string { + return m.table +} diff --git a/server/internal/course/internal/model/vars.go b/server/internal/course/internal/model/vars.go new file mode 100644 index 00000000..69ca814e --- /dev/null +++ b/server/internal/course/internal/model/vars.go @@ -0,0 +1,5 @@ +package model + +import "github.com/zeromicro/go-zero/core/stores/sqlx" + +var ErrNotFound = sqlx.ErrNotFound diff --git a/server/internal/course/internal/types/types.go b/server/internal/course/internal/types/types.go new file mode 100644 index 00000000..27693e2b --- /dev/null +++ b/server/internal/course/internal/types/types.go @@ -0,0 +1,57 @@ +// Code generated by goctl. DO NOT EDIT. +// goctl 1.9.2 + +package types + +type BaseResp struct { + Code int `json:"code"` // 状态码(0成功,非0失败) + Msg string `json:"msg"` // 提示信息 +} + +type CourseResp struct { + Id int64 `json:"id"` // 课程ID + Title string `json:"title"` // 课程标题 + Subtitle string `json:"subtitle"` // 课程副标题 + CoverUrl string `json:"cover_url"` // 课程封面图URL + Intro string `json:"intro"` // 课程简介 + Status int8 `json:"status"` // 课程状态 + CreateTime string `json:"create_time"` // 创建时间 + UpdateTime string `json:"update_time"` // 更新时间 +} + +type CreateCourseReq struct { + Title string `json:"title" validate:"required"` // 课程标题 + Subtitle string `json:"subtitle"` // 课程副标题 + CoverUrl string `json:"cover_url"` // 课程封面图URL + Intro string `json:"intro"` // 课程简介 + Status int8 `json:"status" default:"1"` // 课程状态(0删除,1-已发布) +} + +type DeleteCourseReq struct { + Id int64 `json:"id" validate:"required"` // 课程ID +} + +type GetCourseReq struct { + Id int64 `json:"id" path:"id" validate:"required"` // 课程ID +} + +type ListCourseReq struct { + Page int `json:"page" default:"1"` // 页码 + Size int `json:"size" default:"10"` // 每页数量 + Status int8 `json:"status"` // 课程状态筛选 + Keyword string `json:"keyword"` // 搜索关键词(标题/副标题) +} + +type ListCourseResp struct { + Total int64 `json:"total"` // 总条数 + List []CourseResp `json:"list"` // 课程列表 +} + +type UpdateCourseReq struct { + Id int64 `json:"id" validate:"required"` // 课程ID + Title string `json:"title"` // 课程标题 + Subtitle string `json:"subtitle"` // 课程副标题 + CoverUrl string `json:"cover_url"` // 课程封面图URL + Intro string `json:"intro"` // 课程简介 + Status int8 `json:"status"` // 课程状态(0删除,1-已发布) +} diff --git a/server/internal/course_content/handler/course_content/addcontenthandler.go b/server/internal/course_content/handler/course_content/addcontenthandler.go new file mode 100644 index 00000000..e227d93f --- /dev/null +++ b/server/internal/course_content/handler/course_content/addcontenthandler.go @@ -0,0 +1,31 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course_content + +import ( + "net/http" + + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/logic/course_content" + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/svc" + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func AddContentHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.AddContentReq + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := course_content.NewAddContentLogic(r.Context(), svcCtx) + resp, err := l.AddContent(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/server/internal/course_content/handler/course_content/deletecontenthandler.go b/server/internal/course_content/handler/course_content/deletecontenthandler.go new file mode 100644 index 00000000..c2601fe1 --- /dev/null +++ b/server/internal/course_content/handler/course_content/deletecontenthandler.go @@ -0,0 +1,31 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course_content + +import ( + "net/http" + + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/logic/course_content" + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/svc" + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func DeleteContentHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.DeleteContentReq + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := course_content.NewDeleteContentLogic(r.Context(), svcCtx) + resp, err := l.DeleteContent(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/server/internal/course_content/handler/course_content/getcontenthandler.go b/server/internal/course_content/handler/course_content/getcontenthandler.go new file mode 100644 index 00000000..95a4b0be --- /dev/null +++ b/server/internal/course_content/handler/course_content/getcontenthandler.go @@ -0,0 +1,31 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course_content + +import ( + "net/http" + + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/logic/course_content" + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/svc" + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func GetContentHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.GetContentReq + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := course_content.NewGetContentLogic(r.Context(), svcCtx) + resp, err := l.GetContent(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/server/internal/course_content/handler/course_content/getcontentlisthandler.go b/server/internal/course_content/handler/course_content/getcontentlisthandler.go new file mode 100644 index 00000000..e777f57a --- /dev/null +++ b/server/internal/course_content/handler/course_content/getcontentlisthandler.go @@ -0,0 +1,31 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course_content + +import ( + "net/http" + + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/logic/course_content" + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/svc" + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func GetContentListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.GetContentListReq + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := course_content.NewGetContentListLogic(r.Context(), svcCtx) + resp, err := l.GetContentList(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/server/internal/course_content/handler/course_content/updatecontenthandler.go b/server/internal/course_content/handler/course_content/updatecontenthandler.go new file mode 100644 index 00000000..5096929b --- /dev/null +++ b/server/internal/course_content/handler/course_content/updatecontenthandler.go @@ -0,0 +1,31 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course_content + +import ( + "net/http" + + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/logic/course_content" + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/svc" + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func UpdateContentHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.UpdateContentReq + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := course_content.NewUpdateContentLogic(r.Context(), svcCtx) + resp, err := l.UpdateContent(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/server/internal/course_content/internal/logic/course_content/addcontentlogic.go b/server/internal/course_content/internal/logic/course_content/addcontentlogic.go new file mode 100644 index 00000000..25bcc2fd --- /dev/null +++ b/server/internal/course_content/internal/logic/course_content/addcontentlogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course_content + +import ( + "context" + + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/svc" + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type AddContentLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewAddContentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AddContentLogic { + return &AddContentLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *AddContentLogic) AddContent(req *types.AddContentReq) (resp *types.AddContentResp, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/server/internal/course_content/internal/logic/course_content/deletecontentlogic.go b/server/internal/course_content/internal/logic/course_content/deletecontentlogic.go new file mode 100644 index 00000000..ef949b73 --- /dev/null +++ b/server/internal/course_content/internal/logic/course_content/deletecontentlogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course_content + +import ( + "context" + + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/svc" + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type DeleteContentLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewDeleteContentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteContentLogic { + return &DeleteContentLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *DeleteContentLogic) DeleteContent(req *types.DeleteContentReq) (resp *types.DeleteContentResp, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/server/internal/course_content/internal/logic/course_content/getcontentlistlogic.go b/server/internal/course_content/internal/logic/course_content/getcontentlistlogic.go new file mode 100644 index 00000000..e948eac1 --- /dev/null +++ b/server/internal/course_content/internal/logic/course_content/getcontentlistlogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course_content + +import ( + "context" + + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/svc" + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetContentListLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetContentListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetContentListLogic { + return &GetContentListLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *GetContentListLogic) GetContentList(req *types.GetContentListReq) (resp *types.GetContentListResp, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/server/internal/course_content/internal/logic/course_content/getcontentlogic.go b/server/internal/course_content/internal/logic/course_content/getcontentlogic.go new file mode 100644 index 00000000..cacec309 --- /dev/null +++ b/server/internal/course_content/internal/logic/course_content/getcontentlogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course_content + +import ( + "context" + + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/svc" + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetContentLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetContentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetContentLogic { + return &GetContentLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *GetContentLogic) GetContent(req *types.GetContentReq) (resp *types.GetContentResp, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/server/internal/course_content/internal/logic/course_content/updatecontentlogic.go b/server/internal/course_content/internal/logic/course_content/updatecontentlogic.go new file mode 100644 index 00000000..83ff84f0 --- /dev/null +++ b/server/internal/course_content/internal/logic/course_content/updatecontentlogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package course_content + +import ( + "context" + + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/svc" + "github.com/JACKYMYPERSON/hldrCenter/internal/course_content/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type UpdateContentLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewUpdateContentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateContentLogic { + return &UpdateContentLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *UpdateContentLogic) UpdateContent(req *types.UpdateContentReq) (resp *types.UpdateContentResp, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/server/internal/course_content/internal/model/coursecontentmodel.go b/server/internal/course_content/internal/model/coursecontentmodel.go new file mode 100644 index 00000000..2c5ced01 --- /dev/null +++ b/server/internal/course_content/internal/model/coursecontentmodel.go @@ -0,0 +1,29 @@ +package model + +import "github.com/zeromicro/go-zero/core/stores/sqlx" + +var _ CourseContentModel = (*customCourseContentModel)(nil) + +type ( + // CourseContentModel is an interface to be customized, add more methods here, + // and implement the added methods in customCourseContentModel. + CourseContentModel interface { + courseContentModel + withSession(session sqlx.Session) CourseContentModel + } + + customCourseContentModel struct { + *defaultCourseContentModel + } +) + +// NewCourseContentModel returns a model for the database table. +func NewCourseContentModel(conn sqlx.SqlConn) CourseContentModel { + return &customCourseContentModel{ + defaultCourseContentModel: newCourseContentModel(conn), + } +} + +func (m *customCourseContentModel) withSession(session sqlx.Session) CourseContentModel { + return NewCourseContentModel(sqlx.NewSqlConnFromSession(session)) +} diff --git a/server/internal/course_content/internal/model/coursecontentmodel_gen.go b/server/internal/course_content/internal/model/coursecontentmodel_gen.go new file mode 100644 index 00000000..d451e28b --- /dev/null +++ b/server/internal/course_content/internal/model/coursecontentmodel_gen.go @@ -0,0 +1,89 @@ +// Code generated by goctl. DO NOT EDIT. +// versions: +// goctl version: 1.9.2 + +package model + +import ( + "context" + "database/sql" + "fmt" + "strings" + + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" +) + +var ( + courseContentFieldNames = builder.RawFieldNames(&CourseContent{}) + courseContentRows = strings.Join(courseContentFieldNames, ",") + courseContentRowsExpectAutoSet = strings.Join(stringx.Remove(courseContentFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",") + courseContentRowsWithPlaceHolder = strings.Join(stringx.Remove(courseContentFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?" +) + +type ( + courseContentModel interface { + Insert(ctx context.Context, data *CourseContent) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*CourseContent, error) + Update(ctx context.Context, data *CourseContent) error + Delete(ctx context.Context, id int64) error + } + + defaultCourseContentModel struct { + conn sqlx.SqlConn + table string + } + + CourseContent struct { + Id int64 `db:"id"` // 内容ID(主键) + CourseId int64 `db:"course_id"` // 关联课程ID + ParentId int64 `db:"parent_id"` // 父级ID(0表示章节,>0表示小节,关联自身id) + Title string `db:"title"` // 章节/小节标题 + Content sql.NullString `db:"content"` // 内容详情(如视频地址、图文内容等) + Sort int64 `db:"sort"` // 排序(数字越小越靠前) + } +) + +func newCourseContentModel(conn sqlx.SqlConn) *defaultCourseContentModel { + return &defaultCourseContentModel{ + conn: conn, + table: "`course_content`", + } +} + +func (m *defaultCourseContentModel) Delete(ctx context.Context, id int64) error { + query := fmt.Sprintf("delete from %s where `id` = ?", m.table) + _, err := m.conn.ExecCtx(ctx, query, id) + return err +} + +func (m *defaultCourseContentModel) FindOne(ctx context.Context, id int64) (*CourseContent, error) { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", courseContentRows, m.table) + var resp CourseContent + err := m.conn.QueryRowCtx(ctx, &resp, query, id) + switch err { + case nil: + return &resp, nil + case sqlx.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultCourseContentModel) Insert(ctx context.Context, data *CourseContent) (sql.Result, error) { + query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?)", m.table, courseContentRowsExpectAutoSet) + ret, err := m.conn.ExecCtx(ctx, query, data.CourseId, data.ParentId, data.Title, data.Content, data.Sort) + return ret, err +} + +func (m *defaultCourseContentModel) Update(ctx context.Context, data *CourseContent) error { + query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, courseContentRowsWithPlaceHolder) + _, err := m.conn.ExecCtx(ctx, query, data.CourseId, data.ParentId, data.Title, data.Content, data.Sort, data.Id) + return err +} + +func (m *defaultCourseContentModel) tableName() string { + return m.table +} diff --git a/server/internal/course_content/internal/model/vars.go b/server/internal/course_content/internal/model/vars.go new file mode 100644 index 00000000..69ca814e --- /dev/null +++ b/server/internal/course_content/internal/model/vars.go @@ -0,0 +1,5 @@ +package model + +import "github.com/zeromicro/go-zero/core/stores/sqlx" + +var ErrNotFound = sqlx.ErrNotFound diff --git a/server/internal/course_content/internal/types/types.go b/server/internal/course_content/internal/types/types.go new file mode 100644 index 00000000..28bb7a00 --- /dev/null +++ b/server/internal/course_content/internal/types/types.go @@ -0,0 +1,70 @@ +// Code generated by goctl. DO NOT EDIT. +// goctl 1.9.2 + +package types + +type AddContentReq struct { + CourseId int `json:"course_id" form:"course_id"` // 课程ID,必填 + ParentId int `json:"parent_id" form:"parent_id"` // 父级ID,必填 + Title string `json:"title" form:"title"` // 标题,必填 + Content string `json:"content" form:"content"` // 内容详情,可选 + Sort int `json:"sort" form:"sort"` // 排序,可选 +} + +type AddContentResp struct { + BaseResp + Data int `json:"data"` // 新增内容的ID +} + +type BaseResp struct { + Code int `json:"code"` // 状态码,0表示成功 + Message string `json:"message"` // 提示信息 + Data interface{} `json:"data"` // 响应数据 +} + +type CourseContent struct { + Id int `json:"id"` // 内容ID(主键) + CourseId int `json:"course_id"` // 关联课程ID + ParentId int `json:"parent_id"` // 父级ID(0表示章节,>0表示小节) + Title string `json:"title"` // 章节/小节标题 + Content string `json:"content"` // 内容详情 + Sort int `json:"sort"` // 排序 +} + +type DeleteContentReq struct { + Id int `json:"id" form:"id" uri:"id"` // 内容ID,必填 +} + +type DeleteContentResp struct { + BaseResp +} + +type GetContentListReq struct { + CourseId int `json:"course_id" form:"course_id"` // 课程ID,必填 + ParentId int `json:"parent_id" form:"parent_id"` // 父级ID,可选,0表示获取章节 +} + +type GetContentListResp struct { + BaseResp + Data []CourseContent `json:"data"` // 内容列表 +} + +type GetContentReq struct { + Id int `json:"id" form:"id" uri:"id"` // 内容ID,必填 +} + +type GetContentResp struct { + BaseResp + Data CourseContent `json:"data"` // 内容详情 +} + +type UpdateContentReq struct { + Id int `json:"id" form:"id"` // 内容ID,必填 + Title string `json:"title" form:"title"` // 标题,可选 + Content string `json:"content" form:"content"` // 内容详情,可选 + Sort int `json:"sort" form:"sort"` // 排序,可选 +} + +type UpdateContentResp struct { + BaseResp +}