工作列表
引擎提供了配套的工作查询功能,支持用户以多种方式筛选个人工作。同时支持跳转工作详情,查看或办理工作。
概览
用户可以根据工作创建时间、工作状态、办理状态、流程、标题等条件筛选工作,查询结果包含创建人、创建时间、工作、流程等信息。
自定义扩展
可以看到,默认的查询条件与结果仅包含引擎相关内容(流程、工作等),不包含业务相关数据。而在实际使用中,往往期望根据某些业务字段搜索工作,例如工单、客户、流水号等。为此引擎提供了工作查询扩展支持。
原理与限制
要想使用业务字段查询工作,必须将其与工作信息关联。但业务表并不唯一,无法简单关联。
引擎利用了 PostgreSQL 的表继承功能——把需要作为查询条件或结果的业务字段抽取至统一的基础表,然后使用基础表与工作信息关联,这样就解决了有多个业务表需要与工作信息关联的问题。
由于要关联查询,基础表必须包含 bizId 信息,通常为主键 id
。
提示
关于 bizId 的更多信息,请查看创建工作说明。
后端实现
与普通查询功能类似,后端实现同样需要实体定义、逻辑实现、服务注册几个步骤。但需要继承引擎提供的一些基础类。下面结合示例分别介绍。
实体 Entity
业务基础表对应的实体类,需继承 WorkBizEntityBase。
@TableName(value = "wf_work_biz_base")
public class WorkBizBase extends WorkBizEntityBase {
private String orderNumber;
private String customerCode;
// 省略 get/set 方法
}
入参 DTO
查询入参类,需继承 WorkSearchDto。由于入参类型无法预知,也就不能使用控制器的模型绑定功能,需要开发人员实现参数绑定与验证。
public class BizSearchDto extends WorkSearchDto {
private String orderNumber;
private String customerCode;
// 省略 get/set 方法
@Override
public void inflate(Map<String, String> requestParams) {
// 填充参数
this.orderNumber = requestParams.getOrDefault("orderNumber", null);
this.customerCode = requestParams.getOrDefault("customerCode", null);
}
@Override
public void validate() {
// 模型验证,按需实现
}
出参 VO
查询结果类,需继承 WorkSearchVo。
public class BizSearchVo extends WorkSearchVo {
private String orderNumber;
private String customerCode;
// 省略 get/set 方法
}
服务 Service
查询服务类,需继承泛型类 AbstractUserWorkSearcher。类型参数分别为上面定义的 Entity、DTO、VO 类。
开发人员需要重写 customQuery 方法,指定业务相关的查询条件与结果字段即可,查询主体已在基类实现。
@Service
@Primary
public class SimUserWorkSearcher extends AbstractUserWorkSearcher<WorkBizBase, BizSearchDto, BizSearchVo> {
@Override
protected void customQuery(MPJLambdaWrapper<?> condition, BizSearchDto dto) {
condition.select("b.order_number", BizSearchVo::getOrderNumber)
.select("b.customer_code", BizSearchVo::getCustomerCode)
.eq(StringUtils.isNotEmpty(dto.getOrderNumber()), "b.customer_code", dto.getOrderNumber())
.eq(StringUtils.isNotEmpty(dto.getCustomerCode()), "b.customer_code", dto.getCustomerCode());
}
}
注意
由于 ORM 框架限制,业务字段只能通过字符串方式指定,且必须使用表别名 b
。
注意
为了使自定义服务生效,除了声明为 Service 外,还需要声明为 Primary。
至此就完成了后端扩展,可以通过请求 /api/wf/works/mine
进行测试验证。
提示
此时 swagger 无法直接使用,需要 postman 等其它工具发送自定义参数。
.NET 差异
- 服务实现
由于 ORM 框架限制,业务条件与结果需要分别指定。
public class TestUserWorkSearcher : AbstractUserWorkSearcher<TestWorkBizEntity, TestWorkBizDto, TestWorkBizVo>
{
protected override Expression<Func<TestWorkBizEntity, bool>> GetQueryCondition(TestWorkBizDto dto)
{
return new OptionalExpressionBuilder<Func<TestWorkBizEntity, bool>>()
.WhereIfNotNullOrEmpty(dto.CustomerCode, t => t.CustomerCode == dto.CustomerCode)
.Build();
}
protected override Expression<Func<TestWorkBizEntity, TestWorkBizVo>> GetQuerySelector()
{
return t => new TestWorkBizVo
{
CustomerCode = t.CustomerCode,
ProductCode = t.ProductCode
};
}
}
- 服务注册
虽然在服务类上直接声明 [Service] 也可以达到目的——在 .NET 中获取指定服务时,如果存在多个匹配则取最后一次注册的服务,而开发人员声明的服务总是晚于基础框架注册的默认服务。
不过为了避免开发人员后续声明多个服务时出现顺序问题,强烈建议手动注册工作查询服务,不使用声明式注册。框架使用 TryAdd 方法注册默认查询服务,因此开发人员应在调用框架的注册服务方法前注册自定义查询服务。
// Startup.cs
public override void ConfigureServices(IServiceCollection services)
{
// 注册查询服务
services.AddScoped<IUserWorkSearcher, TestUserWorkSearcher>();
// 调用框架注册服务方法
base.ConfigureServices(services);
// 省略其它内容
}
前端实现
引擎提供了前端组件,供重写查询页面时使用。组件路径为 @frame/pages/work/list/components/WorkSearchList.vue
。
属性
名称 | 类型 | 说明 | 取值 |
---|---|---|---|
before-query-fn | function(query) | 查询前调用,供写入查询参数 | 默认为null |
reset-data-fn | function | 重置查询时调用,供清空查询条件 | 默认为null |
插槽
名称 | 类别 | 说明 |
---|---|---|
custom-condition | 查询条件 | 在默认查询条件之前(日期条件之后) |
custom-condition-back | 查询条件 | 在默认查询条件之后 |
custom-table-column | 查询结果 | 在“操作列”之前,内容为 el-table-column。 |
示例
下面给出一个简单示例。
<template>
<work-search-list :before-query-fn="onQuery" :reset-data-fn="onReset">
<!-- 自定义筛选条件 -->
<template #custom-condition>
<el-form-item label="客户代码:">
<el-input
v-model="query.customerCode"
placeholder="请输入"
clearable
></el-input>
</el-form-item>
</template>
<!-- 自定义列 -->
<template #custom-table-column>
<el-table-column
prop="customerCode"
align="left"
label="客户代码"
></el-table-column>
</template>
</work-search-list>
</template>
import WorkSearchList from "@frame/pages/work/list/components/WorkSearchList.vue";
export default {
name: "work-list",
components: {
WorkSearchList,
},
data() {
return {
query: this.initData(),
};
},
methods: {
initData() {
return {
customerCode: "",
};
},
onQuery(data) {
Object.assign(data, this.query);
},
onReset() {
this.query = this.initData();
},
},
};
系统菜单
实现新查询页面后,需要将“我的工作”菜单修改为新页面路径。同时,工作台“更多”按钮链接也需要修改。