# 业务单根据状态进入不同的子模块

# 概述

本功能用于实现不同状态的数据自动归类到不同的列表页签中。例如合同管理中,起草中的合同进入“起草中”页签,审批中的合同进入“审批中”页签,待签署的合同进入“待签署”页签。

# 一、示例演示:合同管理

# 演示路径

  • 访问地址:应用中心
  • 模块名称:合同管理

# 业务处理效果

全部合同列表(共6个合同):

  • 合同100:起草中
  • 合同101:审批中
  • 合同102:待签署
  • 合同103:已生效
  • 合同104:已完成
  • 合同105:已终止

分类列表

  • 起草中:仅显示合同100
  • 审批中:仅显示合同101
  • 待签署:仅显示合同102

动态变化

  • 将合同100的状态从“起草中”改为“审批中”并保存
  • 合同100从“起草中”列表消失
  • 合同100出现在“审批中”列表中

# 二、实现方法

# 后台服务实现

文件路径Web项目\Apps\Controllers

每个状态对应一个独立的控制器,通过重载ApplyDataIsolationFilter过滤对应状态的数据。

起草中控制器SampleContractsDraftController.cs

// 第26-29行:过滤起草中的合同
protected override IQueryable<SampleContract> ApplyDataIsolationFilter(
    IQueryable<SampleContract> query, 
    HttpContext httpContext)
{
    return query.Where(x => x.Status == SampleContractStatus.Draft);
}

审批中控制器SampleContractsApprovingController.cs

// 第26-29行:过滤审批中的合同
protected override IQueryable<SampleContract> ApplyDataIsolationFilter(
    IQueryable<SampleContract> query, 
    HttpContext httpContext)
{
    return query.Where(x => x.Status == SampleContractStatus.Approving);
}

代码说明

  • 每个控制器重载ApplyDataIsolationFilter函数
  • 通过Where条件筛选特定状态的数据
  • 其他状态(待签署、已生效、已完成、已终止)的实现方式相同

# 前台配置

文件路径wwwroot\Apps\samples

每个状态对应一个独立的前台文件,通过serviceUrl指定对应的后台服务。

起草中前台ContractsDraft.js

Ext.define('Apps.samples.ContractsDraft', {
    extend: 'Apps.samples.ContractsAbstract',  // 继承公共基类
    serviceUrl: Yiez.$url('app/samples/contracts/draft')  // 指定后台服务
});

审批中前台ContractsApproving.js

Ext.define('Apps.samples.ContractsApproving', {
    extend: 'Apps.samples.ContractsAbstract',  // 继承公共基类
    serviceUrl: Yiez.$url('app/samples/contracts/approving')  // 指定后台服务
});

代码说明

  • 每个前台文件仅5行代码
  • 继承公共基类ContractsAbstract,复用列表配置
  • 通过serviceUrl指定对应的后台服务地址

# 模块菜单配置

文件路径Web项目\Apps\Navigator\Samples\ConceptController.cs

// 第115-146行:合同管理二级模块配置
new {
    id = "Sample.合同管理",
    text = "合同管理",
    expanded = true,
    children = new object[]{  // 二级模块配置
        new {
            id = "Sample.合同管理.起草中",
            text = "起草中",
            title = "起草中的合同",
            glyph = 0xec07,
            xclass = "Apps.samples.ContractsDraft"  // 关联前台类
        },
        new {
            id = "Sample.合同管理.审批中",
            text = "审批中",
            title = "正在审批的合同",
            glyph = 0xea96,
            xclass = "Apps.samples.ContractsApproving"  // 关联前台类
        },
        new {
            id = "Sample.合同管理.待签署",
            text = "待签署",
            title = "审批完成等待签署",
            glyph = 0xec08,
            xclass = "Apps.samples.ContractsPendingSignature"
        },
        new {
            id = "Sample.合同管理.全部合同",
            text = "全部合同",
            glyph = 0xeb0d,
            xclass = "Apps.samples.ContractsAll"
        }
    }
}

代码说明

  • 第119行children属性实现二级模块结构
  • 如需使用标签页,将children改为tabs即可

# 三、核心原理

# 实现架构

层级 作用 实现方式
后台控制器 数据过滤 重载ApplyDataIsolationFilter,按状态过滤
前台脚本 指定数据源 通过serviceUrl指定对应的后台服务
公共基类 复用代码 列表布局等公共配置在基类中统一实现
模块配置 菜单组织 使用childrentabs组织二级结构

# 数据流向

  1. 用户点击“起草中”菜单
  2. 加载ContractsDraft.js前台脚本
  3. 脚本通过serviceUrl调用/app/samples/contracts/draft服务
  4. 后台SampleContractsDraftController过滤出状态为Draft的数据
  5. 返回过滤后的数据并在列表中显示

# 四、配置步骤

# 操作步骤

  1. 创建后台控制器:为每个状态创建独立的控制器,重载ApplyDataIsolationFilter过滤对应状态
  2. 创建前台脚本:为每个状态创建独立的前台文件,指定对应的serviceUrl
  3. 提取公共基类:将列表公共配置提取到基类中,避免重复代码
  4. 配置模块菜单:在ConceptController.cs中使用childrentabs组织二级结构

# 关键要点

  • 数据过滤:通过ApplyDataIsolationFilter实现状态筛选
  • 代码复用:公共部分提取到基类,子类仅需指定服务地址
  • 菜单结构:使用children实现二级菜单,tabs实现标签页

# 五、常见应用场景

场景 分类方式 过滤条件
合同管理 按合同状态 x.Status == Draft/Approving/PendingSignature
订单管理 按订单状态 x.OrderStatus == New/Processing/Completed
任务管理 按任务状态 x.TaskStatus == Todo/Doing/Done
审批流程 按审批节点 x.ApprovalNode == DeptManager/HR/Finance

# 六、注意事项

  1. 状态一致性:前后台使用的状态值必须保持一致
  2. 基类复用:相同列表配置应提取到基类,避免重复代码
  3. 菜单结构:根据需求选择children(二级菜单)或tabs(标签页)
  4. 性能考虑:状态字段建议添加数据库索引

# 七、总结

不同状态的单子进入不同的标签页实现非常便捷:

  • 核心机制:使用ApplyDataIsolationFilter按状态过滤数据
  • 代码复用:公共部分提取到基类,子类只需指定服务地址
  • 灵活组织:支持children二级菜单和tabs标签页两种结构
  • 动态更新:修改状态后数据自动移动到对应分类

类似的功能,其核心就是数据的分类显示,使用ApplyDataIsolationFilter方法对不同子模块的数据进行过滤就能实现。子模块排布可以用二级模块(children),也可以用标签页(tabs)。