支持与现有的业务系统对接,支持业务系统的用户、角色和部门,本系统仅做流程处理。
自动登录
本系统提供一种自动登录的方式仅供参考,若不符合业务系统要求,可自行扩展
时序图:

- 业务系统跳转到本系统之前,生成一个当前登录用户的唯一token用来识别当前用户
- 前端将生成的token和租户id(若有)拼在本系统登录页面的url当参数传递,格式:
http://pro.flyflow.cc/login?token=*******&&tenantId=******* - 本系统前端将获取的token和租户id自动传递给本系统服务器处理
- 本系统服务器收到前端提交的token之后,请求业务服务端进行鉴权;若鉴权成功,返回跟token对应的userId
- 本系统收到鉴权之后的userId之后登录系统,并将登录信息返回给本系统前端页面
- 本系统前端页面登录成功跳转到首页
从上面步骤可以看出,业务系统有三处需要改造:
- 服务端:提供生成token的接口,并将与当前登录用户关联起来
- web端:获取token并跳转本系统
- 服务端:提供鉴权接口给本系统,参数是token,返回值是userId
相关接口格式下面介绍,此处不展开了
注意事项
- 如果组织架构数据非本系统提供,则需要将
role.allPermission设置为true
因为没有角色权限是不能登录系统的,而外部的用户未被设置角色,所以需要打开该配置默认所有人拥有所有的角色权限
- 具体实现的方式,可以参考FlyFlow默认的sql实现
- 如果用户离职了,或者在业务系统不存在了,根据用户id查询用户信息,也要返回,因为涉及到此人之前审批流程的人员信息回显,此时可以将该用户的状态置为
0:禁用即可
对接其他系统的组织架构
FlyFlow预留接口支持对接其他系统的组织架构,支持通过实现接口ApiStrategy来自定义对接方式,包括Http、直连数据库等,只要参数和返回值满足接口需求即可
以上无论何种方式对接,都记得修改配置文件中的api.ori选项
商业版涉及到的接口文档如下:
1.初始化数据
方法名: initData
备注:项目启动的时候初始化数据,比如钉钉对接版,项目启动的时候判断数据库是否有用户部门数据,若没有会通过钉钉接口下载全量的钉钉部门和用户数据
参数:
返回值:
2.远程拉取部门数据
方法名: loadRemoteDept
备注: 全量同步部门数据,比如钉钉版,手动点击同步全量部门数据
参数:
返回值:
3.远程拉取用户数据
方法名: loadRemoteUser
备注: 只同步用户数据,可以根据手机号精确同步;比如新入职的员工,可以只同步这个用户;要注意,如果新用户的部门一定要提前同步好或者建立好
参数:
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| phone | 手机号 | 否 | string | |
返回值: R对象
4.获取部门的根节点id
方法名: getDeptRootId
备注: 最高层级的节点id,比如第一个部门id是1,那要返回的就是这个部门的上级部门id,比如0;从技术设计上也是要有一个值,不要返回null
参数:
返回值: 部门根节点id,String类型
5.根据部门、角色、岗位和标签查询用户列表
方法名: queryUserPropertyList
备注: 具体实现可以参考FlyFlow的默认实现,暂时只会出现部门和其他的交叉查询,不会查询角色和岗位的交叉查询等;返回值里要返回对应的部门id、用户id、岗位id、标签id,是为了排序:比如页面上先选择了标签1、标签2,那展示的时候也要按照这个顺序来展示,因为审批人支持多人顺序签署,所以要保证顺序
参数:
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| deptIdList | 部门id | 否 | array<string> | |
| roleIdList | 角色id | 否 | array<string> | |
| postIdList | 岗位id | 否 | array<string> | |
| labelIdList | 标签id | 否 | array<string> | |
返回值:List类型
| 参数 | 名称 | 类型 | 备注 |
| deptId | 部门id | string | |
| userId | 用户id | string | |
| userName | 用户名称 | string | |
| postId | 岗位id | string | |
| labelId | 标签id | string | |
6.根据用户id查询角色id集合
方法名: loadRoleIdListByUserId
备注:
参数:userId:String
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| userId | 用户id | true | string | |
返回值:角色id集合:List<String>
7.根据用户id查询权限id
方法名: loadPermissionIdListByUserId
备注:
参数:userId:String
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| userId | 用户id | true | string | |
返回值:权限id集合:List<String>
8.查询所有的权限id
方法名: loadAllPermissionIdList
备注:
参数:
返回值:权限id集合:List<String>
9.根据用户id查询岗位id
方法名: loadPostIdListByUserId
备注:
参数:userId:String
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| userId | 用户id | true | string | |
返回值:岗位id集合:List<String>
10.根据用户id查询所任部门主管的部门id集合
方法名: loadDeptIdOfLeaderListByUserId
备注:查询的是指定的用户是主管的部门id集合
参数:userId:String
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| userId | 用户id | true | string | |
返回值:部门id集合:List<String>
11.获取用户的标签id集合
方法名: loadLabelIdListByUserId
备注: 返回值格式[['标签组id','标签id']]
参数:userId:String
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| userId | 用户id | true | string | |
返回值:标签id集合:List<List<String>>
12.查询所有的角色
方法名: loadAllRole
备注:
参数:
返回值:List
| 参数 | 名称 | 类型 | 备注 |
| name | 角色名称 | string | |
| id | 角色id | string | |
| status | 状态 | int | 1正常 |
13.查询所有的岗位
方法名: loadAllPost
备注:
参数:
返回值:List
| 参数 | 名称 | 类型 | 备注 |
| name | 岗位名称 | string | |
| id | 岗位id | string | |
| status | 状态 | int | 1正常2禁用 |
14.查询所有的标签组
方法名: loadAllLabelGroup
备注:
参数:
返回值:List
| 参数 | 名称 | 类型 | 备注 |
| name | 标签组名称 | string | |
| id | 标签组id | string | |
| status | 状态 | int | 1正常2禁用 |
| labelList | 标签列表 | array | |
| name | 标签名称 | string | |
| id | 标签id | string | |
15.查询部门数据
方法名: loadAllDept
备注:
参数:
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| parentDeptId | 上级部门id | false | string | 不传就是查询所有的部门 |
| tenantId | 租户id | false | string | |
返回值:List
| 参数 | 名称 | 类型 | 备注 |
| name | 部门名称 | string | |
| id | 部门id | string | |
| parentId | 上级部门id | string | |
| leaderUserIdList | 部门主管id数组 | array<string> | |
| status | 状态 | int | 1正常2禁用 |
16.查询上级部门数据
方法名: loadParentDept
备注: 从部门id查询上级部门数据;包含当前部门的数据(deptId的部门数据);注意部门的排序,第一条数据就是deptId的部门数据
参数:
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| deptId | 部门id | true | string | |
| tenantId | 租户id | false | string | |
返回值:List
| 参数 | 名称 | 类型 | 备注 |
| name | 部门名称 | string | |
| id | 部门id | string | |
| parentId | 上级部门id | string | |
| leaderUserIdList | 部门主管id数组 | array<string> | |
| status | 状态 | int | 1正常2禁用 |
17.查询下级部门数据
方法名: loadChildDept
备注: 从部门id查询下级部门数据;包含当前部门的数据(deptId的部门数据);注意部门的排序,第一条数据就是deptId的部门数据;level和maxLeven不会同时生效;deptId的部门的层级是1
参数:
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| deptId | 部门id | true | string | |
| level | 指定层级 | false | int | |
| maxLevel | 最高层级 | false | int | |
返回值:List
| 参数 | 名称 | 类型 | 备注 |
| name | 部门名称 | string | |
| id | 部门id | string | |
| parentId | 上级部门id | string | |
| leaderUserIdList | 部门主管id数组 | array<string> | |
| status | 状态 | int | 1正常2禁用 |
18.批量查询下级部门
方法名: batchLoadChildDept
备注:
参数:
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| deptIdList | 部门id数组 | true | array<string> | |
返回值:List
| 参数 | 名称 | 类型 | 备注 |
| name | 部门名称 | string | |
| id | 部门id | string | |
| parentId | 上级部门id | string | |
| leaderUserIdList | 部门主管id数组 | array<string> | |
| status | 状态 | int | 1正常2禁用 |
19.根据用户id查询用户数据
方法名: getUser
备注:
参数:
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| userId | 用户id | true | string | |
| tenantId | 租户id | false | string | |
返回值:
| 参数 | 名称 | 类型 | 备注 |
| name | 用户名称 | string | |
| id | 用户id | string | |
| parentId | 直属领导id | string | |
| email | 邮箱 | string | |
| avatarUrl | 用户头像地址 | string | |
| tenantId | 租户id | string | |
| phone | 手机号 | string | |
| deptIdList | 用户所属部门id列表 | array<string> | |
| deptName | 部门名称 | string | 展示用,如果多个部门可以逗号分割部门名称 |
| status | 状态 | int | 1正常2禁用 |
20.查询下级用户id列表
方法名: getChildUserIdList
备注:
参数:
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| userId | 用户id(直属领导id) | true | string | |
返回值:List<string>
21.批量获取用户集合
方法名: batchGetUser
备注:返回值是字典格式<用户id,用户对象>
参数:
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| userIdList | 用户id 集合 | true | array<string> | |
| tenantId | 租户id | false | string | |
返回值:用户对象格式如下
| 参数 | 名称 | 类型 | 备注 |
| name | 用户名称 | string | |
| id | 用户id | string | |
| parentId | 直属领导id | string | |
| email | 邮箱 | string | |
| avatarUrl | 用户头像地址 | string | |
| tenantId | 租户id | string | |
| phone | 手机号 | string | |
| deptIdList | 用户所属部门id列表 | array<string> | |
| deptName | 部门名称 | string | 展示用,如果多个部门可以逗号分割部门名称 |
| status | 状态 | int | 1正常2禁用 |
22.批量查询部门
方法名: getDeptList
备注:
参数:
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| deptIdList | 部门id数组 | true | array<string> | |
返回值:List
| 参数 | 名称 | 类型 | 备注 |
| name | 部门名称 | string | |
| id | 部门id | string | |
| parentId | 上级部门id | string | |
| leaderUserIdList | 部门主管id数组 | array<string> | |
| status | 状态 | int | 1正常2禁用 |
23. 搜索用户
方法名: searchUser
备注:
参数:
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| keyword | 关键词 | false | string | 支持模糊搜索:包括名字、拼音和手机号 |
| deptId | 部门id | false | string | |
返回值:List
| 参数 | 名称 | 类型 | 备注 |
| name | 用户名称 | string | |
| id | 用户id | string | |
| parentId | 直属领导id | string | |
| email | 邮箱 | string | |
| avatarUrl | 用户头像地址 | string | |
| tenantId | 租户id | string | |
| phone | 手机号 | string | |
| deptIdList | 用户所属部门id列表 | array<string> | |
| deptName | 部门名称 | string | 展示用,如果多个部门可以逗号分割部门名称 |
| status | 状态 | int | 1正常2禁用 |
24.远程拉取全部数据
方法名: loadRemoteData
备注: 全量同步数据,比如钉钉版,手动点击同步全量数据:包含部门和用户
参数:
返回值:
24. 查询自定义字段
方法名: queryUserFieldList
备注:
参数:
返回值:List
| 参数 | 名称 | 类型 | 备注 |
| name | 字段名称 | string | |
| type | 字段类型 | string | |
| required | 是否必填 | boolean | |
| props | 字段额外配置属性 | string | |
| key | 字段key | string | |
25. 查询用户的自定义字段值
方法名: queryUserFieldData
备注:
参数:
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| userId | 用户id | true | string | |
返回值:Map<string,string>,key是自定义字段的key
26. 查询租户对象
方法名: getTenant
备注:
参数:
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| tenantId | 租户id | true | string | |
返回值:List
| 参数 | 名称 | 类型 | 备注 |
| tenantId | 租户id | string | |
| name | 租户名称 | string | |
| adminId | 管理员id | string | |
| adminName | 管理员名称 | string | |
| adminPhone | 管理员手机号 | string | |
| status | 状态 | int | 1正常2禁用 |
27. 根据用户手机号查询所在的租户列表
方法名: queryUserTenantListByPhone
备注:
参数:
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| phone | 手机号 | true | string | |
返回值:List
| 参数 | 名称 | 类型 | 备注 |
| tenantId | 租户id | string | |
| name | 租户名称 | string | |
| adminId | 管理员id | string | |
| adminName | 管理员名称 | string | |
| adminPhone | 管理员手机号 | string | |
| status | 状态 | int | 1正常2禁用 |
28. 查询字典类型
方法名: queryDictTypeList
备注:
参数:
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| keywords | 关键字 | false | string | 模糊查询字段类型名称或者编码 |
| dataType | 类型 | false | string | 列表:list 树形:tree |
返回值:List
| 参数 | 名称 | 类型 | 备注 |
| name | 字典类型名称 | string | |
| code | 字典类型编码 | string | |
| dataType | 类型 | string | 列表:list 树形:tree |
| status | 状态 | int | 1正常2禁用 |
29. 查询字典
方法名: queryDictList
备注:
参数:
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| keywords | 关键字 | false | string | 模糊查询字段类型名称 |
| typeCode | 字典类型编码 | true | string | |
返回值:List
| 参数 | 名称 | 类型 | 备注 |
| name | 字典名称 | string | |
| value | 字典值 | string | |
| typeCode | 字典类型编码 | string | |
| parentValue | 上级字典值 | string | 树形字典时有效 |
| status | 状态 | int | 1正常2禁用 |
30. 发送消息
方法名: sendMsg
备注:
参数:
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| type | 消息类型 | true | string | 参考枚举:MessageTypeEnum TodoTask:待办 CopyTask:抄送 UrgeTask:催办 ExpiredTask:超时提醒 ProcessEndAlertStarter:流程结束 ProcessComment:流程评论 |
| userId | 消息接收用户id | true | string | |
| bizUniqueId | 业务唯一id | true | string | 可能是任务id 也可能是流程实例id |
| param | 消息参数 | false | string | |
| content | 消息内容 | true | string | |
| title | 消息标题 | true | string | |
| flowId | 流程定义id | false | string | |
| processInstanceId | 流程实例id | false | string | |
| startUserId | 发起人id | false | string | |
| startUserName | 发起人姓名 | false | string | |
| groupName | 分组名称 | false | string | |
| flowName | 流程名称 | false | string | |
| remark | 流程名称 | false | string | |
| currentUserId | 当前用户id | false | string | |
| currentUserTenantId | 当前用户的租户id | false | string | |
| tenantId | 租户id | true | string | |
| processTenantId | 流程租户id | true | string | |
返回值:List
31. 批量获取代理人数据
方法名: queryAgentUserMap
备注: 根据用户id列表批量获取代理人数据,返回值为map类型,key是被代理人的id,value是代理人id;实现上要注意递归查询:a代理b,b代理c,那c的代理人是a,不是b
参数:
| 参数 | 名称 | 是否必填 | 类型 | 备注 |
| userIdSet | 用户id列表 | true | array<string> | |
| tenantId | 租户id | false | string | |
返回值:Map<string,string>