优化审批流

This commit is contained in:
hero920103 committed 2026-10-07 22:56:35 +08:00
1 parent ffaadc26ae
commit 438145cae7
17 files changed
+1131 -187

No files matched your search

+53 -27
View File
@@ -10,6 +10,7 @@ import (
"server/models"
"server/services"
approvalEngine "server/services/approval"
"github.com/beego/beego/v2/client/orm"
beego "github.com/beego/beego/v2/server/web"
@@ -26,12 +27,12 @@ type PlatformApprovalController struct {
// ---- 配置侧 JSON 结构 ----
// approvalNodePayload 单个节点(前端画布节点)。
// node_type:1开始 2审批 3结束 4条件网关;pos_x/pos_y 为画布坐标回显;
// condition_expr 为该节点作为「条件网关出边目标」时的进入条件(由 edges 反推落库)。
// node_type:1开始 2审批 3结束 4判断 5通知;pos_x/pos_y 为画布坐标回显;
// condition_expr 为该节点作为「判断节点出边目标」时的进入条件(由 edges 反推落库)。
type approvalNodePayload struct {
NodeKey string `json:"node_key"`
NodeName string `json:"node_name"`
NodeType int8 `json:"node_type"` // 1开始 2审批 3结束 4条件网关
NodeType int8 `json:"node_type"` // 1开始 2审批 3结束 4判断 5通知
ApproverType int8 `json:"approver_type"` // 1指定用户 2指定角色 ...
ApproverIDs []uint64 `json:"approver_ids"`
MultiMode int8 `json:"multi_mode"` // 1或签 2会签
@@ -52,31 +53,33 @@ type approvalEdge struct {
// approvalFlowSave 保存流程(图:节点 + 连线,节点全量覆盖)
type approvalFlowSave struct {
ID uint64 `json:"id"`
ModuleCode string `json:"module_code"`
BizType string `json:"biz_type"`
FlowName string `json:"flow_name"`
Description string `json:"description"`
IsDefault int8 `json:"is_default"`
Status int8 `json:"status"`
Nodes []approvalNodePayload `json:"nodes"`
Edges []approvalEdge `json:"edges"`
ID uint64 `json:"id"`
ModuleCode string `json:"module_code"`
BizType string `json:"biz_type"`
FlowName string `json:"flow_name"`
Description string `json:"description"`
IsDefault int8 `json:"is_default"`
Status int8 `json:"status"`
ApplyDeptIDs []uint64 `json:"apply_dept_ids"` // 仅租户侧使用,空=全公司通用
Nodes []approvalNodePayload `json:"nodes"`
Edges []approvalEdge `json:"edges"`
}
// approvalFlowView 流程 + 节点 + 连线(详情返回)
type approvalFlowView struct {
ID uint64 `json:"id"`
ModuleCode string `json:"module_code"`
BizType string `json:"biz_type"`
FlowCode string `json:"flow_code"`
FlowName string `json:"flow_name"`
Description string `json:"description"`
IsDefault int8 `json:"is_default"`
Status int8 `json:"status"`
NodeCount int `json:"node_count"`
CreateTime string `json:"create_time"`
Nodes []approvalNodePayload `json:"nodes"`
Edges []approvalEdge `json:"edges"`
ID uint64 `json:"id"`
ModuleCode string `json:"module_code"`
BizType string `json:"biz_type"`
FlowCode string `json:"flow_code"`
FlowName string `json:"flow_name"`
Description string `json:"description"`
IsDefault int8 `json:"is_default"`
Status int8 `json:"status"`
NodeCount int `json:"node_count"`
CreateTime string `json:"create_time"`
ApplyDeptIDs []uint64 `json:"apply_dept_ids"` // 仅租户侧回显
Nodes []approvalNodePayload `json:"nodes"`
Edges []approvalEdge `json:"edges"`
}
// readApprovalBody 读取并解析 JSON 请求体
@@ -355,6 +358,7 @@ func (c *PlatformApprovalController) Pick() {
list := make([]map[string]interface{}, 0, len(rows))
for _, r := range rows {
list = append(list, map[string]interface{}{
"id": r.ID,
"module_code": r.ModuleCode,
"biz_type": r.BizType,
"flow_code": r.FlowCode,
@@ -457,6 +461,28 @@ func (c *PlatformApprovalController) BizTypes() {
_ = c.ServeJSON()
}
// AvailableFlows GET /platform/approval/flow/available?biz_type=domain
// 业务侧“发起前拉可用流”:返回当前 biz_type 启用的平台流程列表。
// 平台无部门概念,userOrgID 固定为 0(引擎内平台侧不做部门过滤)。
func (c *PlatformApprovalController) AvailableFlows() {
if _, err := requirePlatform(&c.Controller); err != nil {
jsonErr(&c.Controller, 401, 401, err.Error())
return
}
bizType := strings.TrimSpace(c.GetString("biz_type"))
if bizType == "" {
jsonErr(&c.Controller, 400, 400, "缺少 biz_type 参数")
return
}
list, err := approvalEngine.ListAvailableFlows(models.ApprovalScopePlatform, 0, bizType, 0)
if err != nil {
jsonErr(&c.Controller, 500, 500, "查询失败: "+err.Error())
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "ok", "data": list}
_ = c.ServeJSON()
}
// ============================ 辅助函数 ============================
// approverDisplayName 优先姓名,回退账号(AdminUser.Account 为普通字符串)
@@ -467,7 +493,7 @@ func approverDisplayName(name *string, account string) string {
return strings.TrimSpace(account)
}
// validateApprovalNodes 校验审批节点:必须选定审批人来源且非空(开始/结束/条件网关跳过)
// validateApprovalNodes 校验审批节点:必须选定审批人来源且非空(开始/结束/判断/通知跳过)
func validateApprovalNodes(nodes []approvalNodePayload) error {
for i, nd := range nodes {
if nd.NodeType == models.ApprovalNodeStart || nd.NodeType == models.ApprovalNodeEnd ||
@@ -587,7 +613,7 @@ func rebuildEdges(nodes []flowEdgeNode) []approvalEdge {
return edges
}
// validateApprovalGraph 校验画布图的完整性:单一开始、审批节点≥1、网关出边≥2、全部可达、连线端点有效
// validateApprovalGraph 校验画布图的完整性:单一开始、审批节点≥1、判断节点出边≥2、全部可达、连线端点有效
func validateApprovalGraph(nodes []approvalNodePayload, edges []approvalEdge) error {
if len(nodes) == 0 {
return fmt.Errorf("流程至少需包含开始与审批节点")
@@ -632,7 +658,7 @@ func validateApprovalGraph(nodes []approvalNodePayload, edges []approvalEdge) er
}
for _, k := range condKeys {
if len(nextAdj[k]) < 2 {
return fmt.Errorf("条件网关需至少两条分支连线")
return fmt.Errorf("判断节点需至少两条分支连线")
}
}
visited := map[string]bool{}