完成课程文件实现层

This commit is contained in:
2025-11-02 09:37:52 +08:00
parent 2f6bd84308
commit d23299ccac
5 changed files with 195 additions and 8 deletions

View File

@@ -28,6 +28,7 @@ type (
FindOne(ctx context.Context, id int64) (*CourseContent, error) FindOne(ctx context.Context, id int64) (*CourseContent, error)
Update(ctx context.Context, data *CourseContent) error Update(ctx context.Context, data *CourseContent) error
Delete(ctx context.Context, id int64) error Delete(ctx context.Context, id int64) error
FindByCourseAndParent(ctx context.Context, courseId, parentId int64) ([]*CourseContent, error)
} }
defaultCourseContentModel struct { defaultCourseContentModel struct {
@@ -84,6 +85,18 @@ func (m *defaultCourseContentModel) Update(ctx context.Context, data *CourseCont
return err return err
} }
func (m *defaultCourseContentModel) FindByCourseAndParent(ctx context.Context, courseId, parentId int64) ([]*CourseContent, error) {
// 构造查询语句按course_id和parent_id筛选按sort升序排序
query := fmt.Sprintf("select %s from %s where `course_id` = ? and `parent_id` = ? order by `sort` asc", courseContentRows, m.table)
var contents []*CourseContent
// 执行查询sqlx.QueryRowsCtx会自动将结果映射到结构体切片
err := m.conn.QueryRowsCtx(ctx, &contents, query, courseId, parentId)
if err != nil {
return nil, err
}
return contents, nil
}
func (m *defaultCourseContentModel) tableName() string { func (m *defaultCourseContentModel) tableName() string {
return m.table return m.table
} }

View File

@@ -5,6 +5,7 @@ package course_file
import ( import (
"context" "context"
"fmt"
"github.com/JACKYMYPERSON/hldrCenter/config" "github.com/JACKYMYPERSON/hldrCenter/config"
"github.com/JACKYMYPERSON/hldrCenter/internal/course_file/internal/model" "github.com/JACKYMYPERSON/hldrCenter/internal/course_file/internal/model"
@@ -30,7 +31,54 @@ func NewCreateCourseFileLogic(ctx context.Context, cfg *config.Config, model mod
} }
func (l *CreateCourseFileLogic) CreateCourseFile(req *types.CreateCourseFileReq) (resp *types.CreateCourseFileResp, err error) { func (l *CreateCourseFileLogic) CreateCourseFile(req *types.CreateCourseFileReq) (resp *types.CreateCourseFileResp, err error) {
// todo: add your logic here and delete this line // 1. 参数校验补充validate标签之外的业务校验
if req.ContentId <= 0 {
return nil, fmt.Errorf("参数错误关联的内容ID必须为正整数")
}
if len(req.Title) == 0 {
return nil, fmt.Errorf("参数错误:文件标题不能为空")
}
if len(req.Title) > 255 {
return nil, fmt.Errorf("参数错误文件标题长度不能超过255字符")
}
if len(req.FileType) == 0 {
return nil, fmt.Errorf("参数错误:文件类型不能为空")
}
if len(req.FileType) > 30 {
return nil, fmt.Errorf("参数错误文件类型长度不能超过30字符")
}
if len(req.FileUrl) == 0 {
return nil, fmt.Errorf("参数错误文件URL不能为空")
}
if len(req.FileUrl) > 255 {
return nil, fmt.Errorf("参数错误文件URL长度不能超过255字符")
}
return // 2. 转换请求参数为Model层结构体适配数据库字段类型
courseFile := &model.CourseFile{
ContentId: int64(req.ContentId), // 假设Model层ContentId为int64类型
Title: req.Title,
FileType: req.FileType,
FileUrl: req.FileUrl,
}
// 3. 调用Model层插入数据
result, err := l.model.Insert(l.ctx, courseFile)
if err != nil {
return nil, fmt.Errorf("创建课程文件失败:%w", err)
}
// 4. 获取新增记录的ID从插入结果中提取
newId, err := result.LastInsertId()
if err != nil {
return nil, fmt.Errorf("获取新增文件ID失败%w", err)
}
// 5. 构造响应
resp = &types.CreateCourseFileResp{
Id: int(newId), // 转换int64为int适配响应结构体
Message: "课程文件创建成功",
}
return resp, nil
} }

View File

@@ -5,10 +5,12 @@ package course_file
import ( import (
"context" "context"
"fmt"
"github.com/JACKYMYPERSON/hldrCenter/config" "github.com/JACKYMYPERSON/hldrCenter/config"
"github.com/JACKYMYPERSON/hldrCenter/internal/course_file/internal/model" "github.com/JACKYMYPERSON/hldrCenter/internal/course_file/internal/model"
"github.com/JACKYMYPERSON/hldrCenter/internal/course_file/internal/types" "github.com/JACKYMYPERSON/hldrCenter/internal/course_file/internal/types"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
) )
@@ -30,7 +32,32 @@ func NewDeleteCourseFileLogic(ctx context.Context, cfg *config.Config, model mod
} }
func (l *DeleteCourseFileLogic) DeleteCourseFile(req *types.DeleteCourseFileReq) (resp *types.DeleteCourseFileResp, err error) { func (l *DeleteCourseFileLogic) DeleteCourseFile(req *types.DeleteCourseFileReq) (resp *types.DeleteCourseFileResp, err error) {
// todo: add your logic here and delete this line // 1. 参数校验确保文件ID为正整数
if req.Id <= 0 {
return nil, fmt.Errorf("参数错误文件ID必须为正整数")
}
return // 2. 检查文件是否存在(避免删除不存在的记录)
fileId := int64(req.Id)
_, err = l.model.FindOne(l.ctx, fileId)
if err != nil {
if err == sqlx.ErrNotFound {
return nil, fmt.Errorf("删除失败:该文件不存在或已被删除")
}
// 其他查询错误(如数据库连接问题)
return nil, fmt.Errorf("查询文件信息失败:%w", err)
}
// 3. 调用Model层执行删除操作
err = l.model.Delete(l.ctx, fileId)
if err != nil {
return nil, fmt.Errorf("删除课程文件失败:%w", err)
}
// 4. 构造成功响应
resp = &types.DeleteCourseFileResp{
Message: "课程文件删除成功",
}
return resp, nil
} }

View File

@@ -5,6 +5,7 @@ package course_file
import ( import (
"context" "context"
"fmt"
"github.com/JACKYMYPERSON/hldrCenter/config" "github.com/JACKYMYPERSON/hldrCenter/config"
"github.com/JACKYMYPERSON/hldrCenter/internal/course_file/internal/model" "github.com/JACKYMYPERSON/hldrCenter/internal/course_file/internal/model"
@@ -30,7 +31,33 @@ func NewGetCourseFileLogic(ctx context.Context, cfg *config.Config, model model.
} }
func (l *GetCourseFileLogic) GetCourseFile(req *types.GetCourseFileReq) (resp *types.GetCourseFileResp, err error) { func (l *GetCourseFileLogic) GetCourseFile(req *types.GetCourseFileReq) (resp *types.GetCourseFileResp, 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层查询文件详情
fileId := int64(req.Id)
fileModel, err := l.model.FindOne(l.ctx, fileId)
if err != nil {
if err == model.ErrNotFound { // 匹配Model层自定义的"记录不存在"错误
return nil, fmt.Errorf("查询失败:该课程文件不存在或已被删除")
}
// 其他查询错误(如数据库异常)
return nil, fmt.Errorf("查询课程文件失败:%w", err)
}
// 3. 转换Model数据为响应结构体含时间格式化
resp = &types.GetCourseFileResp{
Id: int(fileModel.Id), // 适配int64→int
ContentId: int(fileModel.ContentId), // 适配int64→int
Title: fileModel.Title,
FileType: fileModel.FileType,
FileUrl: fileModel.FileUrl,
// 时间格式化:默认转为 "2006-01-02 15:04:05" 格式(可根据需求调整)
CreateTime: fileModel.CreateTime.Format("2006-01-02 15:04:05"),
UpdateTime: fileModel.UpdateTime.Format("2006-01-02 15:04:05"),
}
return resp, nil
} }

View File

@@ -5,10 +5,12 @@ package course_file
import ( import (
"context" "context"
"fmt"
"github.com/JACKYMYPERSON/hldrCenter/config" "github.com/JACKYMYPERSON/hldrCenter/config"
"github.com/JACKYMYPERSON/hldrCenter/internal/course_file/internal/model" "github.com/JACKYMYPERSON/hldrCenter/internal/course_file/internal/model"
"github.com/JACKYMYPERSON/hldrCenter/internal/course_file/internal/types" "github.com/JACKYMYPERSON/hldrCenter/internal/course_file/internal/types"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
) )
@@ -30,7 +32,77 @@ func NewUpdateCourseFileLogic(ctx context.Context, cfg *config.Config, model mod
} }
func (l *UpdateCourseFileLogic) UpdateCourseFile(req *types.UpdateCourseFileReq) (resp *types.UpdateCourseFileResp, err error) { func (l *UpdateCourseFileLogic) UpdateCourseFile(req *types.UpdateCourseFileReq) (resp *types.UpdateCourseFileResp, err error) {
// todo: add your logic here and delete this line // 1. 校验必填参数文件ID
if req.Id <= 0 {
return nil, fmt.Errorf("参数错误文件ID必须为正整数")
}
fileId := int64(req.Id)
return // 2. 校验可选参数(仅当参数存在时校验)
if req.ContentId > 0 { // 允许不传递ContentId传递时必须为正整数
if req.ContentId <= 0 {
return nil, fmt.Errorf("参数错误关联的内容ID必须为正整数")
}
}
if req.Title != "" { // 标题非空时校验长度
if len(req.Title) > 255 {
return nil, fmt.Errorf("参数错误文件标题长度不能超过255字符")
}
}
if req.FileType != "" { // 文件类型非空时校验长度
if len(req.FileType) > 30 {
return nil, fmt.Errorf("参数错误文件类型长度不能超过30字符")
}
}
if req.FileUrl != "" { // 文件URL非空时校验长度
if len(req.FileUrl) > 255 {
return nil, fmt.Errorf("参数错误文件URL长度不能超过255字符")
}
}
// 3. 检查文件是否存在(避免更新不存在的记录)
existingFile, err := l.model.FindOne(l.ctx, fileId)
if err != nil {
if err == model.ErrNotFound || err == sqlx.ErrNotFound {
return nil, fmt.Errorf("更新失败:该文件不存在或已被删除")
}
return nil, fmt.Errorf("查询文件信息失败:%w", err)
}
// 4. 构造更新数据(仅更新请求中提供的字段,未提供的保留原数据)
updateData := &model.CourseFile{
Id: existingFile.Id, // 必须保留原ID更新条件
ContentId: existingFile.ContentId, // 默认保留原关联ID
Title: existingFile.Title, // 默认保留原标题
FileType: existingFile.FileType, // 默认保留原文件类型
FileUrl: existingFile.FileUrl, // 默认保留原文件URL
// 若有时间字段可在此更新UpdateTimeUpdateTime: time.Now()
}
// 覆盖请求中提供的字段
if req.ContentId > 0 {
updateData.ContentId = int64(req.ContentId)
}
if req.Title != "" {
updateData.Title = req.Title
}
if req.FileType != "" {
updateData.FileType = req.FileType
}
if req.FileUrl != "" {
updateData.FileUrl = req.FileUrl
}
// 5. 调用Model层执行更新
err = l.model.Update(l.ctx, updateData)
if err != nil {
return nil, fmt.Errorf("更新课程文件失败:%w", err)
}
// 6. 构造成功响应
resp = &types.UpdateCourseFileResp{
Message: "课程文件更新成功",
}
return resp, nil
} }