From 4295d0ff7f9c04763511683c5621e2b4cc41fe0f Mon Sep 17 00:00:00 2001 From: xh <11675084@qq.com> Date: Sun, 21 Dec 2025 18:18:26 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A8=A1=E7=89=88=E4=BC=98=E5=8C=96=EF=BC=8C?= =?UTF-8?q?=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/src/api/system/corn.ts | 81 ++++++ admin/src/views/monitor/error/index.vue | 4 +- admin/src/views/system/corn/details.vue | 130 +++++++++ admin/src/views/system/corn/edit.vue | 142 ++++++++++ admin/src/views/system/corn/index.vue | 227 +++++++++++++++ .../monitorController/monitor_client_ctl.go | 10 +- .../controller/admin_ctl/system_corn_ctl.go | 232 +++++++++++++++ server/app/corn/init.go | 67 +++++ server/app/schema/system_corn_schema.go | 59 ++++ .../templates/gocode/controller.go.tpl | 8 +- .../tpl_utils/templates/gocode/route.go.tpl | 20 +- .../tpl_utils/templates/gocode/service.go.tpl | 23 +- .../service/generatorService/tpl_utils/tpl.go | 35 +-- .../generatorService/tpl_utils/utils.go | 4 + .../monitorService/monitor_client_service.go | 12 +- .../app/service/systemService/permService.go | 2 +- server/app/service/system_corn_service.go | 263 ++++++++++++++++++ server/core/corn.go | 41 ++- server/model/monitor_client.go | 2 +- server/model/system_corn.go | 30 ++ server/routes/adminRoute/system_corn_route.go | 52 ++++ server/util/tools.go | 3 +- 22 files changed, 1387 insertions(+), 60 deletions(-) create mode 100644 admin/src/api/system/corn.ts create mode 100644 admin/src/views/system/corn/details.vue create mode 100644 admin/src/views/system/corn/edit.vue create mode 100644 admin/src/views/system/corn/index.vue create mode 100644 server/app/controller/admin_ctl/system_corn_ctl.go create mode 100644 server/app/schema/system_corn_schema.go create mode 100644 server/app/service/system_corn_service.go create mode 100644 server/model/system_corn.go create mode 100644 server/routes/adminRoute/system_corn_route.go diff --git a/admin/src/api/system/corn.ts b/admin/src/api/system/corn.ts new file mode 100644 index 0000000..380123d --- /dev/null +++ b/admin/src/api/system/corn.ts @@ -0,0 +1,81 @@ +import request from '@/utils/request' +import type { Pages } from '@/utils/request' + +import config from '@/config' +import queryString from 'query-string' +import { getToken } from '@/utils/auth' +import { clearEmpty } from '@/utils/util' + +export type type_system_corn = { + Id?: string + TaskName?: string + TaskCode?: string + CornExpr?: string + Disabled?: number + CreatedBy?: string + IsDelete?: number + CreateTime?: string + UpdateTime?: string + DeleteTime?: string +} +// 查询 +export type type_system_corn_query = { + TaskName?: string + TaskCode?: string + CornExpr?: string + Disabled?: number + CreatedBy?: string + CreateTimeStart?: string + CreateTimeEnd?: string + UpdateTimeStart?: string + UpdateTimeEnd?: string +} +// 添加编辑 +export type type_system_corn_edit = { + Id?: string + TaskName?: string + TaskCode?: string + CornExpr?: string + Disabled?: number +} + +// 定时任务列表 +export function system_corn_list(params?: type_system_corn_query) { + return request.get>({ url: '/system_corn/list', params: clearEmpty(params) }) +} +// 定时任务列表-所有 +export function system_corn_list_all(params?: type_system_corn_query) { + return request.get({ url: '/system_corn/listAll', params: clearEmpty(params) }) +} + +// 定时任务详情 +export function system_corn_detail(Id: number | string) { + return request.get({ url: '/system_corn/detail', params: { Id } }) +} + +// 定时任务新增 +export function system_corn_add(data: type_system_corn_edit) { + return request.post({ url: '/system_corn/add', data }) +} + +// 定时任务编辑 +export function system_corn_edit(data: type_system_corn_edit) { + return request.post({ url: '/system_corn/edit', data }) +} + +// 定时任务删除 +export function system_corn_delete(Id: number | string) { + return request.post({ url: '/system_corn/del', data: { Id } }) +} +// 定时任务删除-批量 +export function system_corn_delete_batch(data: { Ids: string }) { + return request.post({ url: '/system_corn/delBatch', data }) +} + +// 定时任务导入 +export const system_corn_import_file = '/system_corn/ImportFile' + +// 定时任务导出 +export function system_corn_export_file(params: any) { + return (window.location.href =`${config.baseUrl}${config.urlPrefix}/system_corn/ExportFile?token=${getToken()}&` + queryString.stringify(clearEmpty(params))) +} diff --git a/admin/src/views/monitor/error/index.vue b/admin/src/views/monitor/error/index.vue index f7e57fa..a8e7927 100644 --- a/admin/src/views/monitor/error/index.vue +++ b/admin/src/views/monitor/error/index.vue @@ -24,9 +24,9 @@ /> - + +
+ + + + + + + + + + + + + + + + + +
+ + + \ No newline at end of file diff --git a/admin/src/views/system/corn/edit.vue b/admin/src/views/system/corn/edit.vue new file mode 100644 index 0000000..80f076c --- /dev/null +++ b/admin/src/views/system/corn/edit.vue @@ -0,0 +1,142 @@ + + diff --git a/admin/src/views/system/corn/index.vue b/admin/src/views/system/corn/index.vue new file mode 100644 index 0000000..c14a34a --- /dev/null +++ b/admin/src/views/system/corn/index.vue @@ -0,0 +1,227 @@ + + diff --git a/server/app/controller/admin_ctl/monitorController/monitor_client_ctl.go b/server/app/controller/admin_ctl/monitorController/monitor_client_ctl.go index 219f715..05c0dcf 100644 --- a/server/app/controller/admin_ctl/monitorController/monitor_client_ctl.go +++ b/server/app/controller/admin_ctl/monitorController/monitor_client_ctl.go @@ -146,12 +146,12 @@ func (hd *MonitorClientHandler) Add(c *gin.Context) { var addReq monitorSchema.MonitorClientAddReq json.Unmarshal([]byte(data), &addReq) - _, err = monitorService.MonitorClientService.DetailByClientId(*addReq.ClientId) + // _, err = monitorService.MonitorClientService.DetailByClientId(*addReq.ClientId) - if err != nil { - response.FailWithMsg(c, response.SystemError, err.Error()) - return - } + // if err != nil { + // response.FailWithMsg(c, response.SystemError, err.Error()) + // return + // } uaStr := c.GetHeader("user-agent") if uaStr != "" { ua := util.UAParser.Parse(uaStr) diff --git a/server/app/controller/admin_ctl/system_corn_ctl.go b/server/app/controller/admin_ctl/system_corn_ctl.go new file mode 100644 index 0000000..4316f34 --- /dev/null +++ b/server/app/controller/admin_ctl/system_corn_ctl.go @@ -0,0 +1,232 @@ +package admin_ctl + +import ( + "fmt" + "net/http" + "strings" + "time" + "x_admin/app/schema" + "x_admin/app/service" + "x_admin/config" + "x_admin/core/request" + "x_admin/core/response" + "x_admin/util" + "x_admin/util/excel2" + + "github.com/gin-gonic/gin" + "golang.org/x/sync/singleflight" +) + +type SystemCornHandler struct { + requestGroup singleflight.Group +} + +// @Summary 定时任务列表 +// @Tags system_corn-定时任务 +// @Produce json +// @Param token header string true "token" +// @Param pageNo query int true "页码" +// @Param pageSize query int true "每页数量" +// @Param TaskName query string false "任务名称" +// @Param TaskCode query string false "任务编码" +// @Param CornExpr query string false "corn表达式" +// @Param Disabled query number false "禁用" +// @Param CreatedBy query string false "创建人" +// @Param CreateTimeStart query string false "创建时间" +// @Param CreateTimeEnd query string false "创建时间" +// @Param UpdateTimeStart query string false "更新时间" +// @Param UpdateTimeEnd query string false "更新时间" +// +// @Success 200 {object} response.Response{data=response.PageResp{lists=[]schema.SystemCornResp}} "成功" +// @Router /api/admin/system_corn/list [get] +func (hd *SystemCornHandler) List(c *gin.Context) { + var page request.PageReq + var listReq schema.SystemCornListReq + if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &page)) { + return + } + if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) { + return + } + res, err := service.SystemCornService.List(page, listReq) + response.CheckAndRespWithData(c, res, err) +} + +// @Summary 定时任务列表-所有 +// @Tags system_corn-定时任务 +// @Produce json +// @Param token header string true "token" +// @Param TaskName query string false "任务名称" +// @Param TaskCode query string false "任务编码" +// @Param CornExpr query string false "corn表达式" +// @Param Disabled query number false "禁用" +// @Param CreatedBy query string false "创建人" +// @Param CreateTimeStart query string false "创建时间" +// @Param CreateTimeEnd query string false "创建时间" +// @Param UpdateTimeStart query string false "更新时间" +// @Param UpdateTimeEnd query string false "更新时间" +// @Success 200 {object} response.Response{data=[]SystemCornResp} "成功" +// @Router /api/admin/system_corn/listAll [get] +func (hd *SystemCornHandler) ListAll(c *gin.Context) { + var listReq schema.SystemCornListReq + if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) { + return + } + res, err := service.SystemCornService.ListAll(listReq) + response.CheckAndRespWithData(c, res, err) +} + +// @Summary 定时任务详情 +// @Tags system_corn-定时任务 +// @Produce json +// @Param token header string true "token" +// @Param Id query string false "taskid" +// @Success 200 {object} response.Response{data=SystemCornResp} "成功" +// @Router /api/admin/system_corn/detail [get] +func (hd *SystemCornHandler) Detail(c *gin.Context) { + var detailReq schema.SystemCornPrimarykey + if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &detailReq)) { + return + } + res, err, _ := hd.requestGroup.Do(fmt.Sprintf("SystemCorn:Detail:%v", detailReq.Id), func() (any, error) { + v, err := service.SystemCornService.Detail(detailReq.Id) + return v, err + }) + + response.CheckAndRespWithData(c, res, err) +} + +// @Summary 定时任务新增 +// @Tags system_corn-定时任务 +// @Produce json +// @Param token header string true "token" +// @Param TaskName body string false "任务名称" +// @Param TaskCode body string false "任务编码" +// @Param CornExpr body string false "corn表达式" +// @Param Disabled body number false "禁用" +// @Success 200 {object} response.Response "成功" +// @Router /api/admin/system_corn/add [post] +func (hd *SystemCornHandler) Add(c *gin.Context) { + var addReq schema.SystemCornAddReq + if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &addReq)) { + return + } + var adminId = config.AdminConfig.GetAdminId(c) + createId, e := service.SystemCornService.Add(addReq, adminId) + response.CheckAndRespWithData(c, createId, e) +} + +// @Summary 定时任务编辑 +// @Tags system_corn-定时任务 +// @Produce json +// @Param token header string true "token" +// @Param Id body string false "taskid" +// @Param TaskName body string false "任务名称" +// @Param TaskCode body string false "任务编码" +// @Param CornExpr body string false "corn表达式" +// @Param Disabled body number false "禁用" +// @Success 200 {object} response.Response "成功" +// @Router /api/admin/system_corn/edit [post] +func (hd *SystemCornHandler) Edit(c *gin.Context) { + var editReq schema.SystemCornEditReq + if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &editReq)) { + return + } + response.CheckAndRespWithData(c, editReq.Id, service.SystemCornService.Edit(editReq)) +} + +// @Summary 定时任务删除 +// @Tags system_corn-定时任务 +// @Produce json +// @Param token header string true "token" +// @Param Id body string false "taskid" +// @Success 200 {object} response.Response "成功" +// @Router /api/admin/system_corn/del [post] +func (hd *SystemCornHandler) Del(c *gin.Context) { + var delReq schema.SystemCornPrimarykey + if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &delReq)) { + return + } + response.CheckAndResp(c, service.SystemCornService.Del(delReq.Id)) +} + +// @Summary 定时任务删除-批量 +// @Tags system_corn-定时任务 +// +// @Produce json +// @Param token header string true "token" +// @Param Ids body string false "逗号分割的id" +// @Success 200 {object} response.Response "成功" +// @Router /api/admin/system_corn/delBatch [post] +func (hd *SystemCornHandler) DelBatch(c *gin.Context) { + var delReq schema.SystemCornDelBatchReq + if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &delReq)) { + return + } + if delReq.Ids == "" { + response.FailWithMsg(c, response.SystemError, "请选择要删除的数据") + return + } + var Ids = strings.Split(delReq.Ids, ",") + + response.CheckAndResp(c, service.SystemCornService.DelBatch(Ids)) +} + +// @Summary 定时任务导出 +// @Tags system_corn-定时任务 +// @Produce octet-stream,json +// @Param token header string true "token" +// @Param TaskName query string false "任务名称" +// @Param TaskCode query string false "任务编码" +// @Param CornExpr query string false "corn表达式" +// @Param Disabled query number false "禁用" +// @Param CreatedBy query string false "创建人" +// @Param CreateTimeStart query string false "创建时间" +// @Param CreateTimeEnd query string false "创建时间" +// @Param UpdateTimeStart query string false "更新时间" +// @Param UpdateTimeEnd query string false "更新时间" +// @Success 200 {file} string "成功" +// @Failure 500 {object} response.Response "失败" +// @Router /api/admin/system_corn/ExportFile [get] +func (hd *SystemCornHandler) ExportFile(c *gin.Context) { + var listReq schema.SystemCornListReq + if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) { + return + } + res, err := service.SystemCornService.ExportFile(listReq) + if err != nil { + response.FailWithMsg(c, response.SystemError, "查询信息失败") + return + } + f, err := excel2.Export(res, service.SystemCornService.GetExcelCol(), "Sheet1", "定时任务") + if err != nil { + response.FailWithMsg(c, response.SystemError, "导出失败") + return + } + excel2.DownLoadExcel("定时任务"+time.Now().Format("20060102-150405"), c.Writer, f) +} + +// @Summary 定时任务导入 +// @Tags system_corn-定时任务 +// @Produce json +// @Param token header string true "token" +// @Param file formData file true "导入文件" +// @Success 200 {object} response.Response "成功" +// @Router /api/admin/system_corn/ImportFile [post] +func (hd *SystemCornHandler) ImportFile(c *gin.Context) { + file, _, err := c.Request.FormFile("file") + if err != nil { + c.String(http.StatusInternalServerError, "文件不存在") + return + } + defer file.Close() + importList := []schema.SystemCornResp{} + err = excel2.GetExcelData(file, &importList, service.SystemCornService.GetExcelCol()) + if err != nil { + c.String(http.StatusInternalServerError, err.Error()) + return + } + + err = service.SystemCornService.ImportFile(importList) + response.CheckAndResp(c, err) +} diff --git a/server/app/corn/init.go b/server/app/corn/init.go index 3a7d572..3ad8044 100644 --- a/server/app/corn/init.go +++ b/server/app/corn/init.go @@ -3,6 +3,8 @@ package corn import ( "x_admin/core" "x_admin/util" + + "gorm.io/gorm" ) // func init() { @@ -15,9 +17,74 @@ import ( // // 启动定时任务 // c.Start() // } + +// 定义任务结构体 +type TaskInfo struct { + TaskCode string // 任务编码 + TaskDesc string // 任务描述 + TaskFunc func() // 任务函数 +} + +var TaskInfoList = []TaskInfo{ + { + TaskCode: "exampleTask", + TaskDesc: "这是一个示例任务,每分钟执行一次", + TaskFunc: func() { + core.Logger.Info("执行示例任务: exampleTask") + }, + }, +} + +// 任务结构 +type RunTask struct { + TaskId string // 任务ID + TaskName string // 任务名称 + TaskCode string // 任务编码 + CronExpr string // cron表达式 + + Disabled bool // 是否禁用 + TaskInfo *TaskInfo // 任务信息 +} + +// 从数据库加载任务 +func LoadTasks(db *gorm.DB) []RunTask { + // 从数据库加载任务 + var tasks []RunTask + err := db.Where("disabled = ?", false).Find(&tasks).Error + if err != nil { + core.Logger.Error("从数据库加载任务失败", err) + return []RunTask{} + } + var RunTaskList = []RunTask{} // 运行中的任务列表 + + for _, task := range tasks { + if task.Disabled == true { + continue + } + for _, info := range TaskInfoList { + if task.TaskCode == info.TaskCode { + task.TaskInfo = &info + RunTaskList = append(RunTaskList, task) + break + } + } + } + return RunTaskList +} func init() { + // var db = core.GetDB() + // var RunTaskList = LoadTasks(db) tm := core.NewCronManager() tm.Start() + + // for _, task := range RunTaskList { + // if task.TaskInfo != nil { + // err := tm.AddTask(task.TaskId, task.CronExpr, task.TaskInfo.TaskFunc) + // if err != nil { + // core.Logger.Error("添加任务失败", err) + // } + // } + // } // defer tm.Stop() // 添加一个每5秒执行的任务 tm.AddTask("broadcast", "*/5 * * * * *", func() { diff --git a/server/app/schema/system_corn_schema.go b/server/app/schema/system_corn_schema.go new file mode 100644 index 0000000..9dcbd51 --- /dev/null +++ b/server/app/schema/system_corn_schema.go @@ -0,0 +1,59 @@ +package schema +import ( + "x_admin/core" +) + +type SystemCornPrimarykey struct { + Id string // taskid +} + +//SystemCornListReq 定时任务列表参数 +type SystemCornListReq struct { + TaskName core.NullString // 任务名称 + TaskCode core.NullString // 任务编码 + CornExpr core.NullString // corn表达式 + Disabled core.NullInt // 禁用 + CreatedBy core.NullString // 创建人 + CreateTimeStart core.NullString // 开始创建时间 + CreateTimeEnd core.NullString // 结束创建时间 + UpdateTimeStart core.NullString // 开始更新时间 + UpdateTimeEnd core.NullString // 结束更新时间 +} + + + +//SystemCornAddReq 定时任务新增参数 +type SystemCornAddReq struct { + TaskName core.NullString // 任务名称 + TaskCode core.NullString // 任务编码 + CornExpr core.NullString // corn表达式 + Disabled core.NullInt // 禁用 +} + +//SystemCornEditReq 定时任务编辑参数 +type SystemCornEditReq struct { + Id string // taskid + TaskName core.NullString // 任务名称 + TaskCode core.NullString // 任务编码 + CornExpr core.NullString // corn表达式 + Disabled core.NullInt // 禁用 +} + + + +//SystemCornDelBatchReq 定时任务批量删除参数 +type SystemCornDelBatchReq struct { + Ids string +} + +//SystemCornResp 定时任务返回信息 +type SystemCornResp struct { + Id string `swaggertype:"string"`// taskid + TaskName core.NullString `swaggertype:"string"`// 任务名称 + TaskCode core.NullString `swaggertype:"string"`// 任务编码 + CornExpr core.NullString `swaggertype:"string"`// corn表达式 + Disabled core.NullInt `swaggertype:"number"`// 禁用 + CreatedBy core.NullString `swaggertype:"string"`// 创建人 + CreateTime core.NullTime `swaggertype:"string"`// 创建时间 + UpdateTime core.NullTime `swaggertype:"string"`// 更新时间 +} diff --git a/server/app/service/generatorService/tpl_utils/templates/gocode/controller.go.tpl b/server/app/service/generatorService/tpl_utils/templates/gocode/controller.go.tpl index 7a219d1..ea48fe0 100644 --- a/server/app/service/generatorService/tpl_utils/templates/gocode/controller.go.tpl +++ b/server/app/service/generatorService/tpl_utils/templates/gocode/controller.go.tpl @@ -2,12 +2,13 @@ package admin_ctl import ( "net/http" - "strconv" + "fmt" "strings" "time" "github.com/gin-gonic/gin" "x_admin/core/request" "x_admin/core/response" + "x_admin/config" "x_admin/util" "x_admin/util/excel2" "golang.org/x/sync/singleflight" @@ -117,7 +118,10 @@ func (hd *{{{ toUpperCamelCase .ModuleName }}}Handler) Add(c *gin.Context) { if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &addReq)) { return } - createId, e := service.{{{ toUpperCamelCase .EntityName }}}Service.Add(addReq) + + var adminId = config.AdminConfig.GetAdminId(c)// 创建人 + + createId, e := service.{{{ toUpperCamelCase .EntityName }}}Service.Add(addReq, adminId) response.CheckAndRespWithData(c,createId, e) } // @Summary {{{ .FunctionName }}}编辑 diff --git a/server/app/service/generatorService/tpl_utils/templates/gocode/route.go.tpl b/server/app/service/generatorService/tpl_utils/templates/gocode/route.go.tpl index dbacfab..71592e7 100644 --- a/server/app/service/generatorService/tpl_utils/templates/gocode/route.go.tpl +++ b/server/app/service/generatorService/tpl_utils/templates/gocode/route.go.tpl @@ -16,16 +16,16 @@ import ( 3. 后台手动添加菜单和按钮 -INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, paths, component, is_cache, is_show, is_disable, create_time, update_time) VALUES (0, 'C', '{{{ .FunctionName }}}', '{{{nameToPath .ModuleName }}}/index', '{{{nameToPath .ModuleName }}}/index', 0, 1, 0, now(), now()); -INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT id, 'A', '{{{ .FunctionName }}}列表','admin:{{{ .ModuleName }}}:list', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='{{{nameToPath .ModuleName }}}/index'; -INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT id, 'A', '{{{ .FunctionName }}}全部列表','admin:{{{ .ModuleName }}}:listAll', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='{{{nameToPath .ModuleName }}}/index'; -INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT id, 'A', '{{{ .FunctionName }}}添加','admin:{{{ .ModuleName }}}:add', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='{{{nameToPath .ModuleName }}}/index'; -INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT id, 'A', '{{{ .FunctionName }}}编辑','admin:{{{ .ModuleName }}}:edit', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='{{{nameToPath .ModuleName }}}/index'; -INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT id, 'A', '{{{ .FunctionName }}}删除','admin:{{{ .ModuleName }}}:del', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='{{{nameToPath .ModuleName }}}/index'; -INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT id, 'A', '{{{ .FunctionName }}}删除-批量','admin:{{{ .ModuleName }}}:delBatch', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='{{{nameToPath .ModuleName }}}/index'; -INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT id, 'A', '{{{ .FunctionName }}}详情','admin:{{{ .ModuleName }}}:detail', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='{{{nameToPath .ModuleName }}}/index'; -INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT id, 'A', '{{{ .FunctionName }}}导出excel','admin:{{{ .ModuleName }}}:ExportFile', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='{{{nameToPath .ModuleName }}}/index'; -INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT id, 'A', '{{{ .FunctionName }}}导入excel','admin:{{{ .ModuleName }}}:ImportFile', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='{{{nameToPath .ModuleName }}}/index'; +INSERT INTO x_system_auth_menu (id,pid, menu_type, menu_name, paths, component, is_cache, is_show, is_disable, create_time, update_time) VALUES ('{{{makeID}}}',"0", 'C', '{{{ .FunctionName }}}', '{{{nameToPath .ModuleName }}}/index', '{{{nameToPath .ModuleName }}}/index', 0, 1, 0, now(), now()); +INSERT INTO x_system_auth_menu (id,pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT '{{{makeID}}}',id, 'A', '{{{ .FunctionName }}}列表','admin:{{{ .ModuleName }}}:list', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='{{{nameToPath .ModuleName }}}/index'; +INSERT INTO x_system_auth_menu (id,pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT '{{{makeID}}}',id, 'A', '{{{ .FunctionName }}}全部列表','admin:{{{ .ModuleName }}}:listAll', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='{{{nameToPath .ModuleName }}}/index'; +INSERT INTO x_system_auth_menu (id,pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT '{{{makeID}}}',id, 'A', '{{{ .FunctionName }}}添加','admin:{{{ .ModuleName }}}:add', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='{{{nameToPath .ModuleName }}}/index'; +INSERT INTO x_system_auth_menu (id,pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT '{{{makeID}}}',id, 'A', '{{{ .FunctionName }}}编辑','admin:{{{ .ModuleName }}}:edit', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='{{{nameToPath .ModuleName }}}/index'; +INSERT INTO x_system_auth_menu (id,pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT '{{{makeID}}}',id, 'A', '{{{ .FunctionName }}}删除','admin:{{{ .ModuleName }}}:del', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='{{{nameToPath .ModuleName }}}/index'; +INSERT INTO x_system_auth_menu (id,pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT '{{{makeID}}}',id, 'A', '{{{ .FunctionName }}}删除-批量','admin:{{{ .ModuleName }}}:delBatch', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='{{{nameToPath .ModuleName }}}/index'; +INSERT INTO x_system_auth_menu (id,pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT '{{{makeID}}}',id, 'A', '{{{ .FunctionName }}}详情','admin:{{{ .ModuleName }}}:detail', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='{{{nameToPath .ModuleName }}}/index'; +INSERT INTO x_system_auth_menu (id,pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT '{{{makeID}}}',id, 'A', '{{{ .FunctionName }}}导出excel','admin:{{{ .ModuleName }}}:ExportFile', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='{{{nameToPath .ModuleName }}}/index'; +INSERT INTO x_system_auth_menu (id,pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT '{{{makeID}}}',id, 'A', '{{{ .FunctionName }}}导入excel','admin:{{{ .ModuleName }}}:ImportFile', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='{{{nameToPath .ModuleName }}}/index'; */ diff --git a/server/app/service/generatorService/tpl_utils/templates/gocode/service.go.tpl b/server/app/service/generatorService/tpl_utils/templates/gocode/service.go.tpl index 0bd177e..9f6eacd 100644 --- a/server/app/service/generatorService/tpl_utils/templates/gocode/service.go.tpl +++ b/server/app/service/generatorService/tpl_utils/templates/gocode/service.go.tpl @@ -1,15 +1,17 @@ package service import ( + "errors" + "x_admin/app/schema" "x_admin/core" "x_admin/core/request" "x_admin/core/response" "x_admin/model" - "x_admin/app/schema" - "gorm.io/gorm" "x_admin/util" "x_admin/util/convert_util" "x_admin/util/excel2" + + "gorm.io/gorm" ) var {{{ toUpperCamelCase .EntityName }}}Service=New{{{ toUpperCamelCase .EntityName }}}Service() @@ -18,9 +20,9 @@ var {{{ toUpperCamelCase .EntityName }}}Service=New{{{ toUpperCamelCase .EntityN func New{{{ toUpperCamelCase .EntityName }}}Service() *{{{ toCamelCase .EntityName }}}Service { return &{{{ toCamelCase .EntityName }}}Service{ db: core.GetDB(), - CacheUtil util.CacheUtil{ + CacheUtil: util.CacheUtil{ Name: "{{{ toCamelCase .EntityName }}}", - } + }, } } @@ -69,11 +71,17 @@ func (service {{{ toCamelCase .EntityName }}}Service) GetUpdateMap(editReq schem updateMap := make(map[string]interface{}) {{{- range .Columns }}} {{{- if .IsEdit }}} + {{{- if .IsPk }}} + if editReq.{{{ toUpperCamelCase .ColumnName }}} !="" { + updateMap["{{{ .ColumnName }}}"] = editReq.{{{ toUpperCamelCase .ColumnName }}} + } + {{{- else }}} if editReq.{{{ toUpperCamelCase .ColumnName }}}.IsExists() { updateMap["{{{ .ColumnName }}}"] = editReq.{{{ toUpperCamelCase .ColumnName }}}.GetValue() } {{{- end }}} {{{- end }}} + {{{- end }}} return updateMap } // List {{{ .FunctionName }}}列表 @@ -143,9 +151,14 @@ func (service {{{ toCamelCase .EntityName }}}Service) Detail({{{ toUpperCamelCas } // Add {{{ .FunctionName }}}新增 -func (service {{{ toCamelCase .EntityName }}}Service) Add(addReq schema.{{{ toUpperCamelCase .EntityName }}}AddReq) (createId {{{.PrimaryKeyGoType}}},e error) { +func (service {{{ toCamelCase .EntityName }}}Service) Add(addReq schema.{{{ toUpperCamelCase .EntityName }}}AddReq, adminId string) (createId {{{.PrimaryKeyGoType}}},e error) { var obj model.{{{ toUpperCamelCase .EntityName }}} convert_util.Copy(&obj, addReq) + + // 需要判断有没有CreatedBy字段 + //obj.CreatedBy = adminId + obj.CreatedBy.SetValue(adminId) + err := service.db.Create(&obj).Error e = response.CheckMysqlErr(err) if e != nil { diff --git a/server/app/service/generatorService/tpl_utils/tpl.go b/server/app/service/generatorService/tpl_utils/tpl.go index b42c149..8bed09c 100644 --- a/server/app/service/generatorService/tpl_utils/tpl.go +++ b/server/app/service/generatorService/tpl_utils/tpl.go @@ -4,9 +4,9 @@ import ( "archive/zip" "bytes" "embed" + "fmt" "io" "path" - "strings" "text/template" "x_admin/core/response" "x_admin/model/gen_model" @@ -32,6 +32,7 @@ var TemplateUtil = templateUtil{ "pathToName": GenUtil.PathToName, "deletePathPrefix": GenUtil.DeletePathPrefix, "toSqlType": GenUtil.ToSqlType, + "makeID": GenUtil.MakeID, }), } @@ -236,25 +237,25 @@ func (tu templateUtil) Render(tplPath string, tplVars TplVars) (res string, e er func (tu templateUtil) GetFilePaths(tplCodeMap map[string]string, ModuleName string) map[string]string { //模板文件对应的输出文件 fmtMap := map[string]string{ - "gocode/model.go.tpl": strings.Join([]string{"server/model/", ModuleName, ".go"}, ""), - "gocode/route.go.tpl": strings.Join([]string{"server/router/adminRoute/", ModuleName, "_route.go"}, ""), + "gocode/model.go.tpl": fmt.Sprintf("server/model/%s.go", ModuleName), //strings.Join([]string{"server/model/", ModuleName, ".go"}, ""), + "gocode/route.go.tpl": fmt.Sprintf("server/routes/adminRoute/%s_route.go", ModuleName), //strings.Join([]string{"server/routes/adminRoute/", ModuleName, "_route.go"}, ""), - "gocode/schema.go.tpl": strings.Join([]string{"server/app/schema/", ModuleName, "_schema.go"}, ""), //"server/app/schema/%s_schema.go" - "gocode/service.go.tpl": strings.Join([]string{"server/app/service/", ModuleName, "_service.go"}, ""), //"server/app/service/%s_service.go", - "gocode/controller.go.tpl": strings.Join([]string{"server/app/controller/admin_ctl/", ModuleName, "_ctl.go"}, ""), //"server/app/controller/admin_ctl/%s_ctl.go", + "gocode/schema.go.tpl": fmt.Sprintf("server/app/schema/%s_schema.go", ModuleName), //"server/app/schema/%s_schema.go" + "gocode/service.go.tpl": fmt.Sprintf("server/app/service/%s_service.go", ModuleName), //"server/app/service/%s_service.go", + "gocode/controller.go.tpl": fmt.Sprintf("server/app/controller/admin_ctl/%s_ctl.go", ModuleName), //"server/app/controller/admin_ctl/%s_ctl.go", - "vue/api.ts.tpl": strings.Join([]string{"admin/src/api/", GenUtil.NameToPath(ModuleName), ".ts"}, ""), // "admin/src/api/%s.ts", - "vue/edit.vue.tpl": strings.Join([]string{"admin/src/views/", GenUtil.NameToPath(ModuleName), "/edit.vue"}, ""), // "admin/src/views/%s/edit.vue", - "vue/details.vue.tpl": strings.Join([]string{"admin/src/views/", GenUtil.NameToPath(ModuleName), "/details.vue"}, ""), // "admin/src/views/%s/details.vue", - "vue/index.vue.tpl": strings.Join([]string{"admin/src/views/", GenUtil.NameToPath(ModuleName), "/index.vue"}, ""), // "admin/src/views/%s/index.vue", - "vue/index-tree.vue.tpl": strings.Join([]string{"admin/src/views/", GenUtil.NameToPath(ModuleName), "/index.vue"}, ""), // "admin/src/views/%s/index-tree.vue", + "vue/api.ts.tpl": fmt.Sprintf("admin/src/api/%s.ts", GenUtil.NameToPath(ModuleName)), // "admin/src/api/%s.ts", + "vue/edit.vue.tpl": fmt.Sprintf("admin/src/views/%s/edit.vue", GenUtil.NameToPath(ModuleName)), // "admin/src/views/%s/edit.vue", + "vue/details.vue.tpl": fmt.Sprintf("admin/src/views/%s/details.vue", GenUtil.NameToPath(ModuleName)), // "admin/src/views/%s/details.vue", + "vue/index.vue.tpl": fmt.Sprintf("admin/src/views/%s/index.vue", GenUtil.NameToPath(ModuleName)), // "admin/src/views/%s/index.vue", + "vue/index-tree.vue.tpl": fmt.Sprintf("admin/src/views/%s/index.vue", GenUtil.NameToPath(ModuleName)), // "admin/src/views/%s/index-tree.vue", - "uniapp/api.ts.tpl": strings.Join([]string{"x_admin_app/api/", GenUtil.NameToPath(ModuleName), ".ts"}, ""), - "uniapp/edit.vue.tpl": strings.Join([]string{"x_admin_app/pages/", GenUtil.NameToPath(ModuleName), "/edit.vue"}, ""), - "uniapp/index.vue.tpl": strings.Join([]string{"x_admin_app/pages/", GenUtil.NameToPath(ModuleName), "/index.vue"}, ""), - "uniapp/search.vue.tpl": strings.Join([]string{"x_admin_app/pages/", GenUtil.NameToPath(ModuleName), "/search.vue"}, ""), - "uniapp/details.vue.tpl": strings.Join([]string{"x_admin_app/pages/", GenUtil.NameToPath(ModuleName), "/details.vue"}, ""), - "uniapp/pages.json.tpl": strings.Join([]string{"x_admin_app/pages/", GenUtil.NameToPath(ModuleName), "/pages.json"}, ""), + "uniapp/api.ts.tpl": fmt.Sprintf("x_admin_app/api/%s.ts", GenUtil.NameToPath(ModuleName)), // "x_admin_app/api/%s.ts", + "uniapp/edit.vue.tpl": fmt.Sprintf("x_admin_app/pages/%s/edit.vue", GenUtil.NameToPath(ModuleName)), // "x_admin_app/pages/%s/edit.vue", + "uniapp/index.vue.tpl": fmt.Sprintf("x_admin_app/pages/%s/index.vue", GenUtil.NameToPath(ModuleName)), // "x_admin_app/pages/%s/index.vue", + "uniapp/search.vue.tpl": fmt.Sprintf("x_admin_app/pages/%s/search.vue", GenUtil.NameToPath(ModuleName)), + "uniapp/details.vue.tpl": fmt.Sprintf("x_admin_app/pages/%s/details.vue", GenUtil.NameToPath(ModuleName)), + "uniapp/pages.json.tpl": fmt.Sprintf("x_admin_app/pages/%s/pages.json", GenUtil.NameToPath(ModuleName)), } filePath := make(map[string]string) for tplPath, tplCode := range tplCodeMap { diff --git a/server/app/service/generatorService/tpl_utils/utils.go b/server/app/service/generatorService/tpl_utils/utils.go index 2c8618e..ed30e77 100644 --- a/server/app/service/generatorService/tpl_utils/utils.go +++ b/server/app/service/generatorService/tpl_utils/utils.go @@ -215,6 +215,10 @@ func (gu genUtil) GetTablePriCol(columns []gen_model.GenTableColumn) (res gen_mo } return } +func (gu genUtil) MakeID() string { + uuid := util.ToolsUtil.MakeUuidV7() + return uuid +} /** * @description: Go类型转TS类型 diff --git a/server/app/service/monitorService/monitor_client_service.go b/server/app/service/monitorService/monitor_client_service.go index f0d563f..37c17c3 100644 --- a/server/app/service/monitorService/monitor_client_service.go +++ b/server/app/service/monitorService/monitor_client_service.go @@ -12,6 +12,7 @@ import ( "x_admin/util/excel2" "gorm.io/gorm" + "gorm.io/gorm/clause" ) var MonitorClientService = NewMonitorClientService() @@ -176,7 +177,16 @@ func (service monitorClientService) ErrorUsers(error_id string) (res []monitorSc func (service monitorClientService) Add(addReq monitorSchema.MonitorClientAddReq) (createId string, e error) { var obj model.MonitorClient convert_util.Copy(&obj, addReq) - err := service.db.Create(&obj).Error + err := service.db.Clauses(clause.OnConflict{ + Columns: []clause.Column{ + {Name: "client_id"}, // 指定以 client_id 作为冲突判断字段(可选,GORM 会自动推断唯一索引) + }, + DoUpdates: clause.Assignments(map[string]interface{}{ + "os": addReq.Os, + "browser": addReq.Browser, + "ua": addReq.Ua, + }), + }).Create(&obj).Error e = response.CheckMysqlErr(err) if e != nil { return "", e diff --git a/server/app/service/systemService/permService.go b/server/app/service/systemService/permService.go index 0412c6f..0f148b9 100644 --- a/server/app/service/systemService/permService.go +++ b/server/app/service/systemService/permService.go @@ -82,7 +82,7 @@ func (service systemAuthPermService) BatchSaveByMenuIds(roleId string, menuIds s var perms []system_model.SystemAuthPerm for _, menuId := range strings.Split(menuIds, ",") { - perms = append(perms, system_model.SystemAuthPerm{ID: util.ToolsUtil.MakeUuidV7(), RoleId: roleId, MenuId: menuId}) + perms = append(perms, system_model.SystemAuthPerm{RoleId: roleId, MenuId: menuId}) } txErr := tx.Create(&perms).Error var te = response.CheckErr(txErr, "BatchSaveByMenuIds Create in tx err") diff --git a/server/app/service/system_corn_service.go b/server/app/service/system_corn_service.go new file mode 100644 index 0000000..fc21782 --- /dev/null +++ b/server/app/service/system_corn_service.go @@ -0,0 +1,263 @@ +package service + +import ( + "errors" + "x_admin/app/schema" + "x_admin/core" + "x_admin/core/request" + "x_admin/core/response" + "x_admin/model" + "x_admin/util" + "x_admin/util/convert_util" + "x_admin/util/excel2" + + "gorm.io/gorm" +) + +var SystemCornService = NewSystemCornService() + +// NewSystemCornService 初始化 +func NewSystemCornService() *systemCornService { + return &systemCornService{ + db: core.GetDB(), + CacheUtil: util.CacheUtil{ + Name: "systemCorn", + }, + } +} + +// systemCornService 定时任务服务实现类 +type systemCornService struct { + db *gorm.DB + CacheUtil util.CacheUtil +} + +// List 定时任务列表 +func (service systemCornService) GetModel(listReq schema.SystemCornListReq) *gorm.DB { + // 查询 + dbModel := service.db.Model(&model.SystemCorn{}) + if listReq.TaskName.GetValue() != nil { + dbModel = dbModel.Where("task_name like ?", "%"+*listReq.TaskName.GetValue()+"%") + } + if listReq.TaskCode.GetValue() != nil { + dbModel = dbModel.Where("task_code = ?", *listReq.TaskCode.GetValue()) + } + if listReq.CornExpr.GetValue() != nil { + dbModel = dbModel.Where("corn_expr = ?", *listReq.CornExpr.GetValue()) + } + if listReq.Disabled.GetValue() != nil { + dbModel = dbModel.Where("disabled = ?", *listReq.Disabled.GetValue()) + } + if listReq.CreatedBy.GetValue() != nil { + dbModel = dbModel.Where("created_by = ?", *listReq.CreatedBy.GetValue()) + } + if listReq.CreateTimeStart.GetValue() != nil { + dbModel = dbModel.Where("create_time >= ?", *listReq.CreateTimeStart.GetValue()) + } + if listReq.CreateTimeEnd.GetValue() != nil { + dbModel = dbModel.Where("create_time <= ?", *listReq.CreateTimeEnd.GetValue()) + } + if listReq.UpdateTimeStart.GetValue() != nil { + dbModel = dbModel.Where("update_time >= ?", *listReq.UpdateTimeStart.GetValue()) + } + if listReq.UpdateTimeEnd.GetValue() != nil { + dbModel = dbModel.Where("update_time <= ?", *listReq.UpdateTimeEnd.GetValue()) + } + dbModel = dbModel.Where("is_delete = ?", 0) + return dbModel +} + +// 获取更新map +func (service systemCornService) GetUpdateMap(editReq schema.SystemCornEditReq) map[string]interface{} { + updateMap := make(map[string]interface{}) + if editReq.Id != "" { + updateMap["id"] = editReq.Id + } + if editReq.TaskName.IsExists() { + updateMap["task_name"] = editReq.TaskName.GetValue() + } + if editReq.TaskCode.IsExists() { + updateMap["task_code"] = editReq.TaskCode.GetValue() + } + if editReq.CornExpr.IsExists() { + updateMap["corn_expr"] = editReq.CornExpr.GetValue() + } + if editReq.Disabled.IsExists() { + updateMap["disabled"] = editReq.Disabled.GetValue() + } + return updateMap +} + +// List 定时任务列表 +func (service systemCornService) List(page request.PageReq, listReq schema.SystemCornListReq) (res response.PageResp, e error) { + // 分页信息 + limit := page.PageSize + offset := page.PageSize * (page.PageNo - 1) + dbModel := service.GetModel(listReq) + // 总数 + var count int64 + err := dbModel.Count(&count).Error + if e = response.CheckErr(err, "失败"); e != nil { + return + } + // 数据 + var modelList []model.SystemCorn + err = dbModel.Limit(limit).Offset(offset).Order("id desc").Find(&modelList).Error + if e = response.CheckErr(err, "查询失败"); e != nil { + return + } + result := []schema.SystemCornResp{} + convert_util.Copy(&result, modelList) + return response.PageResp{ + PageNo: page.PageNo, + PageSize: page.PageSize, + Count: count, + Lists: result, + }, nil +} + +// ListAll 定时任务列表 +func (service systemCornService) ListAll(listReq schema.SystemCornListReq) (res []schema.SystemCornResp, e error) { + dbModel := service.GetModel(listReq) + + var modelList []model.SystemCorn + + err := dbModel.Find(&modelList).Error + if e = response.CheckErr(err, "查询全部失败"); e != nil { + return + } + convert_util.Copy(&res, modelList) + return res, nil +} + +// Detail 定时任务详情 +func (service systemCornService) Detail(Id string) (res schema.SystemCornResp, e error) { + var obj = model.SystemCorn{} + err := service.CacheUtil.GetCache(Id, &obj) + if err != nil { + err := service.db.Where("id = ? AND is_delete = ?", Id, 0).Limit(1).First(&obj).Error + if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil { + return + } + if e = response.CheckErr(err, "获取详情失败"); e != nil { + return + } + service.CacheUtil.SetCache(obj.Id, obj) + } + + convert_util.Copy(&res, obj) + return +} + +// Add 定时任务新增 +func (service systemCornService) Add(addReq schema.SystemCornAddReq, adminId string) (createId string, e error) { + var obj model.SystemCorn + convert_util.Copy(&obj, addReq) + obj.CreatedBy.SetValue(adminId) + err := service.db.Create(&obj).Error + e = response.CheckMysqlErr(err) + if e != nil { + return "", e + } + service.CacheUtil.SetCache(obj.Id, obj) + createId = obj.Id + return +} + +// Edit 定时任务编辑 +func (service systemCornService) Edit(editReq schema.SystemCornEditReq) (e error) { + var obj model.SystemCorn + err := service.db.Where("id = ? AND is_delete = ?", editReq.Id, 0).Limit(1).First(&obj).Error + // 校验 + if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil { + return + } + if e = response.CheckErr(err, "查询失败"); e != nil { + return + } + // convert_util.Copy(&obj, editReq) + updateMap := service.GetUpdateMap(editReq) + if len(updateMap) == 0 { + return errors.New("没有可更新的字段") + } + + err = service.db.Model(&obj).Updates(updateMap).Error + if e = response.CheckErr(err, "编辑失败"); e != nil { + return + } + service.CacheUtil.RemoveCache(obj.Id) + // service.Detail(obj.Id) + return +} + +// Del 定时任务删除 +func (service systemCornService) Del(Id string) (e error) { + var obj model.SystemCorn + err := service.db.Where("id = ? AND is_delete = ?", Id, 0).Limit(1).First(&obj).Error + // 校验 + if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil { + return + } + if e = response.CheckErr(err, "查询数据失败"); e != nil { + return + } + // 删除 + obj.IsDelete = 1 + obj.DeleteTime = util.NullTimeUtil.Now() + err = service.db.Save(&obj).Error + e = response.CheckErr(err, "删除失败") + service.CacheUtil.RemoveCache(obj.Id) + return +} + +// DelBatch 用户协议-批量删除 +func (service systemCornService) DelBatch(Ids []string) (e error) { + var obj model.SystemCorn + err := service.db.Where("id in (?)", Ids).Delete(&obj).Error + if err != nil { + return err + } + // 删除缓存 + service.CacheUtil.RemoveCache(Ids) + return nil +} + +// 获取Excel的列 +func (service systemCornService) GetExcelCol() []excel2.Col { + var cols = []excel2.Col{ + {Name: "任务名称", Key: "TaskName", Width: 15, Decode: core.DecodeString}, + {Name: "任务编码", Key: "TaskCode", Width: 15, Decode: core.DecodeString}, + {Name: "corn表达式", Key: "CornExpr", Width: 15, Decode: core.DecodeString}, + {Name: "禁用", Key: "Disabled", Width: 15, Decode: core.DecodeInt}, + {Name: "创建人", Key: "CreatedBy", Width: 15, Decode: core.DecodeString}, + {Name: "创建时间", Key: "CreateTime", Width: 15, Decode: util.NullTimeUtil.DecodeTime}, + {Name: "更新时间", Key: "UpdateTime", Width: 15, Decode: util.NullTimeUtil.DecodeTime}, + } + // 还可以考虑字典,请求下来加上 Replace 实现替换导出 + return cols +} + +// ExportFile 定时任务导出 +func (service systemCornService) ExportFile(listReq schema.SystemCornListReq) (res []schema.SystemCornResp, e error) { + // 查询 + dbModel := service.GetModel(listReq) + + // 数据 + var modelList []model.SystemCorn + err := dbModel.Order("id asc").Find(&modelList).Error + if e = response.CheckErr(err, "查询失败"); e != nil { + return + } + result := []schema.SystemCornResp{} + convert_util.Copy(&result, modelList) + return result, nil +} + +// 导入 +func (service systemCornService) ImportFile(importReq []schema.SystemCornResp) (e error) { + var importData []model.SystemCorn + convert_util.Copy(&importData, importReq) + err := service.db.Create(&importData).Error + e = response.CheckErr(err, "添加失败") + return e +} diff --git a/server/core/corn.go b/server/core/corn.go index 524a939..32d5ad9 100644 --- a/server/core/corn.go +++ b/server/core/corn.go @@ -22,7 +22,21 @@ func NewCronManager() *CronManager { } } -// AddTask 添加任务 +// RemoveTask 删除任务 +func (tm *CronManager) RemoveTask(taskID string) { + tm.mutex.Lock() + defer tm.mutex.Unlock() + + if id, exists := tm.taskIDs[taskID]; exists { + tm.cron.Remove(id) + delete(tm.taskIDs, taskID) + fmt.Printf("任务 '%s' 已移除\n", taskID) + } else { + fmt.Printf("任务 '%s' 不存在\n", taskID) + } +} + +// AddTask 添加、更新任务 func (tm *CronManager) AddTask(taskID, spec string, cmd func()) error { tm.mutex.Lock() defer tm.mutex.Unlock() @@ -42,19 +56,18 @@ func (tm *CronManager) AddTask(taskID, spec string, cmd func()) error { return nil } -// RemoveTask 删除任务 -func (tm *CronManager) RemoveTask(taskID string) { - tm.mutex.Lock() - defer tm.mutex.Unlock() - - if id, exists := tm.taskIDs[taskID]; exists { - tm.cron.Remove(id) - delete(tm.taskIDs, taskID) - fmt.Printf("任务 '%s' 已移除\n", taskID) - } else { - fmt.Printf("任务 '%s' 不存在\n", taskID) - } -} +// 批量添加、更新任务,不存在的任务会添加,存在的任务会更新 +// func (tm *CronManager) AddTasks(tasks []*TaskInfo) error { +// for _, task := range tasks { +// if task.TaskId == "" || task.CronExpr == "" || task.TaskFunc == nil { +// return fmt.Errorf("任务ID、Cron表达式或任务函数不能为空") +// } +// if err := tm.AddTask(task.TaskId, task.CronExpr, task.TaskFunc); err != nil { +// return err +// } +// } +// return nil +// } // Start 启动任务调度器 func (tm *CronManager) Start() { diff --git a/server/model/monitor_client.go b/server/model/monitor_client.go index 804f745..53c6132 100644 --- a/server/model/monitor_client.go +++ b/server/model/monitor_client.go @@ -11,7 +11,7 @@ import ( type MonitorClient struct { Id string `gorm:"primarykey;type:char(36);comment:'uuid'"` // uuid ProjectKey string `gorm:"comment:'项目key'"` // 项目key - ClientId string `gorm:"comment:'sdk生成的客户端id'"` // sdk生成的客户端id + ClientId string `gorm:"uniqueIndex;comment:'sdk生成的客户端id'"` // sdk生成的客户端id // UserId string `gorm:"comment:'用户id'"` // 用户id Os string `gorm:"comment:'系统'"` // 系统 Browser string `gorm:"comment:'浏览器'"` // 浏览器 diff --git a/server/model/system_corn.go b/server/model/system_corn.go new file mode 100644 index 0000000..d71914b --- /dev/null +++ b/server/model/system_corn.go @@ -0,0 +1,30 @@ +package model +import ( + "github.com/google/uuid" + "gorm.io/gorm" + "x_admin/core" + "gorm.io/plugin/soft_delete" +) + +//SystemCorn 定时任务实体 +type SystemCorn struct { + Id string `gorm:"column:id;type:char(36);primarykey;comment:'taskid'"` + TaskName core.NullString `gorm:"column:task_name;type:char(100);comment:'任务名称'"` + TaskCode core.NullString `gorm:"column:task_code;type:char(100);comment:'任务编码'"` + CornExpr core.NullString `gorm:"column:corn_expr;type:char(100);comment:'corn表达式'"` + Disabled core.NullInt `gorm:"column:disabled;type:tinyint(1);comment:'禁用'"` + CreatedBy core.NullString `gorm:"column:created_by;type:char(36);comment:'创建人'"` + IsDelete soft_delete.DeletedAt `gorm:"column:is_delete;type:tinyint(1);not null;default:0;softDelete:flag,DeletedAtField:DeleteTime;comment:'是否删除: 0=否, 1=是'"` + CreateTime core.NullTime `gorm:"column:create_time;type:datetime;autoCreateTime;comment:'创建时间'"` + UpdateTime core.NullTime `gorm:"column:update_time;type:datetime;autoUpdateTime;comment:'更新时间'"` + DeleteTime core.NullTime `gorm:"column:delete_time;type:datetime;comment:'删除时间'"` +} +// 自动在创建时设置 UUIDv7 +func (u *SystemCorn) BeforeCreate(tx *gorm.DB) error { + id, err := uuid.NewV7() + if err != nil { + return err + } + u.Id = id.String() + return nil +} \ No newline at end of file diff --git a/server/routes/adminRoute/system_corn_route.go b/server/routes/adminRoute/system_corn_route.go new file mode 100644 index 0000000..d030ef9 --- /dev/null +++ b/server/routes/adminRoute/system_corn_route.go @@ -0,0 +1,52 @@ +package adminRoute + +import ( + "github.com/gin-gonic/gin" + "x_admin/middleware" + "x_admin/app/controller/admin_ctl" +) + +/** +集成 +1. 导入 +- 请先提交git避免文件覆盖!!! +- 下载并解压压缩包后,直接复制server、admin文件夹到项目根目录即可 + +2. 注册路由(通过init函数收集路由,Autoload自动注册) + +3. 后台手动添加菜单和按钮 + +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, paths, component, is_cache, is_show, is_disable, create_time, update_time) VALUES (0, 'C', '定时任务', 'system/corn/index', 'system/corn/index', 0, 1, 0, now(), now()); +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT id, 'A', '定时任务列表','admin:system_corn:list', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='system/corn/index'; +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT id, 'A', '定时任务全部列表','admin:system_corn:listAll', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='system/corn/index'; +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT id, 'A', '定时任务添加','admin:system_corn:add', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='system/corn/index'; +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT id, 'A', '定时任务编辑','admin:system_corn:edit', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='system/corn/index'; +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT id, 'A', '定时任务删除','admin:system_corn:del', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='system/corn/index'; +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT id, 'A', '定时任务删除-批量','admin:system_corn:delBatch', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='system/corn/index'; +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT id, 'A', '定时任务详情','admin:system_corn:detail', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='system/corn/index'; +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT id, 'A', '定时任务导出excel','admin:system_corn:ExportFile', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='system/corn/index'; +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) SELECT id, 'A', '定时任务导入excel','admin:system_corn:ImportFile', 0, 1, 0, now(), now() FROM x_system_auth_menu WHERE component='system/corn/index'; +*/ + + +// SystemCornRoute(rg) +func SystemCornRoute(rg *gin.RouterGroup) { + handle := admin_ctl.SystemCornHandler{} + + r := rg.Group("/", middleware.TokenAuth()) + r.GET("/system_corn/list", handle.List) + r.GET("/system_corn/listAll", handle.ListAll) + r.GET("/system_corn/detail", handle.Detail) + + r.POST("/system_corn/add",middleware.RecordLog("定时任务新增"), handle.Add) + r.POST("/system_corn/edit",middleware.RecordLog("定时任务编辑"), handle.Edit) + + r.POST("/system_corn/del", middleware.RecordLog("定时任务删除"), handle.Del) + r.POST("/system_corn/delBatch", middleware.RecordLog("定时任务删除-批量"), handle.DelBatch) + + r.GET("/system_corn/ExportFile", middleware.RecordLog("定时任务导出"), handle.ExportFile) + r.POST("/system_corn/ImportFile", handle.ImportFile) +} +func init() { + routeHandlers = append(routeHandlers, SystemCornRoute) +} diff --git a/server/util/tools.go b/server/util/tools.go index 6f239f4..f84ff35 100644 --- a/server/util/tools.go +++ b/server/util/tools.go @@ -10,7 +10,6 @@ import ( "mime/multipart" "os" "reflect" - "strings" "time" "github.com/google/uuid" @@ -40,7 +39,7 @@ func (tu toolsUtil) MakeUuidV7() string { if err != nil { return "" } - return strings.ReplaceAll(v7.String(), "-", "") + return v7.String() } // MakeMd5 制作MD5