You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET MVC多流程统一审批前端泛型实现方案咨询及POC需求

统一审批流程的ASP.NET MVC实现方案

一、现有泛型实现的合理性分析

当前的泛型思路方向是合理的,但代码存在编译错误:RecruitmentDoc和LoanDoc继承的是未指定泛型参数的Document,正确的做法应该是让它们继承带具体业务数据类型的Document<T>。

用泛型类Document<T>封装不同流程的业务数据,同时统一承载审批通用属性(如流程ID、当前步骤、审批人等),既符合开闭原则(新增流程只需添加对应业务数据类,无需修改审批核心逻辑),也能为前端统一审批界面提供一致的数据模型支撑。

二、POC示例实现

1. 后端核心代码调整

泛型文档基类与流程业务数据类

// 泛型文档基类:封装通用审批属性+动态业务数据
public class Document<T>
{
    public T Data { get; set; }
    public int WorkFlowId { get; set; }
    public string CurrentStep { get; set; }
    public int CurrentStepOrder { get; set; }
    public bool IsRejected { get; set; }
    public string ApproverId { get; set; }

    public Document(T data)
    {
        Data = data;
    }
}

// 招聘流程专属业务数据
public class RecruitmentData
{
    public string PositionName { get; set; }
    public decimal SalaryRange { get; set; }
    public int RequiredExperience { get; set; }
}

// 招聘文档:绑定专属业务数据的泛型实例
public class RecruitmentDoc : Document<RecruitmentData>
{
    public RecruitmentDoc(RecruitmentData data) : base(data) { }
}

// 贷款流程专属业务数据
public class LoanData
{
    public decimal LoanAmount { get; set; }
    public int LoanTerm { get; set; }
    public string ApplicantId { get; set; }
}

// 贷款文档:绑定专属业务数据的泛型实例
public class LoanDoc : Document<LoanData>
{
    public LoanDoc(LoanData data) : base(data) { }
}

统一审批服务与控制器

// ProcessDetails表对应的实体类
public class ProcessDetail
{
    public int WorkFlowId { get; set; }
    public string ApproverId { get; set; }
    public string StepName { get; set; }
    public int StepOrder { get; set; }
    public string ActionType { get; set; }
}

// 统一审批逻辑服务
public class ApprovalService
{
    // 模拟从ProcessDetails表获取当前审批步骤(实际替换为数据库查询)
    public ProcessDetail GetCurrentApprovalStep(int workFlowId, int currentStepOrder)
    {
        return new ProcessDetail
        {
            WorkFlowId = workFlowId,
            ApproverId = User.Identity.Name,
            StepName = workFlowId == 1 ? "部门经理审批" : "风控专员审批",
            StepOrder = currentStepOrder,
            ActionType = "Approval"
        };
    }

    // 统一处理审批/驳回操作
    public bool PerformApproval(Document<object> document, bool isApproved, string comment)
    {
        // 1. 校验当前审批人权限(结合ProcessDetails表)
        // 2. 更新流程状态:通过则推进步骤,驳回则标记流程
        // 3. 记录审批日志
        return true; // 模拟操作成功
    }
}

// 统一审批控制器
public class ApprovalController : Controller
{
    private readonly ApprovalService _approvalService = new ApprovalService();

    // 统一审批页面入口
    public ActionResult Index(int workFlowId, int documentId)
    {
        var document = GetDocumentByWorkFlow(workFlowId, documentId);
        if (document == null) return HttpNotFound();

        ViewBag.CurrentStep = _approvalService.GetCurrentApprovalStep(document.WorkFlowId, document.CurrentStepOrder);
        ViewBag.WorkFlowId = workFlowId;
        return View(document);
    }

    // 模拟从数据库获取对应流程的文档数据
    private Document<object> GetDocumentByWorkFlow(int workFlowId, int documentId)
    {
        return workFlowId switch
        {
            1 => new RecruitmentDoc(new RecruitmentData
            {
                PositionName = "高级后端开发",
                SalaryRange = 25000,
                RequiredExperience = 5
            })
            {
                WorkFlowId = 1,
                CurrentStep = "部门经理审批",
                CurrentStepOrder = 1,
                ApproverId = User.Identity.Name
            },
            2 => new LoanDoc(new LoanData
            {
                LoanAmount = 500000,
                LoanTerm = 360,
                ApplicantId = "cust007"
            })
            {
                WorkFlowId = 2,
                CurrentStep = "风控专员审批",
                CurrentStepOrder = 2,
                ApproverId = User.Identity.Name
            },
            _ => null
        };
    }

    // 审批提交接口
    [HttpPost]
    public ActionResult SubmitApproval(int workFlowId, bool isApproved, string comment, FormCollection form)
    {
        var document = GetDocumentByWorkFlow(workFlowId, int.Parse(form["DocumentId"]));
        bool operationResult = _approvalService.PerformApproval(document, isApproved, comment);

        if (operationResult)
        {
            return isApproved 
                ? RedirectToAction("Index", new { workFlowId, documentId = form["DocumentId"] }) 
                : RedirectToAction("Rejected", new { workFlowId, documentId = form["DocumentId"] });
        }
        else
        {
            ModelState.AddModelError("", "审批操作失败,请重试");
            return View("Index", document);
        }
    }
}

2. Razor统一审批视图(Views/Approval/Index.cshtml)

@model Document<object>
@{
    ViewBag.Title = "统一审批页面";
    var currentStep = ViewBag.CurrentStep as ProcessDetail;
}

<div class="approval-container">
    <h2>当前审批环节:@currentStep.StepName</h2>
    
    <!-- 动态渲染不同流程的业务数据 -->
    <div class="document-content">
        <h3>流程详情</h3>
        @if (Model.Data is RecruitmentData recruitment)
        {
            <div class="recruitment-card">
                <p><strong>招聘岗位:</strong>@recruitment.PositionName</p>
                <p><strong>薪资范围:</strong>@recruitment.SalaryRange.ToString("C")</p>
                <p><strong>要求经验:</strong>@recruitment.RequiredExperience年</p>
            </div>
        }
        else if (Model.Data is LoanData loan)
        {
            <div class="loan-card">
                <p><strong>贷款金额:</strong>@loan.LoanAmount.ToString("C")</p>
                <p><strong>贷款期限:</strong>@loan.LoanTerm个月</p>
                <p><strong>申请人ID:</strong>@loan.ApplicantId</p>
            </div>
        }
    </div>

    <!-- 统一审批操作区域 -->
    <div class="approval-actions">
        @using (Html.BeginForm("SubmitApproval", "Approval", FormMethod.Post))
        {
            @Html.Hidden("WorkFlowId", ViewBag.WorkFlowId)
            @Html.Hidden("DocumentId", 1) <!-- 实际从路由/模型获取文档ID -->
            
            <div class="form-group">
                <label for="Comment">审批意见:</label>
                <textarea id="Comment" name="Comment" class="form-control" rows="3"></textarea>
            </div>

            <button type="submit" name="isApproved" value="true" class="btn btn-success mr-3">同意审批</button>
            <button type="submit" name="isApproved" value="false" class="btn btn-danger">驳回申请</button>
        }
    </div>
</div>

<style>
    .approval-container { max-width: 800px; margin: 2rem auto; padding: 2rem; border: 1px solid #eee; border-radius: 8px; }
    .document-content { margin: 1.5rem 0; padding: 1.2rem; background-color: #f8f9fa; border-radius: 4px; }
    .approval-actions { margin-top: 2rem; }
</style>

三、关键优化建议

  1. 将动态渲染业务数据的逻辑拆分为Razor部分视图(如_RecruitmentData.cshtml),通过Html.Partial动态加载,降低主视图复杂度
  2. 用AutoMapper简化不同文档类型的转换,避免控制器中硬编码类型判断
  3. 审批权限校验整合到ActionFilter中,统一处理权限拦截
  4. 流程状态更新使用数据库事务,确保数据一致性

内容的提问来源于stack exchange,提问作者user8512043

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 20:19:55