feat: message notify

This commit is contained in:
meilin.huang
2025-04-15 21:42:31 +08:00
parent 3c0292b56e
commit 1b40d345eb
104 changed files with 2681 additions and 288 deletions

View File

@@ -10,6 +10,7 @@ type Procdef struct {
Status entity.ProcdefStatus `json:"status" binding:"required"`
Condition string `json:"condition"`
Remark string `json:"remark"`
MsgTmplId uint64 `json:"msgTmplId"`
CodePaths []string `json:"codePaths"`
}

View File

@@ -7,11 +7,14 @@ import (
"mayfly-go/internal/flow/application/dto"
"mayfly-go/internal/flow/domain/entity"
"mayfly-go/internal/flow/imsg"
msgapp "mayfly-go/internal/msg/application"
msgentity "mayfly-go/internal/msg/domain/entity"
tagapp "mayfly-go/internal/tag/application"
tagentity "mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/req"
"mayfly-go/pkg/utils/collx"
"mayfly-go/pkg/utils/structx"
"strings"
"github.com/may-fly/cast"
@@ -20,12 +23,15 @@ import (
type Procdef struct {
procdefApp application.Procdef `inject:"T"`
tagTreeRelateApp tagapp.TagTreeRelate `inject:"T"`
msgTmplBizApp msgapp.MsgTmplBiz `inject:"T"`
}
func (p *Procdef) ReqConfs() *req.Confs {
reqs := [...]*req.Conf{
req.NewGet("", p.GetProcdefPage),
req.NewGet("/detail/:id", p.GetProcdefDetail),
req.NewGet("/:resourceType/:resourceCode", p.GetProcdef),
req.NewPost("", p.Save).Log(req.NewLogSaveI(imsg.LogProcdefSave)).RequiredPermissionCode("flow:procdef:save"),
@@ -49,6 +55,25 @@ func (p *Procdef) GetProcdefPage(rc *req.Ctx) {
rc.ResData = res
}
func (p *Procdef) GetProcdefDetail(rc *req.Ctx) {
def, err := p.procdefApp.GetById(cast.ToUint64(rc.PathParamInt("id")))
biz.ErrIsNil(err)
res := new(vo.Procdef)
biz.ErrIsNil(structx.Copy(res, def))
p.tagTreeRelateApp.FillTagInfo(tagentity.TagRelateTypeFlowDef, res)
bizMsgTmpl := &msgentity.MsgTmplBiz{
BizId: res.Id,
BizType: application.FlowTaskNotifyBizKey,
}
if p.msgTmplBizApp.GetByCond(bizMsgTmpl) == nil {
res.MsgTmplId = &bizMsgTmpl.TmplId
}
rc.ResData = res
}
func (p *Procdef) GetProcdef(rc *req.Ctx) {
resourceType := rc.PathParamInt("resourceType")
resourceCode := rc.PathParam("resourceCode")
@@ -61,6 +86,7 @@ func (a *Procdef) Save(rc *req.Ctx) {
rc.ReqParam = form
biz.ErrIsNil(a.procdefApp.SaveProcdef(rc.MetaCtx, &dto.SaveProcdef{
Procdef: procdef,
MsgTmplId: form.MsgTmplId,
CodePaths: form.CodePaths,
}))
}

View File

@@ -8,6 +8,8 @@ import (
type Procdef struct {
tagentity.RelateTags // 标签信息
entity.Procdef
MsgTmplId *uint64 `json:"msgTmplId" gorm:"-"` // 消息模板ID
}
func (p *Procdef) GetRelateId() uint64 {

View File

@@ -0,0 +1,5 @@
package application
const (
FlowTaskNotifyBizKey = "flow:task:notify" // 工单任务处理通知
)

View File

@@ -4,6 +4,7 @@ import "mayfly-go/internal/flow/domain/entity"
type SaveProcdef struct {
Procdef *entity.Procdef
MsgTmplId uint64 // 消息模板id
CodePaths []string
}

View File

@@ -6,6 +6,8 @@ import (
"mayfly-go/internal/flow/domain/entity"
"mayfly-go/internal/flow/domain/repository"
"mayfly-go/internal/flow/imsg"
msgapp "mayfly-go/internal/msg/application"
msgdto "mayfly-go/internal/msg/application/dto"
tagapp "mayfly-go/internal/tag/application"
tagentity "mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/base"
@@ -36,6 +38,7 @@ type procdefAppImpl struct {
procinstApp Procinst `inject:"T"`
msgTmplBizApp msgapp.MsgTmplBiz `inject:"T"`
tagTreeApp tagapp.TagTree `inject:"T"`
tagTreeRelateApp tagapp.TagTreeRelate `inject:"T"`
}
@@ -67,6 +70,14 @@ func (p *procdefAppImpl) SaveProcdef(ctx context.Context, defParam *dto.SaveProc
return p.Tx(ctx, func(ctx context.Context) error {
return p.Save(ctx, def)
}, func(ctx context.Context) error {
// 保存通知消息模板
if err := p.msgTmplBizApp.SaveBizTmpl(ctx, msgdto.MsgTmplBizSave{
TmplId: defParam.MsgTmplId,
BizType: FlowTaskNotifyBizKey,
BizId: def.Id,
}); err != nil {
return err
}
return p.tagTreeRelateApp.RelateTag(ctx, tagentity.TagRelateTypeFlowDef, def.Id, defParam.CodePaths...)
})
}

View File

@@ -3,19 +3,24 @@ package application
import (
"context"
"fmt"
"mayfly-go/internal/event"
"mayfly-go/internal/flow/application/dto"
"mayfly-go/internal/flow/domain/entity"
"mayfly-go/internal/flow/domain/repository"
"mayfly-go/internal/flow/imsg"
msgdto "mayfly-go/internal/msg/application/dto"
"mayfly-go/pkg/base"
"mayfly-go/pkg/contextx"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/global"
"mayfly-go/pkg/i18n"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils/anyx"
"mayfly-go/pkg/utils/jsonx"
"mayfly-go/pkg/utils/stringx"
"github.com/may-fly/cast"
)
type Procinst interface {
@@ -140,6 +145,7 @@ func (p *procinstAppImpl) CompleteTask(ctx context.Context, instTaskId uint64, r
procinst.SetEnd()
} else {
procinst.TaskKey = task.TaskKey
}
return p.Tx(ctx, func(ctx context.Context) error {
@@ -287,7 +293,26 @@ func (p *procinstAppImpl) createProcinstTask(ctx context.Context, procinst *enti
TaskName: task.Name,
Assignee: task.UserId,
}
return p.procinstTaskRepo.Insert(ctx, procinstTask)
if err := p.procinstTaskRepo.Insert(ctx, procinstTask); err != nil {
return err
}
// 发送通知消息
global.EventBus.Publish(ctx, event.EventTopicBizMsgTmplSend, msgdto.BizMsgTmplSend{
BizType: FlowTaskNotifyBizKey,
BizId: procinst.ProcdefId,
Params: map[string]any{
"creator": procinst.Creator,
"procdefName": procinst.ProcdefName,
"bizKey": procinst.BizKey,
"taskName": task.Name,
"procinstRemark": procinst.Remark,
},
ReceiverIds: []uint64{cast.ToUint64(task.UserId)},
})
return nil
}
// 获取下一审批节点任务

View File

@@ -15,6 +15,7 @@ type ProcinstTaskQuery struct {
ProcinstId uint64 `json:"procinstId"` // 流程实例id
ProcinstName string `json:"procinstName"` // 流程实例名称
BizType string `json:"bizType" form:"bizType"`
BizKey string `json:"bizKey" form:"bizKey"` // 业务key
Assignee string `json:"assignee"` // 分配到该任务的用户
Status ProcinstTaskStatus `json:"status" form:"status"` // 状态
}

View File

@@ -4,6 +4,7 @@ import (
"mayfly-go/internal/flow/domain/entity"
"mayfly-go/internal/flow/domain/repository"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
)
@@ -31,6 +32,14 @@ func newProcinstTaskRepo() repository.ProcinstTask {
}
func (p *procinstTaskImpl) GetPageList(condition *entity.ProcinstTaskQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
qd := model.NewModelCond(condition)
return p.PageByCondToAny(qd, pageParam, toEntity)
qd := gormx.NewQueryWithTableName("t_flow_procinst_task t").
Joins("JOIN t_flow_procinst tp ON t.procinst_id = tp.id ").
WithCond(model.NewCond().Columns("t.*, tp.biz_key").
Eq("tp.biz_key", condition.BizKey).
Eq0("tp.is_deleted", model.ModelUndeleted).
Eq("tp.biz_type", condition.BizType).
Eq0("t.is_deleted", model.ModelUndeleted).
Eq("t.status", condition.Status).
OrderByDesc("t.id"))
return gormx.PageQuery(qd, pageParam, toEntity)
}