HarmonyOS 「星办OA」App应用实战57 : 第57篇:多条件审批过滤引擎
第57篇:多条件审批过滤引擎
概述
在企业级审批系统中,随着审批数据的增长,用户需要一种高效、灵活的方式来筛选和查找审批记录。星办OA 在 ApprovalDomain.ts 中实现了 filterApprovals 过滤引擎,支持三维过滤逻辑:视图过滤、类型过滤和关键词匹配。本文将深入分析过滤引擎的实现原理、三维过滤的协作机制以及如何通过 ApprovalView 实现视图切换。 
一、过滤引擎的核心函数
1.1 filterApprovals 完整实现
export function filterApprovals(approvals: ApprovalRequest[], view: string,
type: string, keyword: string): ApprovalRequest[] {
let normalizedKeyword: string = keyword.trim().toLowerCase()
let result: ApprovalRequest[] = []
approvals.forEach((item: ApprovalRequest) => {
// 第一维:视图过滤
let inView: boolean = false
if (view === ApprovalView.PENDING) {
inView = item.pendingForMe && item.status === ApprovalStatus.PENDING
} else if (view === ApprovalView.MINE) {
inView = item.isMine
} else {
inView = item.handledByMe
}
// 第二维:类型过滤
let inType: boolean = type === '全部' || item.type === type
// 第三维:关键词匹配
let searchable: string = `${item.id} ${item.title} ${item.applicant}`.toLowerCase()
let inKeyword: boolean = normalizedKeyword.length === 0 || searchable.includes(normalizedKeyword)
// 三维条件同时满足时加入结果集
if (inView && inType && inKeyword) {
result.push(item)
}
})
return result
}
1.2 函数签名分析
filterApprovals(
approvals: ApprovalRequest[], // 完整审批列表
view: string, // 视图筛选(待我审批/我发起的/已处理)
type: string, // 类型筛选(全部/请假/报销/出差/...)
keyword: string // 关键词搜索
): ApprovalRequest[]
参数设计原则: 过滤引擎采用纯函数设计,输入完整的审批列表和三个筛选条件,输出过滤后的子集。这种设计保证了函数的可测试性和可预测性——相同的输入必定产生相同的输出。
二、三维过滤逻辑详解
2.1 第一维:视图过滤
视图过滤是最高优先级的筛选维度,它决定了用户从哪个视角查看审批数据:
let inView: boolean = false
if (view === ApprovalView.PENDING) {
inView = item.pendingForMe && item.status === ApprovalStatus.PENDING
} else if (view === ApprovalView.MINE) {
inView = item.isMine
} else {
inView = item.handledByMe
}
三个视图的筛选条件:
| 视图 | 筛选条件 | 业务含义 |
| 待我审批(PENDING) | pendingForMe === true 且 status === PENDING |
当前等待我审批的请求 |
| 我发起的(MINE) | isMine === true |
我提交的所有请求 |
| 已处理(HANDLED) | handledByMe === true |
我已经处理过的请求 |
视图切换的业务场景:
- 待我审批视图:一个审批人每天登录系统后,首先查看的是"待我审批"视图,了解自己需要处理哪些审批请求。
- 我发起的视图:申请人提交审批后,通过"我发起的"视图追踪申请进度,查看是已通过、已驳回还是仍在审批中。
- 已处理视图:审批人回顾自己处理过的历史记录,查看过往的审批决策。
2.2 第二维:类型过滤
类型过滤是第二维筛选,在视图筛选的基础上进一步缩小范围:
let inType: boolean = type === '全部' || item.type === type
类型过滤的逻辑: 当选择"全部"时,不过滤类型,返回视图中所有类型的审批记录;当选择具体类型(如"报销")时,只返回该类型的审批记录。
6 种审批类型的过滤场景:
| 筛选类型 | 业务场景 |
| 全部 | 查看所有类型的审批概览 |
| 请假 | 集中处理请假申请 |
| 报销 | 财务人员集中处理报销 |
| 出差 | 出差审批集中管理 |
| 采购 | 采购审批专项处理 |
| 加班 | 加班审批统一管理 |
| 用印 | 用印审批专项处理 |
2.3 第三维:关键词匹配
关键词匹配是最细粒度的筛选维度,通过全文搜索实现精确查找:
let searchable: string = `${item.id} ${item.title} ${item.applicant}`.toLowerCase()
let inKeyword: boolean = normalizedKeyword.length === 0 || searchable.includes(normalizedKeyword)
搜索范围分析: 搜索覆盖了三个字段:
- 审批单号(
id):如搜索"A20260824001"可以精确匹配到某条审批 - 审批标题(
title):如搜索"报销"可以匹配所有标题中包含"报销"的审批 - 申请人(
applicant):如搜索"周婷"可以找出该员工提交的所有审批
关键词匹配的模糊搜索机制:
// 关键词标准化
let normalizedKeyword: string = keyword.trim().toLowerCase()
// 搜索文本标准化
let searchable: string = `${item.id} ${item.title} ${item.applicant}`.toLowerCase()
// 模糊匹配
let inKeyword: boolean = normalizedKeyword.length === 0 || searchable.includes(normalizedKeyword)
模糊匹配的特点:
- 大小写不敏感:搜索关键词和搜索文本都转换为小写,确保大小写不影响搜索结果
- 部分匹配:使用
includes方法实现部分匹配,如搜索"李"可以匹配"李明" - 首尾空格去除:使用
trim()去除关键词首尾空格,避免因空格导致的匹配失败 - 空关键词跳过:当关键词为空时,跳过关键词过滤,提高搜索效率
三、三维过滤的协作机制
3.1 过滤流水线
三维过滤使用严格的 AND 逻辑串联:
inView && inType && inKeyword
这意味着一条审批记录必须同时满足三个条件才会出现在结果集中。这种设计的优势是:
- 精确性:三个维度层层递进,逐步缩小范围,最终找到用户需要的记录
- 可预测性:用户添加的每个条件都会进一步缩小结果集,行为符合直觉
- 组合灵活性:用户可以自由组合条件,如"待我审批的报销申请"或"我发起的包含'上海'的审批"
3.2 过滤场景示例
场景一:查看待审批的报销申请
filterApprovals(approvals, ApprovalView.PENDING, '报销', '')
// 结果:pendingForMe=true && status=PENDING && type=报销
// 匹配:报销 - 客户拜访交通费报销
场景二:搜索我发起的、包含"显示器"的审批
filterApprovals(approvals, ApprovalView.MINE, '全部', '显示器')
// 结果:isMine=true && title.includes('显示器')
// 匹配:采购 - 产品部显示器采购
场景三:搜索周婷提交的待审批申请
filterApprovals(approvals, ApprovalView.PENDING, '全部', '周婷')
// 结果:pendingForMe=true && status=PENDING && applicant.includes('周婷')
// 匹配:报销 - 客户拜访交通费报销
四、ApprovalView 视图定义
4.1 视图常量
export class ApprovalView {
static readonly PENDING: string = '待我审批'
static readonly MINE: string = '我发起的'
static readonly HANDLED: string = '已处理'
}
ApprovalView 使用静态常量定义三个视图名称,字符串常量既是视图的标识符,也是 UI 上显示的文字。这种设计简化了视图名称的管理,避免了名字和标识符之间的映射。
4.2 视图在 Store 中的使用
ApprovalStore 中提供了三个预定义的视图查询方法:
getPendingApprovals(): ApprovalRequest[] {
return filterApprovals(this.approvals, ApprovalView.PENDING, '全部', '')
}
getMineApprovals(): ApprovalRequest[] {
return filterApprovals(this.approvals, ApprovalView.MINE, '全部', '')
}
getHandledApprovals(): ApprovalRequest[] {
return filterApprovals(this.approvals, ApprovalView.HANDLED, '全部', '')
}
以及一个通用的过滤方法,支持自定义三个维度:
getFilteredApprovals(view: string, type: string, keyword: string): ApprovalRequest[] {
return filterApprovals(this.approvals, view, type, keyword)
}
五、过滤引擎的性能考量
5.1 时间复杂度
filterApprovals 使用线性扫描(forEach)遍历审批列表,时间复杂度为 O(n),其中 n 是审批记录的总数。
对于演示数据(7 条记录)来说,线性扫描的效率完全足够。在真实生产环境中,如果审批记录数量达到数千甚至数万条,可以考虑以下优化策略:
- 预索引:为视图类型(
pendingForMe、isMine、handledByMe)建立索引 - 分页加载:结合分页机制,每次只加载和过滤当前页的数据
- 延迟计算:使用
LazyForEach实现虚拟列表,只渲染可见区域的数据
5.2 搜索优化
当前的关键词搜索使用 includes 方法,实现了简单的模糊匹配。如果需要更高级的搜索功能,可以考虑:
- 多字段权重:标题匹配的权重高于审批单号匹配
- 拼音搜索:支持中文拼音搜索,如搜索"li ming"匹配"李明"
- 全文索引:构建倒排索引,加速搜索
六、实际应用场景
6.1 仪表盘统计
过滤引擎与仪表盘统计共用相同的筛选逻辑:
export function getDashboardStats(approvals: ApprovalRequest[], messages: ApprovalMessage[]): DashboardStats {
let stats: DashboardStats = new DashboardStats()
approvals.forEach((item: ApprovalRequest) => {
if (item.pendingForMe && item.status === ApprovalStatus.PENDING) {
stats.pending++ // 待我审批数
}
if (item.isMine) {
stats.mine++ // 我发起的数
}
if (item.handledByMe) {
stats.handled++ // 已处理数
}
})
messages.forEach((item: ApprovalMessage) => {
if (!item.isRead) {
stats.unread++ // 未读数
}
})
return stats
}
6.2 列表页的视图切换
在审批列表页中,用户可以通过 Tab 切换视图:
[待我审批] [我发起的] [已处理]
切换视图时,调用 filterApprovals 重新渲染列表。如果同时选择了类型筛选或输入了搜索关键词,这三个条件会组合使用。
七、总结
filterApprovals 过滤引擎是星办OA 审批系统的数据检索核心,它通过三维过滤逻辑(视图过滤、类型过滤、关键词匹配)实现了高效、灵活的数据筛选。
三维过滤的设计优势:
- 视图维度:从用户角色视角出发,解决了"谁看到什么数据"的问题
- 类型维度:从业务分类视角出发,解决了"按类型筛选"的问题
- 关键词维度:从搜索需求出发,解决了"精确查找"的问题
工程实现特点:
- 纯函数设计:无副作用,输入输出确定,易于测试和调试
- AND 逻辑串联:三个条件同时满足,结果精确可控
- 模糊搜索:大小写不敏感、部分匹配、空关键词跳过
- 视图常量:使用
ApprovalView静态常量统一管理视图名称
通过 filterApprovals 函数,星办OA 实现了从"海量数据"到"精准结果"的高效筛选,为用户提供了流畅的审批数据检索体验。
源文件路径: commons/common/src/main/ets/model/ApprovalDomain.ts
更多推荐



所有评论(0)