Files
yunzerwebsiteallinone/go/controllers/platform_domain_approval.go
2026-10-07 13:46:32 +08:00

172 lines
6.0 KiB
Go
Raw Permalink 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 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
}