diff --git a/server/api/admin/activity/activity.go b/server/api/admin/activity/activity.go new file mode 100644 index 0000000..2ce4ac8 --- /dev/null +++ b/server/api/admin/activity/activity.go @@ -0,0 +1,67 @@ +// Package activity +// @Link https://github.com/bufanyun/hotgo +// @Copyright Copyright (c) 2025 HotGo CLI +// @Author Ms <133814250@qq.com> +// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE +// @AutoGenerate Version 2.17.8 +package activity + +import ( + "hotgo/internal/model/input/form" + "hotgo/internal/model/input/sysin" + + "github.com/gogf/gf/v2/frame/g" +) + +// ListReq 查询活动管理列表 +type ListReq struct { + g.Meta `path:"/activity/list" method:"get" tags:"活动管理" summary:"获取活动管理列表"` + sysin.ActivityListInp +} + +type ListRes struct { + form.PageRes + List []*sysin.ActivityListModel `json:"list" dc:"数据列表"` +} + +// ExportReq 导出活动管理列表 +type ExportReq struct { + g.Meta `path:"/activity/export" method:"get" tags:"活动管理" summary:"导出活动管理列表"` + sysin.ActivityListInp +} + +type ExportRes struct{} + +// ViewReq 获取活动管理指定信息 +type ViewReq struct { + g.Meta `path:"/activity/view" method:"get" tags:"活动管理" summary:"获取活动管理指定信息"` + sysin.ActivityViewInp +} + +type ViewRes struct { + *sysin.ActivityViewModel +} + +// EditReq 修改/新增活动管理 +type EditReq struct { + g.Meta `path:"/activity/edit" method:"post" tags:"活动管理" summary:"修改/新增活动管理"` + sysin.ActivityEditInp +} + +type EditRes struct{} + +// DeleteReq 删除活动管理 +type DeleteReq struct { + g.Meta `path:"/activity/delete" method:"post" tags:"活动管理" summary:"删除活动管理"` + sysin.ActivityDeleteInp +} + +type DeleteRes struct{} + +// StatusReq 更新活动管理状态 +type StatusReq struct { + g.Meta `path:"/activity/status" method:"post" tags:"活动管理" summary:"更新活动管理状态"` + sysin.ActivityStatusInp +} + +type StatusRes struct{} \ No newline at end of file diff --git a/server/api/api/activity/activity.go b/server/api/api/activity/activity.go new file mode 100644 index 0000000..32f100e --- /dev/null +++ b/server/api/api/activity/activity.go @@ -0,0 +1,16 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package activity + +import ( + "context" + + "hotgo/api/api/activity/v1" +) + +type IActivityV1 interface { + ActivityList(ctx context.Context, req *v1.ActivityListReq) (res *v1.ActivityListRes, err error) + ActivityDetail(ctx context.Context, req *v1.ActivityDetailReq) (res *v1.ActivityDetailRes, err error) +} diff --git a/server/api/api/activity/v1/activity.go b/server/api/api/activity/v1/activity.go new file mode 100644 index 0000000..083d581 --- /dev/null +++ b/server/api/api/activity/v1/activity.go @@ -0,0 +1,29 @@ +package v1 + +import ( + "hotgo/internal/model/entity" + + "github.com/gogf/gf/v2/frame/g" +) + +// 获取活动列表请求 +type ActivityListReq struct { + g.Meta `path:"/activity/list" method:"get" tags:"活动" summary:"获取活动列表"` +} + +// 获取活动列表响应 +type ActivityListRes struct { + List []*entity.Activity `json:"list" dc:"活动列表"` + Total int `json:"total" dc:"总数"` +} + +// 查看活动详情请求 +type ActivityDetailReq struct { + g.Meta `path:"/activity/detail" method:"get" tags:"活动" summary:"查看活动详情"` + Id int64 `json:"id" v:"required#活动ID必填" dc:"活动ID"` +} + +// 查看活动详情响应 +type ActivityDetailRes struct { + *entity.Activity `dc:"活动"` +} diff --git a/server/internal/controller/admin/sys/activity.go b/server/internal/controller/admin/sys/activity.go new file mode 100644 index 0000000..e753167 --- /dev/null +++ b/server/internal/controller/admin/sys/activity.go @@ -0,0 +1,73 @@ +// Package sys +// @Link https://github.com/bufanyun/hotgo +// @Copyright Copyright (c) 2025 HotGo CLI +// @Author Ms <133814250@qq.com> +// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE +// @AutoGenerate Version 2.17.8 +package sys + +import ( + "context" + "hotgo/api/admin/activity" + "hotgo/internal/model/input/sysin" + "hotgo/internal/service" +) + +var ( + Activity = cActivity{} +) + +type cActivity struct{} + +// List 查看活动管理列表 +func (c *cActivity) List(ctx context.Context, req *activity.ListReq) (res *activity.ListRes, err error) { + list, totalCount, err := service.SysActivity().List(ctx, &req.ActivityListInp) + if err != nil { + return + } + + if list == nil { + list = []*sysin.ActivityListModel{} + } + + res = new(activity.ListRes) + res.List = list + res.PageRes.Pack(req, totalCount) + return +} + +// Export 导出活动管理列表 +func (c *cActivity) Export(ctx context.Context, req *activity.ExportReq) (res *activity.ExportRes, err error) { + err = service.SysActivity().Export(ctx, &req.ActivityListInp) + return +} + +// Edit 更新活动管理 +func (c *cActivity) Edit(ctx context.Context, req *activity.EditReq) (res *activity.EditRes, err error) { + err = service.SysActivity().Edit(ctx, &req.ActivityEditInp) + return +} + +// View 获取指定活动管理信息 +func (c *cActivity) View(ctx context.Context, req *activity.ViewReq) (res *activity.ViewRes, err error) { + data, err := service.SysActivity().View(ctx, &req.ActivityViewInp) + if err != nil { + return + } + + res = new(activity.ViewRes) + res.ActivityViewModel = data + return +} + +// Delete 删除活动管理 +func (c *cActivity) Delete(ctx context.Context, req *activity.DeleteReq) (res *activity.DeleteRes, err error) { + err = service.SysActivity().Delete(ctx, &req.ActivityDeleteInp) + return +} + +// Status 更新活动管理状态 +func (c *cActivity) Status(ctx context.Context, req *activity.StatusReq) (res *activity.StatusRes, err error) { + err = service.SysActivity().Status(ctx, &req.ActivityStatusInp) + return +} \ No newline at end of file diff --git a/server/internal/controller/api/activity/activity.go b/server/internal/controller/api/activity/activity.go new file mode 100644 index 0000000..83449de --- /dev/null +++ b/server/internal/controller/api/activity/activity.go @@ -0,0 +1,5 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package activity diff --git a/server/internal/controller/api/activity/activity_new.go b/server/internal/controller/api/activity/activity_new.go new file mode 100644 index 0000000..29ea701 --- /dev/null +++ b/server/internal/controller/api/activity/activity_new.go @@ -0,0 +1,15 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package activity + +import ( + "hotgo/api/api/activity" +) + +type ControllerV1 struct{} + +func NewV1() activity.IActivityV1 { + return &ControllerV1{} +} diff --git a/server/internal/controller/api/activity/activity_v1_activity_detail.go b/server/internal/controller/api/activity/activity_v1_activity_detail.go new file mode 100644 index 0000000..f6a1e98 --- /dev/null +++ b/server/internal/controller/api/activity/activity_v1_activity_detail.go @@ -0,0 +1,28 @@ +package activity + +import ( + "context" + + "hotgo/internal/dao" + "hotgo/internal/model/entity" + + "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/errors/gerror" + + v1 "hotgo/api/api/activity/v1" +) + +func (c *ControllerV1) ActivityDetail(ctx context.Context, req *v1.ActivityDetailReq) (res *v1.ActivityDetailRes, err error) { + activity := new(entity.Activity) + err = dao.Activity.Ctx(ctx).Where("id = ?", req.Id).Scan(activity) + if err != nil { + return nil, gerror.NewCode(gcode.CodeDbOperationError, "数据库错误") + } + if activity.Id == 0 { + return nil, gerror.NewCode(gcode.CodeNotFound, "活动不存在") + } + res = &v1.ActivityDetailRes{ + Activity: activity, + } + return +} diff --git a/server/internal/controller/api/activity/activity_v1_activity_list.go b/server/internal/controller/api/activity/activity_v1_activity_list.go new file mode 100644 index 0000000..e5fa48f --- /dev/null +++ b/server/internal/controller/api/activity/activity_v1_activity_list.go @@ -0,0 +1,34 @@ +package activity + +import ( + "context" + + "hotgo/internal/dao" + "hotgo/internal/model/entity" + + "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/errors/gerror" + + v1 "hotgo/api/api/activity/v1" +) + +func (c *ControllerV1) ActivityList(ctx context.Context, req *v1.ActivityListReq) (res *v1.ActivityListRes, err error) { + // 查询活动列表 + var list []*entity.Activity + err = dao.Activity.Ctx(ctx).Scan(&list) + if err != nil { + return nil, gerror.NewCode(gcode.CodeDbOperationError, "数据库错误") + } + + // 统计总数 + total, err := dao.Activity.Ctx(ctx).Count() + if err != nil { + return nil, gerror.NewCode(gcode.CodeDbOperationError, "统计总数失败") + } + + res = &v1.ActivityListRes{ + List: list, + Total: total, + } + return +} diff --git a/server/internal/dao/internal/activity.go b/server/internal/dao/internal/activity.go index 36c775e..ca6bcc2 100755 --- a/server/internal/dao/internal/activity.go +++ b/server/internal/dao/internal/activity.go @@ -25,10 +25,14 @@ type ActivityColumns struct { Title string // 活动标题 Introduction string // 活动介绍 Cover string // 活动封面图 + Imgs string // 说明图片 + Banner string // 活动头图 Video string // 活动视频 StartTime string // 活动开始时间 EndTime string // 活动结束时间 - CategoryId string // 分类id + Extra string // 扩展字段 + Attachment string // 活动附件 + Status string // 活动状态 Revision string // 乐观锁 CreatedBy string // 创建人 CreatedTime string // 创建时间 @@ -42,10 +46,14 @@ var activityColumns = ActivityColumns{ Title: "title", Introduction: "introduction", Cover: "cover", + Imgs: "imgs", + Banner: "banner", Video: "video", StartTime: "start_time", EndTime: "end_time", - CategoryId: "category_id", + Extra: "extra", + Attachment: "attachment", + Status: "status", Revision: "revision", CreatedBy: "created_by", CreatedTime: "created_time", diff --git a/server/internal/logic/middleware/api_auth.go b/server/internal/logic/middleware/api_auth.go index e217443..78fcc1d 100644 --- a/server/internal/logic/middleware/api_auth.go +++ b/server/internal/logic/middleware/api_auth.go @@ -6,12 +6,13 @@ package middleware import ( - "github.com/gogf/gf/v2/errors/gcode" - "github.com/gogf/gf/v2/net/ghttp" - "github.com/gogf/gf/v2/text/gstr" "hotgo/internal/consts" "hotgo/internal/library/response" "hotgo/utility/simple" + + "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/text/gstr" ) // ApiAuth API鉴权中间件 diff --git a/server/internal/logic/sys/activity.go b/server/internal/logic/sys/activity.go new file mode 100644 index 0000000..9aaf847 --- /dev/null +++ b/server/internal/logic/sys/activity.go @@ -0,0 +1,156 @@ +// Package sys +// @Link https://github.com/bufanyun/hotgo +// @Copyright Copyright (c) 2025 HotGo CLI +// @Author Ms <133814250@qq.com> +// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE +// @AutoGenerate Version 2.17.8 +package sys + +import ( + "context" + "fmt" + "hotgo/internal/dao" + "hotgo/internal/library/contexts" + "hotgo/internal/library/hgorm/handler" + "hotgo/internal/model/input/form" + "hotgo/internal/model/input/sysin" + "hotgo/internal/service" + "hotgo/utility/convert" + "hotgo/utility/excel" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gctx" + "github.com/gogf/gf/v2/util/gconv" +) + +type sSysActivity struct{} + +func NewSysActivity() *sSysActivity { + return &sSysActivity{} +} + +func init() { + service.RegisterSysActivity(NewSysActivity()) +} + +// Model 活动管理ORM模型 +func (s *sSysActivity) Model(ctx context.Context, option ...*handler.Option) *gdb.Model { + return handler.Model(dao.Activity.Ctx(ctx), option...) +} + +// List 获取活动管理列表 +func (s *sSysActivity) List(ctx context.Context, in *sysin.ActivityListInp) (list []*sysin.ActivityListModel, totalCount int, err error) { + mod := s.Model(ctx) + + // 字段过滤 + mod = mod.Fields(sysin.ActivityListModel{}) + + // 查询id + if in.Id > 0 { + mod = mod.Where(dao.Activity.Columns().Id, in.Id) + } + + // 查询活动状态 + if in.Status > 0 { + mod = mod.Where(dao.Activity.Columns().Status, in.Status) + } + + // 分页 + mod = mod.Page(in.Page, in.PerPage) + + // 排序 + mod = mod.OrderDesc(dao.Activity.Columns().Id) + + // 查询数据 + if err = mod.ScanAndCount(&list, &totalCount, false); err != nil { + err = gerror.Wrap(err, "获取活动管理列表失败,请稍后重试!") + return + } + return +} + +// Export 导出活动管理 +func (s *sSysActivity) Export(ctx context.Context, in *sysin.ActivityListInp) (err error) { + list, totalCount, err := s.List(ctx, in) + if err != nil { + return + } + + // 字段的排序是依据tags的字段顺序,如果你不想使用默认的排序方式,可以直接定义 tags = []string{"字段名称", "字段名称2", ...} + tags, err := convert.GetEntityDescTags(sysin.ActivityExportModel{}) + if err != nil { + return + } + + var ( + fileName = "导出活动管理-" + gctx.CtxId(ctx) + sheetName = fmt.Sprintf("索引条件共%v行,共%v页,当前导出是第%v页,本页共%v行", totalCount, form.CalPageCount(totalCount, in.PerPage), in.Page, len(list)) + exports []sysin.ActivityExportModel + ) + + if err = gconv.Scan(list, &exports); err != nil { + return + } + + err = excel.ExportByStructs(ctx, tags, exports, fileName, sheetName) + return +} + +// Edit 修改/新增活动管理 +func (s *sSysActivity) Edit(ctx context.Context, in *sysin.ActivityEditInp) (err error) { + return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) { + + // 修改 + if in.Id > 0 { + in.UpdatedBy = contexts.GetUserId(ctx) + if _, err = s.Model(ctx). + Fields(sysin.ActivityUpdateFields{}). + WherePri(in.Id).Data(in).Update(); err != nil { + err = gerror.Wrap(err, "修改活动管理失败,请稍后重试!") + } + return + } + + // 新增 + in.CreatedBy = contexts.GetUserId(ctx) + if _, err = s.Model(ctx, &handler.Option{FilterAuth: false}). + Fields(sysin.ActivityInsertFields{}). + Data(in).OmitEmptyData().Insert(); err != nil { + err = gerror.Wrap(err, "新增活动管理失败,请稍后重试!") + } + return + }) +} + +// Delete 删除活动管理 +func (s *sSysActivity) Delete(ctx context.Context, in *sysin.ActivityDeleteInp) (err error) { + + if _, err = s.Model(ctx).WherePri(in.Id).Unscoped().Delete(); err != nil { + err = gerror.Wrap(err, "删除活动管理失败,请稍后重试!") + return + } + return +} + +// View 获取活动管理指定信息 +func (s *sSysActivity) View(ctx context.Context, in *sysin.ActivityViewInp) (res *sysin.ActivityViewModel, err error) { + if err = s.Model(ctx).WherePri(in.Id).Scan(&res); err != nil { + err = gerror.Wrap(err, "获取活动管理信息,请稍后重试!") + return + } + return +} + +// Status 更新活动管理状态 +func (s *sSysActivity) Status(ctx context.Context, in *sysin.ActivityStatusInp) (err error) { + if _, err = s.Model(ctx).WherePri(in.Id).Data(g.Map{ + dao.Activity.Columns().Status: in.Status, + dao.Activity.Columns().UpdatedBy: contexts.GetUserId(ctx), + }).Update(); err != nil { + err = gerror.Wrap(err, "更新活动管理状态失败,请稍后重试!") + return + } + return +} \ No newline at end of file diff --git a/server/internal/model/do/activity.go b/server/internal/model/do/activity.go index c734af1..89cf98e 100755 --- a/server/internal/model/do/activity.go +++ b/server/internal/model/do/activity.go @@ -16,10 +16,14 @@ type Activity struct { Title interface{} // 活动标题 Introduction interface{} // 活动介绍 Cover interface{} // 活动封面图 + Imgs interface{} // 说明图片 + Banner interface{} // 活动头图 Video interface{} // 活动视频 - StartTime interface{} // 活动开始时间 - EndTime interface{} // 活动结束时间 - CategoryId interface{} // 分类id + StartTime *gtime.Time // 活动开始时间 + EndTime *gtime.Time // 活动结束时间 + Extra interface{} // 扩展字段 + Attachment interface{} // 活动附件 + Status interface{} // 活动状态 Revision interface{} // 乐观锁 CreatedBy interface{} // 创建人 CreatedTime *gtime.Time // 创建时间 diff --git a/server/internal/model/entity/activity.go b/server/internal/model/entity/activity.go index 018f0e3..292f2bb 100755 --- a/server/internal/model/entity/activity.go +++ b/server/internal/model/entity/activity.go @@ -10,17 +10,21 @@ import ( // Activity is the golang structure for table activity. type Activity struct { - Id int `json:"id" orm:"id" description:"id"` + Id int64 `json:"id" orm:"id" description:"id"` Title string `json:"title" orm:"title" description:"活动标题"` Introduction string `json:"introduction" orm:"introduction" description:"活动介绍"` Cover string `json:"cover" orm:"cover" description:"活动封面图"` + Imgs string `json:"imgs" orm:"imgs" description:"说明图片"` + Banner string `json:"banner" orm:"banner" description:"活动头图"` Video string `json:"video" orm:"video" description:"活动视频"` - StartTime string `json:"startTime" orm:"start_time" description:"活动开始时间"` - EndTime string `json:"endTime" orm:"end_time" description:"活动结束时间"` - CategoryId int `json:"categoryId" orm:"category_id" description:"分类id"` + StartTime *gtime.Time `json:"startTime" orm:"start_time" description:"活动开始时间"` + EndTime *gtime.Time `json:"endTime" orm:"end_time" description:"活动结束时间"` + Extra string `json:"extra" orm:"extra" description:"扩展字段"` + Attachment string `json:"attachment" orm:"attachment" description:"活动附件"` + Status int `json:"status" orm:"status" description:"活动状态"` Revision int `json:"revision" orm:"revision" description:"乐观锁"` - CreatedBy int `json:"createdBy" orm:"created_by" description:"创建人"` + CreatedBy int64 `json:"createdBy" orm:"created_by" description:"创建人"` CreatedTime *gtime.Time `json:"createdTime" orm:"created_time" description:"创建时间"` - UpdatedBy int `json:"updatedBy" orm:"updated_by" description:"更新人"` + UpdatedBy int64 `json:"updatedBy" orm:"updated_by" description:"更新人"` UpdatedTime *gtime.Time `json:"updatedTime" orm:"updated_time" description:"更新时间"` } diff --git a/server/internal/model/input/sysin/activity.go b/server/internal/model/input/sysin/activity.go new file mode 100644 index 0000000..57f0053 --- /dev/null +++ b/server/internal/model/input/sysin/activity.go @@ -0,0 +1,143 @@ +// Package sysin +// @Link https://github.com/bufanyun/hotgo +// @Copyright Copyright (c) 2025 HotGo CLI +// @Author Ms <133814250@qq.com> +// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE +// @AutoGenerate Version 2.17.8 +package sysin + +import ( + "context" + "hotgo/internal/consts" + "hotgo/internal/model/entity" + "hotgo/internal/model/input/form" + "hotgo/utility/validate" + + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/os/gtime" +) + +// ActivityUpdateFields 修改活动管理字段过滤 +type ActivityUpdateFields struct { + Title string `json:"title" dc:"活动标题"` + Introduction string `json:"introduction" dc:"活动介绍"` + Cover string `json:"cover" dc:"活动封面图"` + Imgs string `json:"imgs" dc:"说明图片"` + Banner string `json:"banner" dc:"活动头图"` + Video string `json:"video" dc:"活动视频"` + StartTime *gtime.Time `json:"startTime" dc:"活动开始时间"` + EndTime *gtime.Time `json:"endTime" dc:"活动结束时间"` + Attachment string `json:"attachment" dc:"活动附件"` + Status int `json:"status" dc:"活动状态"` + UpdatedBy int64 `json:"updatedBy" dc:"更新人"` +} + +// ActivityInsertFields 新增活动管理字段过滤 +type ActivityInsertFields struct { + Title string `json:"title" dc:"活动标题"` + Introduction string `json:"introduction" dc:"活动介绍"` + Cover string `json:"cover" dc:"活动封面图"` + Imgs string `json:"imgs" dc:"说明图片"` + Banner string `json:"banner" dc:"活动头图"` + Video string `json:"video" dc:"活动视频"` + StartTime *gtime.Time `json:"startTime" dc:"活动开始时间"` + EndTime *gtime.Time `json:"endTime" dc:"活动结束时间"` + Attachment string `json:"attachment" dc:"活动附件"` + Status int `json:"status" dc:"活动状态"` + CreatedBy int64 `json:"createdBy" dc:"创建人"` +} + +// ActivityEditInp 修改/新增活动管理 +type ActivityEditInp struct { + entity.Activity +} + +func (in *ActivityEditInp) Filter(ctx context.Context) (err error) { + + return +} + +type ActivityEditModel struct{} + +// ActivityDeleteInp 删除活动管理 +type ActivityDeleteInp struct { + Id interface{} `json:"id" v:"required#id不能为空" dc:"id"` +} + +func (in *ActivityDeleteInp) Filter(ctx context.Context) (err error) { + return +} + +type ActivityDeleteModel struct{} + +// ActivityViewInp 获取指定活动管理信息 +type ActivityViewInp struct { + Id int `json:"id" v:"required#id不能为空" dc:"id"` +} + +func (in *ActivityViewInp) Filter(ctx context.Context) (err error) { + return +} + +type ActivityViewModel struct { + entity.Activity +} + +// ActivityListInp 获取活动管理列表 +type ActivityListInp struct { + form.PageReq + Id int `json:"id" dc:"id"` + Status int `json:"status" dc:"活动状态"` +} + +func (in *ActivityListInp) Filter(ctx context.Context) (err error) { + return +} + +type ActivityListModel struct { + Id int `json:"id" dc:"id"` + Title string `json:"title" dc:"活动标题"` + Cover string `json:"cover" dc:"活动封面图"` + Banner string `json:"banner" dc:"活动头图"` + StartTime *gtime.Time `json:"startTime" dc:"活动开始时间"` + EndTime *gtime.Time `json:"endTime" dc:"活动结束时间"` + Status int `json:"status" dc:"活动状态"` +} + +// ActivityExportModel 导出活动管理 +type ActivityExportModel struct { + Id int `json:"id" dc:"id"` + Title string `json:"title" dc:"活动标题"` + Cover string `json:"cover" dc:"活动封面图"` + Banner string `json:"banner" dc:"活动头图"` + Video string `json:"video" dc:"活动视频"` + StartTime *gtime.Time `json:"startTime" dc:"活动开始时间"` + EndTime *gtime.Time `json:"endTime" dc:"活动结束时间"` + Status int `json:"status" dc:"活动状态"` +} + +// ActivityStatusInp 更新活动管理状态 +type ActivityStatusInp struct { + Id int `json:"id" v:"required#id不能为空" dc:"id"` + Status int `json:"status" dc:"状态"` +} + +func (in *ActivityStatusInp) Filter(ctx context.Context) (err error) { + if in.Id <= 0 { + err = gerror.New("id不能为空") + return + } + + if in.Status <= 0 { + err = gerror.New("状态不能为空") + return + } + + if !validate.InSlice(consts.StatusSlice, in.Status) { + err = gerror.New("状态不正确") + return + } + return +} + +type ActivityStatusModel struct{} \ No newline at end of file diff --git a/server/internal/router/api.go b/server/internal/router/api.go index 6f5ed8b..535ccbe 100644 --- a/server/internal/router/api.go +++ b/server/internal/router/api.go @@ -8,6 +8,7 @@ package router import ( "context" "hotgo/internal/consts" + "hotgo/internal/controller/api/activity" "hotgo/internal/controller/api/lesson" "hotgo/internal/controller/api/member" "hotgo/internal/controller/api/mycourse" @@ -34,8 +35,9 @@ func Api(ctx context.Context, group *ghttp.RouterGroup) { group.Group(simple.RouterPrefix(ctx, consts.AppApi), func(group *ghttp.RouterGroup) { group.Bind( - users.NewV1(), // 前台用户 - lesson.NewV1(), // 课程 + users.NewV1(), // 前台用户 + lesson.NewV1(), // 课程 + activity.NewV1(), // 活动 ) }) } diff --git a/server/internal/router/genrouter/activity.go b/server/internal/router/genrouter/activity.go new file mode 100644 index 0000000..f560c1b --- /dev/null +++ b/server/internal/router/genrouter/activity.go @@ -0,0 +1,13 @@ +// Package genrouter +// @Link https://github.com/bufanyun/hotgo +// @Copyright Copyright (c) 2025 HotGo CLI +// @Author Ms <133814250@qq.com> +// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE +// @AutoGenerate Version 2.17.8 +package genrouter + +import "hotgo/internal/controller/admin/sys" + +func init() { + LoginRequiredRouter = append(LoginRequiredRouter, sys.Activity) // 活动管理 +} \ No newline at end of file diff --git a/server/internal/service/sys.go b/server/internal/service/sys.go index 1b85f93..e8fac07 100644 --- a/server/internal/service/sys.go +++ b/server/internal/service/sys.go @@ -20,6 +20,22 @@ import ( ) type ( + ISysActivity interface { + // Model 活动管理ORM模型 + Model(ctx context.Context, option ...*handler.Option) *gdb.Model + // List 获取活动管理列表 + List(ctx context.Context, in *sysin.ActivityListInp) (list []*sysin.ActivityListModel, totalCount int, err error) + // Export 导出活动管理 + Export(ctx context.Context, in *sysin.ActivityListInp) (err error) + // Edit 修改/新增活动管理 + Edit(ctx context.Context, in *sysin.ActivityEditInp) (err error) + // Delete 删除活动管理 + Delete(ctx context.Context, in *sysin.ActivityDeleteInp) (err error) + // View 获取活动管理指定信息 + View(ctx context.Context, in *sysin.ActivityViewInp) (res *sysin.ActivityViewModel, err error) + // Status 更新活动管理状态 + Status(ctx context.Context, in *sysin.ActivityStatusInp) (err error) + } ISysAddons interface { // List 获取列表 List(ctx context.Context, in *sysin.AddonsListInp) (list []*sysin.AddonsListModel, totalCount int, err error) @@ -468,6 +484,7 @@ type ( ) var ( + localSysActivity ISysActivity localSysAddons ISysAddons localSysAddonsConfig ISysAddonsConfig localSysAttachment ISysAttachment @@ -495,6 +512,17 @@ var ( localSysUsers ISysUsers ) +func SysActivity() ISysActivity { + if localSysActivity == nil { + panic("implement not found for interface ISysActivity, forgot register?") + } + return localSysActivity +} + +func RegisterSysActivity(i ISysActivity) { + localSysActivity = i +} + func SysAddons() ISysAddons { if localSysAddons == nil { panic("implement not found for interface ISysAddons, forgot register?") diff --git a/server/storage/data/generate/activity_menu.sql b/server/storage/data/generate/activity_menu.sql new file mode 100644 index 0000000..0df8bc4 --- /dev/null +++ b/server/storage/data/generate/activity_menu.sql @@ -0,0 +1,65 @@ +-- hotgo自动生成菜单权限SQL 通常情况下只在首次生成代码时自动执行一次 +-- 如需再次执行请先手动删除生成的菜单权限和SQL文件:/Users/guochen/Documents/projects/g031/hotgo/server/storage/data/generate/activity_menu.sql +-- Version: 2.17.8 +-- Date: 2025-07-28 21:16:53 +-- Link https://github.com/bufanyun/hotgo + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +SET AUTOCOMMIT = 0; +START TRANSACTION; + +-- +-- 数据库: `hotgo` +-- + +-- -------------------------------------------------------- + +-- +-- 插入表中的数据 `hg_admin_menu` +-- + + +SET @now := now(); + + +-- 菜单目录 +INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, '0', '活动管理', 'activity', '/activity', 'MenuOutlined', '1', '/activity/index', '', '', 'LAYOUT', '1', '', '0', '0', '', '0', '0', '0', '1', '', '0', '', '1', @now, @now); + + +SET @dirId = LAST_INSERT_ID(); + + +-- 菜单页面 +-- 列表 +INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @dirId, '活动管理列表', 'activityIndex', 'index', '', '2', '', '/activity/list', '', '/activity/index', '1', 'activity', '0', '0', '', '0', '1', '0', '2', CONCAT('tr_', @dirId,' '), '10', '', '1', @now, @now); + + +SET @listId = LAST_INSERT_ID(); + +-- 详情 +INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '活动管理详情', 'activityView', '', '', '3', '', '/activity/view', '', '', '1', '', '0', '0', '', '0', '1', '0', '3', CONCAT('tr_', @dirId, ' tr_', @listId,' '), '10', '', '1', @now, @now); + + +-- 菜单按钮 + +-- 编辑 +INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '编辑/新增活动管理', 'activityEdit', '', '', '3', '', '/activity/edit', '', '', '1', '', '0', '0', '', '0', '1', '0', '3', CONCAT('tr_', @dirId, ' tr_', @listId,' '), '20', '', '1', @now, @now); + + +SET @editId = LAST_INSERT_ID(); + + +-- 删除 +INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '删除活动管理', 'activityDelete', '', '', '3', '', '/activity/delete', '', '', '1', '', '0', '0', '', '0', '0', '0', '3', CONCAT('tr_', @dirId, ' tr_', @listId,' '), '40', '', '1', @now, @now); + + +-- 更新状态 +INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '修改活动管理状态', 'activityStatus', '', '', '3', '', '/activity/status', '', '', '1', '', '0', '0', '', '0', '0', '0', '3', CONCAT('tr_', @dirId, ' tr_', @listId,' '), '50', '', '1', @now, @now); + + + +-- 导出 +INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '导出活动管理', 'activityExport', '', '', '3', '', '/activity/export', '', '', '1', '', '0', '0', '', '0', '0', '0', '3', CONCAT('tr_', @dirId, ' tr_', @listId,' '), '70', '', '1', @now, @now); + + +COMMIT; \ No newline at end of file diff --git a/web/src/api/activity/index.ts b/web/src/api/activity/index.ts new file mode 100644 index 0000000..64954d0 --- /dev/null +++ b/web/src/api/activity/index.ts @@ -0,0 +1,51 @@ +import { http, jumpExport } from '@/utils/http/axios'; + +// 获取活动管理列表 +export function List(params) { + return http.request({ + url: '/activity/list', + method: 'get', + params, + }); +} + +// 删除/批量删除活动管理 +export function Delete(params) { + return http.request({ + url: '/activity/delete', + method: 'POST', + params, + }); +} + +// 添加/编辑活动管理 +export function Edit(params) { + return http.request({ + url: '/activity/edit', + method: 'POST', + params, + }); +} + +// 修改活动管理状态 +export function Status(params) { + return http.request({ + url: '/activity/status', + method: 'POST', + params, + }); +} + +// 获取活动管理指定详情 +export function View(params) { + return http.request({ + url: '/activity/view', + method: 'GET', + params, + }); +} + +// 导出活动管理 +export function Export(params) { + jumpExport('/activity/export', params); +} \ No newline at end of file diff --git a/web/src/views/activity/edit.vue b/web/src/views/activity/edit.vue new file mode 100644 index 0000000..de938f6 --- /dev/null +++ b/web/src/views/activity/edit.vue @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 取消 + + + 确定 + + + + + + + + + + \ No newline at end of file diff --git a/web/src/views/activity/index.vue b/web/src/views/activity/index.vue new file mode 100644 index 0000000..f2c4830 --- /dev/null +++ b/web/src/views/activity/index.vue @@ -0,0 +1,225 @@ + + + + + + + + + + + + + + + + + + + + + + 添加 + + + + + + + + 批量删除 + + + + + + + + 导出 + + + + + + + + + + + + \ No newline at end of file diff --git a/web/src/views/activity/model.ts b/web/src/views/activity/model.ts new file mode 100644 index 0000000..49ff687 --- /dev/null +++ b/web/src/views/activity/model.ts @@ -0,0 +1,133 @@ +import { h, ref } from 'vue'; +import { cloneDeep } from 'lodash-es'; +import { FormSchema } from '@/components/Form'; +import { renderImage, renderOptionTag } from '@/utils'; +import { useDictStore } from '@/store/modules/dict'; + +const dict = useDictStore(); + +export class State { + public id = 0; // id + public title = ''; // 活动标题 + public introduction = ''; // 活动介绍 + public cover = ''; // 活动封面图 + public imgs = ''; // 说明图片 + public banner = ''; // 活动头图 + public video = ''; // 活动视频 + public startTime = ''; // 活动开始时间 + public endTime = ''; // 活动结束时间 + public extra = ''; // 扩展字段 + public attachment = ''; // 活动附件 + public status = 1; // 活动状态 + public revision = 0; // 乐观锁 + public createdBy = 0; // 创建人 + public createdTime = ''; // 创建时间 + public updatedBy = 0; // 更新人 + public updatedTime = ''; // 更新时间 + + constructor(state?: Partial) { + if (state) { + Object.assign(this, state); + } + } +} + +export function newState(state: State | Record | null): State { + if (state !== null) { + if (state instanceof State) { + return cloneDeep(state); + } + return new State(state); + } + return new State(); +} + +// 表单验证规则 + +// 表格搜索表单 +export const schemas = ref([ + { + field: 'id', + component: 'NInputNumber', + label: 'id', + componentProps: { + placeholder: '请输入id', + onUpdateValue: (e: any) => { + console.log(e); + }, + }, + }, + { + field: 'status', + component: 'NSelect', + label: '活动状态', + defaultValue: null, + componentProps: { + placeholder: '请选择活动状态', + options: dict.getOption('sys_normal_disable'), + onUpdateValue: (e: any) => { + console.log(e); + }, + }, + }, +]); + +// 表格列 +export const columns = [ + { + title: 'id', + key: 'id', + align: 'left', + width: -1, + }, + { + title: '活动标题', + key: 'title', + align: 'left', + width: -1, + }, + { + title: '活动封面图', + key: 'cover', + align: 'left', + width: -1, + render(row: State) { + return renderImage(row.cover); + }, + }, + { + title: '活动头图', + key: 'banner', + align: 'left', + width: -1, + render(row: State) { + return renderImage(row.banner); + }, + }, + { + title: '活动开始时间', + key: 'startTime', + align: 'left', + width: -1, + }, + { + title: '活动结束时间', + key: 'endTime', + align: 'left', + width: -1, + }, + { + title: '活动状态', + key: 'status', + align: 'left', + width: -1, + render(row: State) { + return renderOptionTag('sys_normal_disable', row.status); + }, + }, +]; + +// 加载字典数据选项 +export function loadOptions() { + dict.loadOptions(['sys_normal_disable']); +} \ No newline at end of file diff --git a/web/src/views/activity/view.vue b/web/src/views/activity/view.vue new file mode 100644 index 0000000..69502cb --- /dev/null +++ b/web/src/views/activity/view.vue @@ -0,0 +1,155 @@ + + + + + + + + + 活动标题 + + {{ formValue.title }} + + + + 活动介绍 + + + + + + 活动封面图 + + + + + + 说明图片 + + + + + + + + + + + + 活动头图 + + + + + + 活动视频 + + + + + + + {{ getFileExt(formValue.video) }} + + + + + + + + + 活动开始时间 + + {{ formValue.startTime }} + + + + 活动结束时间 + + {{ formValue.endTime }} + + + + 活动附件 + + + + + + + + {{ + getFileExt(item) + }} + + + + + + + + + + {{ dict.getLabel('sys_normal_disable', formValue.status) }} + + + + + + + + + + + + \ No newline at end of file