Files
flow-center-front/src/api/module/flow.ts
T

308 lines
13 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Method } from "alova";
import { alovaInstance } from "@/utils/alova/alova-iview";
/**
* 流程中心用户面/管理面接口(/api/flow/**)。
* 响应 {code,msg,data} 由 alova 实例统一解包(code!=0 抛错提示)。
*/
const ROOT = "/api/flow";
function get<T = any>(url: string, params?: Record<string, any>): Method<T> {
return new Method<T>("GET", alovaInstance, url, { params });
}
// alova 的请求体是 Method 构造的第 5 个参数(instance.data),不是 config 上的键:
// 写进 config 的 body/data 都会被适配器忽略,POST 将发出空 body。
function post<T = any>(url: string, body?: any): Method<T> {
return new Method<T>("POST", alovaInstance, url, {}, body);
}
/** 状态枚举(后端 FlwEnums 口径) */
export const INSTANCE_STATUS: Record<number, string> = {
10: "审批中",
20: "已完成",
30: "已拒绝",
40: "已撤回",
};
/** 状态列 Tag 主题色(与 INSTANCE_STATUS 同码表,缺省灰) */
export const INSTANCE_STATUS_COLOR: Record<number, string> = {
10: "blue",
20: "green",
30: "red",
40: "gray",
};
export const TASK_STATUS: Record<number, string> = {
0: "待办",
1: "同意",
2: "拒绝",
3: "失效",
4: "退回",
5: "移交",
// 6/7 为轨迹留痕事件行(发起/重新提交、撤回),不是审批动作
6: "提交",
7: "撤回",
};
/** 任务结果 Tag 主题色(同 TASK_STATUS 码表,缺省灰) */
export const TASK_STATUS_COLOR: Record<number, string> = {
0: "blue",
1: "green",
2: "red",
3: "default",
4: "orange",
5: "cyan",
6: "green",
7: "orange",
};
class FlowApi {
// ==================== 用户面 ====================
/** 我的待办(appKey=按应用筛选,可空) */
todo(params: { page?: number; size?: number; appKey?: string }) {
return get(`${ROOT}/todo`, params);
}
/** 我的已办(appKey=按应用筛选,可空) */
done(params: { page?: number; size?: number; appKey?: string }) {
return get(`${ROOT}/done`, params);
}
/** 我的抄送(NOTIFY 节点落库;知会不占待办,独立页签) */
ccMy(params: { page?: number; size?: number; appKey?: string }) {
return get(`${ROOT}/cc/my`, params);
}
/** 我提交的办件 */
my(params: { status?: number; page?: number; size?: number; appKey?: string }) {
return get(`${ROOT}/my`, params);
}
/** 办件详情(提交人/办理人/本校管理员可见) */
detail(instanceId: number | string) {
return get(`${ROOT}/instance/${instanceId}`);
}
/** 任务定位办件详情(办理页 /task/:taskId 数据源) */
taskDetail(taskId: number | string) {
return get(`${ROOT}/task/${taskId}/detail`);
}
/** 同意(多出口节点必须传 edgeName=所选出口名,单出口可省) */
approve(taskId: number | string, opinion?: string, edgeName?: string) {
return post(`${ROOT}/task/${taskId}/approve`, { opinion: opinion || null, edgeName: edgeName || null });
}
/** 退回(targetNodeId 可选=缺省最近已办主线节点;opinion 可选) */
returnBack(taskId: number | string, targetNodeId?: string, opinion?: string) {
return post(`${ROOT}/task/${taskId}/returnBack`, { targetNodeId: targetNodeId || null, opinion: opinion || null });
}
/** 移交(toUserId 必填;reason 可选) */
transfer(taskId: number | string, toUserId: number, reason?: string) {
return post(`${ROOT}/task/${taskId}/transfer`, { toUserId, reason: reason || null });
}
/** 拒绝(opinion 必填) */
reject(taskId: number | string, opinion: string) {
return post(`${ROOT}/task/${taskId}/reject`, { opinion });
}
/** 撤回(提交人;仅尚无任务被办理时) */
withdraw(instanceId: number | string) {
return post(`${ROOT}/instance/${instanceId}/withdraw`);
}
/** 催办(提交人/管理员) */
urge(instanceId: number | string) {
return post(`${ROOT}/instance/${instanceId}/urge`);
}
// ==================== 用户面:流程示意图 ====================
/** 流程示意图(flowGuid=最高已发布版;instanceId=办件 def 快照版;mode=dept|user,缺省 user) */
diagram(params: { flowGuid?: string; instanceId?: number | string; mode?: string }) {
return get(`${ROOT}/diagram`, params);
}
/** 流程源码(图示页「源码」抽屉;可见性同 /diagram) */
defSource(params: { flowGuid?: string; instanceId?: number | string }) {
return get(`${ROOT}/def/source`, params);
}
// ==================== 管理面:流程定义 ====================
defList(params?: { status?: number; appKey?: string }) {
return get(`${ROOT}/admin/def/list`, params);
}
/** 应用清单("按应用筛选"下拉):本校 flw_def 已标注 ∪ 已注册回调的应用 */
defAppKeys() {
return get(`${ROOT}/admin/def/appkeys`);
}
// ==================== 管理面:应用设置(2026-10-10) ====================
/** 应用管理列表(flw_app 白名单;附带学校池静默同步,UserBase 不可达降级本地行) */
appList() {
return get(`${ROOT}/admin/app/list`);
}
/** 开关某应用是否对接流程(停用后 defSave 归属应用校验拦截新引用) */
appEnable(id: number | string, enabled: boolean) {
return post(`${ROOT}/admin/app/enable`, { id, enabled });
}
/** 应用辅助统计:appKey → 回调注册数(本校) */
appStats() {
return get(`${ROOT}/admin/app/stats`);
}
defGet(id: number | string) {
return get(`${ROOT}/admin/def/get`, { id });
}
defSave(body: { id?: number; code: string; name: string; contentJson: string; baseGuid?: string; appKey?: string; changeLog?: string }) {
return post(`${ROOT}/admin/def/save`, body);
}
/** 元数据原地编辑(2026-10-10 议题2):只改 name/appKey 不升版本;已发布亦可 */
defUpdateMeta(body: { id: number; name: string; appKey?: string }) {
return post(`${ROOT}/admin/def/updateMeta`, body);
}
defPublish(id: number | string) {
return post(`${ROOT}/admin/def/publish/${id}`);
}
defOffline(id: number | string) {
return post(`${ROOT}/admin/def/offline/${id}`);
}
/** 启用(与 defOffline 对称:仅停用版 → 已发布,重跑发布期静态校验) */
defEnable(id: number | string) {
return post(`${ROOT}/admin/def/enable/${id}`);
}
defVersions(flowGuid: string) {
return get(`${ROOT}/admin/def/versions`, { flowGuid });
}
/** 在途办件数(议题二④):flowGuid → 审批中办件数,无在途的流程线也返回 0 键 */
defInflight(flowGuids: string[]) {
return get(`${ROOT}/admin/def/inflight`, { flowGuids: flowGuids.join(",") });
}
/** 流程定义示意图(管理面:defId 任意版本,草稿可预览) */
adminDefDiagram(params: { id: number | string; mode?: string }) {
return get(`${ROOT}/admin/def/diagram`, params);
}
// ==================== 管理面:科室管理(2026-10-10,取代旧 /map/* 映射 CRUD) ====================
/** 科室列表(deptKey=自增 id 字符串 + 启用成员数;编辑器 ctx.depts 同结构) */
deptList() {
return get(`${ROOT}/admin/dept/list`);
}
deptCreate(deptName: string) {
return post(`${ROOT}/admin/dept/create`, { deptName });
}
deptRename(id: number | string, deptName: string) {
return post(`${ROOT}/admin/dept/rename`, { id, deptName });
}
deptStatus(id: number | string, enabled: boolean) {
return post(`${ROOT}/admin/dept/status`, { id, enabled });
}
deptDelete(id: number | string) {
return post(`${ROOT}/admin/dept/delete`, { id });
}
deptMembers(deptId: number | string) {
return get(`${ROOT}/admin/dept/members`, { deptId });
}
/** 批量加成员(返回新增数) */
deptMemberAdd(deptId: number | string, userIds: number[]) {
return post(`${ROOT}/admin/dept/memberAdd`, { deptId, userIds });
}
deptMemberRemove(memberId: number | string) {
return post(`${ROOT}/admin/dept/memberRemove`, { memberId });
}
/** 一键拉取教师组·预览(不落库,确认后导入) */
deptGroupPreview() {
return get(`${ROOT}/admin/dept/groupPreview`);
}
/** 一键拉取教师组·导入(source_group_id 幂等;重复拉取=刷新组名与成员集) */
deptImportGroups() {
return post(`${ROOT}/admin/dept/importGroups`);
}
/** 成员检索(UserBase byId;编辑器选人/姓名补全共用,原 /map/lookupUser 通道保留) */
mapLookupUser(userId: number) {
return get(`${ROOT}/admin/map/lookupUser`, { userId });
}
/** 选人组件数据源:学校组树(组→组内用户叶子) */
adminUserTree() {
return get(`${ROOT}/admin/user/tree`);
}
/** 选人组件数据源·教师版(仿 Notice:组树骨架 + YschClassOpenApi 教师按 GroupIds 挂组) */
adminTeacherTree() {
return get(`${ROOT}/admin/user/teacherTree`);
}
// ==================== 管理面:回调注册/日志/死信 ====================
regList() {
return get(`${ROOT}/admin/callback/regList`);
}
regStatus(id: number | string, enabled: boolean) {
return post(`${ROOT}/admin/callback/regStatus/${id}?enabled=${enabled}`);
}
regResetSecret(id: number | string) {
return post(`${ROOT}/admin/callback/resetSecret/${id}`);
}
/** 回调探测:对该注册同步推一条 flow.ping(未知事件码),返回 {success,httpStatus,elapsedMs,respSnippet,error} */
callbackProbe(id: number | string) {
return post(`${ROOT}/admin/callback/probe/${id}`);
}
callbackLogs(params: { status?: number; event?: string; instanceId?: number; page?: number; size?: number }) {
return get(`${ROOT}/admin/callback/logs`, params);
}
callbackDead(params: { page?: number; size?: number }) {
return get(`${ROOT}/admin/callback/dead`, params);
}
/** 挂起列表(待推且重试达阈值) */
callbackHung(params: { page?: number; size?: number }) {
return get(`${ROOT}/admin/callback/hung`, params);
}
/** 手工标记死信(标记后可 repush 复活) */
callbackMarkDead(id: number | string) {
return post(`${ROOT}/admin/callback/markDead/${id}`);
}
callbackRepush(ids: number[]) {
return post(`${ROOT}/admin/callback/repush`, ids);
}
/** 对接健康度体检(2026-10-15 P2):每应用一行六项检查 + 综合评分,零新增表 */
callbackHealth() {
return get(`${ROOT}/admin/callback/health`);
}
// ==================== 管理面:条件路由注册 / 重跑 ====================
/** 判断服务注册列表(flw_router 全局表;编辑器下拉与管理页共用) */
routerList() {
return get(`${ROOT}/admin/router/list`);
}
routerSave(body: {
id?: number;
routerKey: string;
name: string;
serviceKey: string;
path: string;
basePath?: string;
}) {
return post(`${ROOT}/admin/router/save`, body);
}
/** 启用/停用注册(停用后发布校验拦截新引用) */
routerStatus(id: number | string, enabled: boolean) {
return post(`${ROOT}/admin/router/status/${id}?enabled=${enabled}`);
}
/**
* 重跑路由(判断失败挂起的恢复入口:重新调判断,成功即按出口续走)。
* useLatestDef=true(F5-4 僵尸逃生门):按该流程当前已发布最高版本重跑并刷新办件定义快照。
*/
instanceReroute(instanceId: number | string, useLatestDef?: boolean) {
const suffix = useLatestDef ? "?useLatestDef=true" : "";
return post(`${ROOT}/admin/instance/${instanceId}/reroute${suffix}`);
}
/** 表达式调试求值(2026-10-10:与运行时同一求值核心;不落库不走流程) */
routerEval(body: { expression: string; variablesJson?: string }) {
return post(`${ROOT}/admin/router/eval`, body);
}
// ==================== 管理面:办件查询 ====================
adminInstances(params: { status?: number; keyword?: string; page?: number; size?: number }) {
return get(`${ROOT}/admin/instance/page`, params);
}
/**
* 发起时指派预览(F6 共享选择器数据源;与 oapi /oapi/flow/apply/preview 同形:
* {flowGuid, defVersion, nodes:[{nodeId,nodeName,countersign,selection,candidates}]})。
* 纯预置:后端 /api 代理端点属 F6 正式接入批次,接线时同批点亮(FlowAssignSelector 当前为备用组件)。
*/
applyPreview(flowGuid: string) {
return get(`${ROOT}/apply/preview`, { flowGuid });
}
}
export const flowApi = new FlowApi();