Files
be.ems/src/modules/monitor/controller/sys_job.go

415 lines
11 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package controller
import (
"encoding/json"
"fmt"
"strconv"
"time"
"be.ems/src/framework/i18n"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
"be.ems/src/framework/utils/file"
"be.ems/src/framework/utils/parse"
"be.ems/src/modules/monitor/model"
"be.ems/src/modules/monitor/service"
systemService "be.ems/src/modules/system/service"
"github.com/gin-gonic/gin"
)
// 实例化控制层 SysJobLogController 结构体
var NewSysJob = &SysJobController{
sysJobService: service.NewSysJob,
sysDictDataService: systemService.NewSysDictData,
}
// 调度任务信息
//
// PATH /monitor/job
type SysJobController struct {
sysJobService *service.SysJob // 调度任务服务
sysDictDataService *systemService.SysDictData // 字典数据服务
}
// 调度任务列表
//
// GET /list
func (s *SysJobController) List(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
query := reqctx.QueryMap(c)
// 多语言值转key查询
if v, ok := query["jobName"]; ok && v != "" {
query["jobName"] = i18n.TFindKeyPrefix(language, "job", v)
}
rows, total := s.sysJobService.FindByPage(query)
// 闭包函数处理多语言
converI18n := func(language string, arr *[]model.SysJob) {
for i := range *arr {
(*arr)[i].JobName = i18n.TKey(language, (*arr)[i].JobName)
(*arr)[i].Remark = i18n.TKey(language, (*arr)[i].Remark)
}
}
converI18n(language, &rows)
c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
}
// 调度任务信息
//
// GET /:jobId
func (s *SysJobController) Info(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
jobId := parse.Number(c.Param("jobId"))
if jobId <= 0 {
c.JSON(400, resp.CodeMsg(40010, "bind err: jobId is empty"))
return
}
data := s.sysJobService.FindById(jobId)
if data.JobId == jobId {
// 处理多语言
data.JobName = i18n.TKey(language, data.JobName)
data.Remark = i18n.TKey(language, data.Remark)
c.JSON(200, resp.OkData(data))
return
}
c.JSON(200, resp.Err(nil))
}
// 调度任务新增
//
// POST /
func (s *SysJobController) Add(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body model.SysJob
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(40422, errMsgs))
return
}
if body.JobId > 0 {
c.JSON(400, resp.CodeMsg(40010, "bind err: jobId not is empty"))
return
}
// 检查cron表达式格式
if parse.CronExpression(body.CronExpression) == 0 {
// 调度任务新增【%s】失败Cron表达式不正确
msg := i18n.TTemplate(language, "job.errCronExpression", map[string]any{"name": body.JobName})
c.JSON(200, resp.ErrMsg(msg))
return
}
// 检查任务调用传入参数是否json格式
if body.TargetParams != "" {
// 调度任务新增【%s】失败任务传入参数json字符串不正确
msg := i18n.TTemplate(language, "job.errTargetParams", map[string]any{"name": body.JobName})
if len(body.TargetParams) < 7 {
c.JSON(200, resp.ErrMsg(msg))
return
}
if !json.Valid([]byte(body.TargetParams)) {
c.JSON(200, resp.ErrMsg(msg))
return
}
}
// 检查属性值唯一
uniqueJob := s.sysJobService.CheckUniqueByJobName(body.JobName, body.JobGroup, 0)
if !uniqueJob {
// 调度任务新增【%s】失败同任务组内有相同任务名称
msg := i18n.TTemplate(language, "job.errJobExists", map[string]any{"name": body.JobName})
c.JSON(200, resp.ErrMsg(msg))
return
}
body.CreateBy = reqctx.LoginUserToUserName(c)
insertId := s.sysJobService.Insert(body)
if insertId > 0 {
c.JSON(200, resp.Ok(nil))
return
}
c.JSON(200, resp.Err(nil))
}
// 调度任务修改
//
// PUT /
func (s *SysJobController) Edit(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body model.SysJob
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(40422, errMsgs))
return
}
if body.JobId <= 0 {
c.JSON(400, resp.CodeMsg(40010, "bind err: jobId is empty"))
return
}
// 检查cron表达式格式
if parse.CronExpression(body.CronExpression) == 0 {
// 调度任务修改【%s】失败Cron表达式不正确
msg := i18n.TTemplate(language, "job.errCronExpression", map[string]any{"name": body.JobName})
c.JSON(200, resp.ErrMsg(msg))
return
}
// 检查任务调用传入参数是否json格式
if body.TargetParams != "" {
// 调度任务修改【%s】失败任务传入参数json字符串不正确
msg := i18n.TTemplate(language, "job.errTargetParams", map[string]any{"name": body.JobName})
if len(body.TargetParams) < 7 {
c.JSON(200, resp.ErrMsg(msg))
return
}
if !json.Valid([]byte(body.TargetParams)) {
c.JSON(200, resp.ErrMsg(msg))
return
}
}
// 检查是否存在
jobInfo := s.sysJobService.FindById(body.JobId)
if jobInfo.JobId != body.JobId {
// 没有可访问调度任务数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "job.noData")))
return
}
// 检查属性值唯一
uniqueJob := s.sysJobService.CheckUniqueByJobName(body.JobName, body.JobGroup, body.JobId)
if !uniqueJob {
// 调度任务修改【%s】失败同任务组内有相同任务名称
msg := i18n.TTemplate(language, "job.errJobExists", map[string]any{"name": body.JobName})
c.JSON(200, resp.ErrMsg(msg))
return
}
// 多语言非原始值
i18nValue := i18n.TKey(language, jobInfo.JobName)
if i18nValue != jobInfo.JobName {
systemService.NewSysI18n.UpdateKeyValue(language, jobInfo.JobName, body.JobName)
body.JobName = jobInfo.JobName
}
// 多语言非原始值
i18nValue2 := i18n.TKey(language, jobInfo.Remark)
if i18nValue2 != jobInfo.Remark {
systemService.NewSysI18n.UpdateKeyValue(language, jobInfo.Remark, body.Remark)
body.Remark = jobInfo.Remark
}
jobInfo.JobName = body.JobName
jobInfo.JobGroup = body.JobGroup
jobInfo.InvokeTarget = body.InvokeTarget
jobInfo.TargetParams = body.TargetParams
jobInfo.CronExpression = body.CronExpression
jobInfo.MisfirePolicy = body.MisfirePolicy
jobInfo.Concurrent = body.Concurrent
jobInfo.StatusFlag = body.StatusFlag
jobInfo.SaveLog = body.SaveLog
jobInfo.Remark = body.Remark
jobInfo.UpdateBy = reqctx.LoginUserToUserName(c)
rows := s.sysJobService.Update(jobInfo)
if rows > 0 {
c.JSON(200, resp.Ok(nil))
return
}
c.JSON(200, resp.Err(nil))
}
// 调度任务删除
//
// DELETE /:jobId
func (s *SysJobController) Remove(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
jobId := c.Param("jobId")
if jobId == "" {
c.JSON(400, resp.CodeMsg(40010, "bind err: jobId is empty"))
return
}
// 处理字符转id数组后去重
uniqueIDs := parse.RemoveDuplicatesToArray(jobId, ",")
// 转换成int64数组类型
ids := make([]int64, 0)
for _, v := range uniqueIDs {
ids = append(ids, parse.Number(v))
}
rows, err := s.sysJobService.DeleteByIds(ids)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
c.JSON(200, resp.OkMsg(msg))
}
// 调度任务修改状态
//
// PUT /changeStatus
func (s *SysJobController) Status(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body struct {
JobId int64 `json:"jobId" binding:"required"`
StatusFlag string `json:"statusFlag" binding:"required,oneof=0 1 2"`
}
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(40422, errMsgs))
return
}
// 检查是否存在
// 检查是否存在
jobInfo := s.sysJobService.FindById(body.JobId)
if jobInfo.JobId != body.JobId {
// 没有可访问调度任务数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "job.noData")))
return
}
// 与旧值相等不变更
if jobInfo.StatusFlag == body.StatusFlag {
// 变更状态与旧值相等!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "job.statusEq")))
return
}
// 更新状态
jobInfo.StatusFlag = body.StatusFlag
jobInfo.UpdateBy = reqctx.LoginUserToUserName(c)
rows := s.sysJobService.Update(jobInfo)
if rows > 0 {
c.JSON(200, resp.Ok(nil))
return
}
c.JSON(200, resp.Err(nil))
}
// 调度任务立即执行一次
//
// PUT /run/:jobId
func (s *SysJobController) Run(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
jobId := parse.Number(c.Param("jobId"))
if jobId <= 0 {
c.JSON(400, resp.CodeMsg(40010, "bind err: jobId is empty"))
return
}
// 检查是否存在
job := s.sysJobService.FindById(jobId)
if job.JobId != jobId {
// 没有可访问调度任务数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "job.noData")))
return
}
ok := s.sysJobService.Run(job)
if ok {
c.JSON(200, resp.Ok(nil))
return
}
c.JSON(200, resp.Err(nil))
}
// 调度任务重置刷新队列
//
// PUT /resetQueueJob
func (s *SysJobController) ResetQueueJob(c *gin.Context) {
s.sysJobService.Reset()
c.JSON(200, resp.Ok(nil))
}
// Export 导出调度任务信息
//
// GET /export
func (s *SysJobController) Export(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
// 查询结果,根据查询条件结果,单页最大值限制
query := reqctx.QueryMap(c)
rows, total := s.sysJobService.FindByPage(query)
if total == 0 {
// c.JSON(200, resp.CodeMsg(40016, "export data record as empty"))
// 导出数据记录为空
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
return
}
// rows := s.sysJobService.SelectJobList(model.SysJob{})
if len(rows) <= 0 {
// 导出数据记录为空
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
return
}
// 闭包函数处理多语言
converI18n := func(language string, arr *[]model.SysJob) {
for i := range *arr {
(*arr)[i].JobName = i18n.TKey(language, (*arr)[i].JobName)
(*arr)[i].Remark = i18n.TKey(language, (*arr)[i].Remark)
}
}
converI18n(language, &rows)
// 导出文件名称
fileName := fmt.Sprintf("job_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli())
// 第一行表头标题
headerCells := map[string]string{
"A1": i18n.TKey(language, "job.export.jobID"),
"B1": i18n.TKey(language, "job.export.jobName"),
"C1": i18n.TKey(language, "job.export.jobGroupName"),
"D1": i18n.TKey(language, "job.export.invokeTarget"),
"E1": i18n.TKey(language, "job.export.cronExpression"),
"F1": i18n.TKey(language, "job.export.status"),
"G1": i18n.TKey(language, "job.export.remark"),
// "E1": i18n.TKey(language, "job.export.targetParams"),
}
// 读取任务组名字典数据
dictSysJobGroup := s.sysDictDataService.FindByType("sys_job_group")
// 从第二行开始的数据
dataCells := make([]map[string]any, 0)
for i, row := range rows {
idx := strconv.Itoa(i + 2)
// 任务组名
sysJobGroup := ""
for _, v := range dictSysJobGroup {
if row.JobGroup == v.DataValue {
sysJobGroup = i18n.TKey(language, v.DataLabel)
break
}
}
// 状态
statusValue := i18n.TKey(language, "dictData.fail")
if row.StatusFlag == "1" {
statusValue = i18n.TKey(language, "dictData.success")
}
dataCells = append(dataCells, map[string]any{
"A" + idx: row.JobId,
"B" + idx: row.JobName,
"C" + idx: sysJobGroup,
"D" + idx: row.InvokeTarget,
"E" + idx: row.CronExpression,
"F" + idx: statusValue,
"G" + idx: row.Remark,
// "E" + idx: row.TargetParams,
})
}
// 导出数据表格
saveFilePath, err := file.WriteSheet(headerCells, dataCells, fileName, "")
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.FileAttachment(saveFilePath, fileName)
}