package controllers import ( "fmt" "time" "server/models" "server/services/approval" "github.com/beego/beego/v2/client/orm" ) // ============================================================= // 域名申请 × 审批流引擎 的接入层(严格模式,无单级兼容) // // 口径: // - 域名申请提交必须命中已配置的默认流程,走引擎多级流转; // - 未配置流程 / 节点无有效审批人 → 提交失败并回滚刚创建的域名行,绝不留下无法审批的脏数据; // - 审核只能通过引擎:必须存在在途实例且命中当前审批人的待办,否则拒绝操作。 // ============================================================= // submitDomainApprovalChecked 将域名提交进平台侧审批流。 // 成功返回空串;失败则软删回滚刚创建的域名行,并返回给前端的错误文案。 func submitDomainApprovalChecked(domainRowID, bizTid, submitUID uint64, submitName, fullDomain string) string { _, err := approval.Submit(approval.SubmitInput{ Scope: models.ApprovalScopePlatform, BizTid: bizTid, BizType: models.ApprovalBizDomain, BizID: domainRowID, BizTitle: fullDomain, SubmitUID: submitUID, SubmitName: submitName, }) if err == nil { return "" } // 提交失败:回滚刚创建的域名行(软删除),避免出现无法审批的待审僵尸数据 _, _ = models.Orm.QueryTable(new(models.SystemTenantDomain)). Filter("id", domainRowID).Update(map[string]interface{}{"delete_time": time.Now()}) if _, ok := err.(*approval.ErrNoFlow); ok { return "平台尚未配置域名审批流程,无法提交申请" } if _, ok := err.(*approval.ErrNoApprover); ok { return "域名审批流程未配置有效审批人,无法提交申请" } return "提交审批失败:" + err.Error() } // findRunningDomainInstance 取某域名当前在途的平台侧审批实例 func findRunningDomainInstance(domainID uint64) (*models.ApprovalInstance, bool) { var inst models.ApprovalInstance err := models.Orm.QueryTable(new(models.ApprovalInstance)). Filter("scope", models.ApprovalScopePlatform). Filter("biz_type", models.ApprovalBizDomain). Filter("biz_id", domainID). Filter("status", models.ApprovalInstanceRunning). Filter("is_deleted", 0). OrderBy("-id").One(&inst) if err == orm.ErrNoRows { return nil, false } if err != nil { return nil, false } return &inst, true } // myPendingDomainTask 取指定审批人在该实例上的当前待办任务 func myPendingDomainTask(instID, approverID uint64) (*models.ApprovalTask, bool) { var task models.ApprovalTask err := models.Orm.QueryTable(new(models.ApprovalTask)). Filter("instance_id", instID). Filter("approver_id", approverID). Filter("status", models.ApprovalTaskPending). Filter("is_deleted", 0). OrderBy("sort", "id").One(&task) if err != nil { return nil, false } return &task, true } // applyDomainApprovalResult 依据引擎结果回写域名状态(仅实例终结时改动) func applyDomainApprovalResult(domainID uint64, res *approval.ApproveResult) { if res == nil || !res.Finished { return } newStatus := 2 // 默认拒绝/驳回 if res.InstanceStat == models.ApprovalInstanceApproved { newStatus = 1 // 通过生效 } now := time.Now() _, _ = models.Orm.QueryTable(new(models.SystemTenantDomain)).Filter("id", domainID). Update(orm.Params{"status": newStatus, "update_time": now}) } // domainApprovalProgress 组装域名审批进度(节点 + 任务),供平台端展示 func domainApprovalProgress(domainID uint64) map[string]interface{} { inst, ok := findRunningDomainInstance(domainID) if !ok { // 无在途实例:可能未走引擎(单级审核)或已结束 return map[string]interface{}{"engine": false} } flow, err := approval.LoadFlow(models.ApprovalScopePlatform, 0, models.ApprovalBizDomain, inst.FlowID) nodes := []map[string]interface{}{} if err == nil && flow != nil { for _, nd := range flow.Nodes { nodes = append(nodes, map[string]interface{}{ "node_key": nd.NodeKey, "node_name": nd.NodeName, "node_type": nd.NodeType, "sort": nd.Sort, }) } } var tasks []models.ApprovalTask _, _ = models.Orm.QueryTable(new(models.ApprovalTask)). Filter("instance_id", inst.ID).Filter("is_deleted", 0). OrderBy("sort", "id").All(&tasks) taskList := make([]map[string]interface{}, 0, len(tasks)) for _, t := range tasks { taskList = append(taskList, map[string]interface{}{ "id": t.ID, "node_key": t.NodeKey, "node_name": t.NodeName, "approver_id": t.ApproverID, "approver_name": t.ApproverName, "status": t.Status, "action": t.Action, "comment": t.Comment, }) } return map[string]interface{}{ "engine": true, "instance_id": inst.ID, "current_node": inst.CurrentNode, "status": inst.Status, "nodes": nodes, "tasks": taskList, } } // engineDomainAudit 平台端审批入口(严格引擎驱动): // 必须存在在途实例且命中当前审批人的待办;否则拒绝,不做任何单级回退。 func engineDomainAudit(domainID, adminID uint64, pass bool, comment string, bizTid uint64) (msg string, code int) { inst, ok := findRunningDomainInstance(domainID) if !ok { return "该域名申请未进入审批流程(未配置流程或已处理)", 400 } task, ok := myPendingDomainTask(inst.ID, adminID) if !ok { return "该单据在审批流程中,当前不在您的待办节点", 403 } res, err := approval.Approve(task.ID, approval.ApproveInput{ ApproverID: adminID, Pass: pass, Comment: comment, BizTid: bizTid, }) if err != nil { return err.Error(), 400 } applyDomainApprovalResult(domainID, res) if res.Finished { if res.InstanceStat == models.ApprovalInstanceApproved { return "审批通过,域名已生效", 200 } return "已驳回", 200 } return fmt.Sprintf("已%s,流程继续(%s)", map[bool]string{true: "通过", false: "驳回"}[pass], res.Message), 200 }