完成所有接口的实现层

This commit is contained in:
2025-11-02 11:10:17 +08:00
parent d23299ccac
commit 7f8c25484e
20 changed files with 918 additions and 28 deletions

View File

@@ -5,6 +5,9 @@ package course_activity
import (
"context"
"database/sql"
"fmt"
"time"
"github.com/JACKYMYPERSON/hldrCenter/config"
"github.com/JACKYMYPERSON/hldrCenter/internal/course_activity/internal/model"
@@ -30,7 +33,95 @@ func NewCreateCourseActivityLogic(ctx context.Context, cfg *config.Config, model
}
func (l *CreateCourseActivityLogic) CreateCourseActivity(req *types.CreateCourseActivityReq) (resp *types.CreateCourseActivityResp, err error) {
// todo: add your logic here and delete this line
// 1. 基础参数校验
if req.CourseId <= 0 {
return nil, fmt.Errorf("参数错误课程ID必须为正整数")
}
if len(req.Title) == 0 || len(req.Title) > 255 {
return nil, fmt.Errorf("参数错误活动标题不能为空且长度不超过255字符")
}
return
// 2. 可选参数校验与默认值设置
// 活动类型未传递则默认1作业传递则校验1-4范围
activityType := 1
if req.ActivityType != 0 {
if req.ActivityType < 1 || req.ActivityType > 4 {
return nil, fmt.Errorf("参数错误活动类型必须是1-41-作业/2-考试/3-讨论/4-直播)")
}
activityType = req.ActivityType
}
// 排序未传递则默认0
sort := 0
if req.Sort >= 0 {
sort = req.Sort
}
// 3. 时间参数解析与适配 sql.NullTime核心修改
timeLayout := "2006-01-02 15:04:05"
var startTime, endTime sql.NullTime // 改为 sql.NullTime 类型
// 解析开始时间:传递则解析并标记 Valid=true未传递则 Valid=false数据库存NULL
if req.StartTime != "" {
parsedTime, err := time.Parse(timeLayout, req.StartTime)
if err != nil {
return nil, fmt.Errorf("参数错误开始时间格式不正确需符合yyyy-MM-dd HH:mm:ss")
}
startTime = sql.NullTime{Time: parsedTime, Valid: true}
}
// 解析结束时间:逻辑同上
if req.EndTime != "" {
parsedTime, err := time.Parse(timeLayout, req.EndTime)
if err != nil {
return nil, fmt.Errorf("参数错误结束时间格式不正确需符合yyyy-MM-dd HH:mm:ss")
}
endTime = sql.NullTime{Time: parsedTime, Valid: true}
}
// 校验:若同时传递开始和结束时间,结束时间需晚于开始时间
if startTime.Valid && endTime.Valid && endTime.Time.Before(startTime.Time) {
return nil, fmt.Errorf("参数错误:结束时间不能早于开始时间")
}
// 4. 转换请求参数为Model层结构体适配 sql.NullTime 和 int64
activityModel := &model.CourseActivity{
CourseId: int64(req.CourseId), // int→int64适配数据库
Title: req.Title,
ActivityType: int64(activityType), // int→int64
Content: stringToNullString(req.Content),
StartTime: startTime, // 直接赋值 sql.NullTime
EndTime: endTime, // 直接赋值 sql.NullTime
Sort: int64(sort), // int→int64
}
// 5. 调用Model层插入数据
result, err := l.model.Insert(l.ctx, activityModel)
if err != nil {
return nil, fmt.Errorf("创建课程活动失败:%w", err)
}
// 6. 获取新增活动的ID
newId, err := result.LastInsertId()
if err != nil {
return nil, fmt.Errorf("获取新增活动ID失败%w", err)
}
// 7. 构造响应
resp = &types.CreateCourseActivityResp{
Id: int(newId), // int64→int适配响应
Message: "课程活动创建成功",
}
return resp, nil
}
func stringToNullString(s string) sql.NullString {
if s == "" {
return sql.NullString{Valid: false}
}
return sql.NullString{
String: s,
Valid: true,
}
}

View File

@@ -30,7 +30,18 @@ func NewDeleteCourseActivityLogic(ctx context.Context, cfg *config.Config, model
}
func (l *DeleteCourseActivityLogic) DeleteCourseActivity(req *types.DeleteCourseActivityReq) (resp *types.DeleteCourseActivityResp, err error) {
// todo: add your logic here and delete this line
// 将请求中的int类型ID转换为数据层需要的int64类型
activityID := int64(req.Id)
return
// 调用数据层的删除方法
err = l.model.Delete(l.ctx, activityID)
if err != nil {
// 若删除过程出现错误,返回错误信息
return nil, err
}
// 删除成功,返回操作结果
return &types.DeleteCourseActivityResp{
Message: "课程活动已成功删除",
}, nil
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/JACKYMYPERSON/hldrCenter/config"
"github.com/JACKYMYPERSON/hldrCenter/internal/course_activity/internal/model"
"github.com/JACKYMYPERSON/hldrCenter/internal/course_activity/internal/types"
"github.com/JACKYMYPERSON/hldrCenter/util"
"github.com/zeromicro/go-zero/core/logx"
)
@@ -30,7 +31,28 @@ func NewGetCourseActivityLogic(ctx context.Context, cfg *config.Config, model mo
}
func (l *GetCourseActivityLogic) GetCourseActivity(req *types.GetCourseActivityReq) (resp *types.GetCourseActivityResp, err error) {
// todo: add your logic here and delete this line
// 将请求中的int类型ID转换为数据层需要的int64类型
activityID := int64(req.Id)
return
// 调用数据层方法查询活动详情
activity, err := l.model.FindOne(l.ctx, activityID)
if err != nil {
// 若查询出错(如未找到或数据库错误),返回错误
return nil, err
}
// 将数据层模型转换为响应结构体
resp = &types.GetCourseActivityResp{
Id: int(activity.Id), // 转换int64为int
CourseId: int(activity.CourseId), // 转换关联课程ID类型
Title: activity.Title, // 活动标题
ActivityType: int(activity.ActivityType), // 转换活动类型
Content: util.NullStringToString(activity.Content), // 活动详情
// 假设数据层返回的是time.Time类型这里格式化为字符串根据实际格式调整
StartTime: util.NullTimeToString(activity.StartTime),
EndTime: util.NullTimeToString(activity.EndTime),
Sort: int(activity.Sort), // 转换排序字段类型
}
return resp, nil
}

View File

@@ -5,10 +5,12 @@ package course_activity
import (
"context"
"strings"
"github.com/JACKYMYPERSON/hldrCenter/config"
"github.com/JACKYMYPERSON/hldrCenter/internal/course_activity/internal/model"
"github.com/JACKYMYPERSON/hldrCenter/internal/course_activity/internal/types"
"github.com/JACKYMYPERSON/hldrCenter/util"
"github.com/zeromicro/go-zero/core/logx"
)
@@ -30,7 +32,67 @@ func NewListCourseActivityLogic(ctx context.Context, cfg *config.Config, model m
}
func (l *ListCourseActivityLogic) ListCourseActivity(req *types.ListCourseActivityReq) (resp *types.ListCourseActivityResp, err error) {
// todo: add your logic here and delete this line
// 1. 处理分页参数计算偏移量页码从1开始
// 2. 构建查询条件根据可选参数拼接WHERE子句
var whereConditions []string
var queryArgs []interface{}
return
// 按课程ID筛选若传入有效CourseId
if req.CourseId > 0 {
whereConditions = append(whereConditions, "course_id = ?")
queryArgs = append(queryArgs, req.CourseId)
}
// 按活动类型筛选若传入有效ActivityType1-4
if req.ActivityType >= 1 && req.ActivityType <= 4 {
whereConditions = append(whereConditions, "activity_type = ?")
queryArgs = append(queryArgs, req.ActivityType)
}
// 拼接WHERE子句若有条件则添加where多个条件用and连接
whereClause := ""
if len(whereConditions) > 0 {
whereClause = "WHERE " + strings.Join(whereConditions, " AND ")
}
// 3. 查询符合条件的总条数(用于分页计算)
total, err := l.model.Count(l.ctx, whereClause, queryArgs...)
if err != nil {
return nil, err // 传递数据库查询错误
}
// 4. 查询当前页的活动列表数据
activities, err := l.model.FindAll(
l.ctx,
whereClause,
queryArgs..., // 这里是最后一个参数,符合语法
)
if err != nil {
return nil, err
}
// 5. 转换数据层模型为响应列表(复用单个活动的转换逻辑)
list := make([]types.GetCourseActivityResp, 0, len(activities))
for _, activity := range activities {
list = append(list, types.GetCourseActivityResp{
Id: util.Int64ToInt(activity.Id),
CourseId: util.Int64ToInt(activity.CourseId),
Title: activity.Title,
ActivityType: util.Int64ToInt(activity.ActivityType),
Content: util.NullStringToString(activity.Content),
StartTime: util.NullTimeToString(activity.StartTime),
EndTime: util.NullTimeToString(activity.EndTime),
Sort: util.Int64ToInt(activity.Sort),
})
}
// 6. 构建并返回响应
resp = &types.ListCourseActivityResp{
Total: total, // 总条数
List: list, // 转换后的活动列表
Page: req.Page, // 当前页码(透传请求参数)
PageSize: req.PageSize, // 每页条数(透传请求参数)
}
return resp, nil
}

View File

@@ -5,6 +5,10 @@ package course_activity
import (
"context"
"database/sql"
"errors"
"fmt"
"time"
"github.com/JACKYMYPERSON/hldrCenter/config"
"github.com/JACKYMYPERSON/hldrCenter/internal/course_activity/internal/model"
@@ -30,7 +34,83 @@ func NewUpdateCourseActivityLogic(ctx context.Context, cfg *config.Config, model
}
func (l *UpdateCourseActivityLogic) UpdateCourseActivity(req *types.UpdateCourseActivityReq) (resp *types.UpdateCourseActivityResp, err error) {
// todo: add your logic here and delete this line
// 1. 转换活动ID为数据层所需的int64类型
activityID := int64(req.Id)
return
// 2. 查询原始活动信息(确保活动存在,用于保留未更新字段的原始值)
original, err := l.model.FindOne(l.ctx, activityID)
if err != nil {
if errors.Is(err, errors.New("resource not found")) {
return nil, fmt.Errorf("活动不存在ID: %d", req.Id)
}
return nil, fmt.Errorf("查询活动信息失败: %v", err)
}
// 3. 处理开始时间字符串转sql.NullTime
var startTime sql.NullTime
if req.StartTime != "" {
// 解析请求中的时间字符串
parsedTime, err := time.Parse("2006-01-02 15:04:05", req.StartTime)
if err != nil {
return nil, fmt.Errorf("开始时间格式错误需符合2006-01-02 15:04:05: %v", err)
}
startTime = sql.NullTime{Time: parsedTime, Valid: true} // 标记为有效时间
} else {
startTime = original.StartTime // 未提供则沿用原始值
}
// 4. 处理结束时间(逻辑同上)
var endTime sql.NullTime
if req.EndTime != "" {
parsedTime, err := time.Parse("2006-01-02 15:04:05", req.EndTime)
if err != nil {
return nil, fmt.Errorf("结束时间格式错误需符合2006-01-02 15:04:05: %v", err)
}
endTime = sql.NullTime{Time: parsedTime, Valid: true}
} else {
endTime = original.EndTime // 未提供则沿用原始值
}
// 5. 构建更新数据(基于原始数据,覆盖请求中提供的字段)
updateData := &model.CourseActivity{
Id: activityID, // 主键ID必须保留用于WHERE条件
CourseId: original.CourseId, // 默认沿用原始课程ID
Title: original.Title, // 默认沿用原始标题
ActivityType: original.ActivityType, // 默认沿用原始活动类型
Content: original.Content, // 默认沿用原始详情
StartTime: startTime, // 处理后的开始时间(新值或原始值)
EndTime: endTime, // 处理后的结束时间(新值或原始值)
Sort: original.Sort, // 默认沿用原始排序
}
// 6. 覆盖需要更新的字段(仅处理请求中提供的有效值)
if req.CourseId != 0 {
// 课程ID不为0时更新int转int64
updateData.CourseId = int64(req.CourseId)
}
if req.Title != "" {
// 标题非空时更新直接赋值string
updateData.Title = req.Title
}
if req.ActivityType >= 1 && req.ActivityType <= 4 {
// 活动类型在有效范围1-4时更新int转int64
updateData.ActivityType = int64(req.ActivityType)
}
// 详情字段无论是否为空均按请求值更新转为sql.NullString
updateData.Content = sql.NullString{String: req.Content, Valid: true}
if req.Sort >= 0 {
// 排序值非负时更新int转int64
updateData.Sort = int64(req.Sort)
}
// 7. 调用数据层执行更新
err = l.model.Update(l.ctx, updateData)
if err != nil {
return nil, fmt.Errorf("更新活动失败: %v", err)
}
// 8. 返回成功响应
return &types.UpdateCourseActivityResp{
Message: fmt.Sprintf("活动ID: %d更新成功", req.Id),
}, nil
}

View File

@@ -28,6 +28,12 @@ type (
FindOne(ctx context.Context, id int64) (*CourseActivity, error)
Update(ctx context.Context, data *CourseActivity) error
Delete(ctx context.Context, id int64) error
Count(ctx context.Context, whereClause string, args ...interface{}) (int, error)
FindAll(
ctx context.Context,
whereClause string,
args ...interface{}, // 可变参数作为最后一个参数,接收所有参数(筛选+分页)
) ([]*CourseActivity, error)
}
defaultCourseActivityModel struct {
@@ -86,6 +92,36 @@ func (m *defaultCourseActivityModel) Update(ctx context.Context, data *CourseAct
return err
}
// 数据层CourseActivityModel的Count方法统计符合条件的总条数
func (m *defaultCourseActivityModel) Count(ctx context.Context, whereClause string, args ...interface{}) (int, error) {
query := fmt.Sprintf("SELECT COUNT(*) FROM %s %s", m.table, whereClause)
var total int
err := m.conn.QueryRowCtx(ctx, &total, query, args...)
return total, err
}
// 数据层CourseActivityModel的FindAll方法查询符合条件的列表数据
func (m *defaultCourseActivityModel) FindAll(
ctx context.Context,
whereClause string,
args ...interface{}, // 可变参数作为最后一个参数,接收所有参数(筛选+分页)
) ([]*CourseActivity, error) {
// SQL中添加分页LIMIT ? OFFSET ?注意参数顺序与queryArgs一致
query := fmt.Sprintf(
"SELECT %s FROM %s %s ORDER BY sort DESC LIMIT ? OFFSET ?",
courseActivityRows, // 预定义的查询字段
m.table,
whereClause,
)
// 执行查询args包含所有参数...展开后是最后一个实参,符合语法)
var activities []*CourseActivity
err := m.conn.QueryRowsCtx(ctx, &activities, query, args...)
if err != nil {
return nil, err
}
return activities, nil
}
func (m *defaultCourseActivityModel) tableName() string {
return m.table
}