@leadal/flowstream-ui-plus 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,612 @@
1
+ # FlowStream Vue3 前端组件接入指南
2
+
3
+ FlowStream 前端运行时组件库的 npm 包名统一为 **`@leadal/flowstream-ui-plus`**。组件库基于 Vue 3 和 Element Plus,封装工作项列表、流程操作、任务发送、任务跳转、流程图及办理轨迹等能力。
4
+
5
+ 组件库只公开 **5 个主组件 + 1 个子组件**。流程设计与 Editor 由工作流程引擎内部提供,不在本组件库中导出。
6
+
7
+ > 目录
8
+ >
9
+ > 1. [安装与配置](#1-安装与配置)
10
+ > 2. [组件定义](#2-组件定义)
11
+ > 1. [ui-flow-buttons](#21-ui-flow-buttons)
12
+ > 2. [ui-flow-button](#22-ui-flow-button)
13
+ > 3. [ui-flow-grid](#23-ui-flow-grid)
14
+ > 4. [ui-flow-send](#24-ui-flow-send)
15
+ > 5. [ui-flow-jump](#25-ui-flow-jump)
16
+ > 6. [ui-flow-diagram](#26-ui-flow-diagram)
17
+ > 3. [请求与错误处理](#3-请求与错误处理)
18
+
19
+ ---
20
+
21
+ ## 1. 安装与配置
22
+
23
+ ### 1.1 环境要求
24
+
25
+ | 项目 | 要求 | 说明 |
26
+ | ------------ | -------- | --------------------------------------- |
27
+ | Node.js | `>= 18` | 组件库构建要求 |
28
+ | pnpm | `>= 8` | 推荐包管理器 |
29
+ | Vue | `>= 3.4` | peer dependency |
30
+ | Element Plus | `>= 2.8` | peer dependency,宿主工程负责安装和注册 |
31
+
32
+ ### 1.2 安装
33
+
34
+ ```bash
35
+ pnpm add @leadal/flowstream-ui-plus
36
+
37
+ # 或使用 npm
38
+ npm install @leadal/flowstream-ui-plus
39
+ ```
40
+
41
+ ### 1.3 全量注册
42
+
43
+ ```ts
44
+ import { createApp } from 'vue'
45
+ import FlowstreamUIPlus from '@leadal/flowstream-ui-plus'
46
+ import '@leadal/flowstream-ui-plus/style.css'
47
+ import App from './App.vue'
48
+
49
+ const app = createApp(App)
50
+
51
+ app.use(FlowstreamUIPlus, {
52
+ baseURL: import.meta.env.VITE_FLOWSTREAM_ORIGIN,
53
+ timeout: 60_000,
54
+ getToken: () => localStorage.getItem('access_token') || undefined,
55
+ })
56
+
57
+ app.mount('#app')
58
+ ```
59
+
60
+ 全量注册后,可直接使用 `ui-flow-buttons`、`ui-flow-button`、`ui-flow-grid`、`ui-flow-send`、`ui-flow-jump` 和 `ui-flow-diagram` 全局标签。
61
+
62
+ ### 1.4 按需引入
63
+
64
+ ```ts
65
+ import {
66
+ FlowButton,
67
+ FlowButtons,
68
+ FlowDiagram,
69
+ FlowGrid,
70
+ FlowJump,
71
+ FlowSend,
72
+ configureWorkflow,
73
+ } from '@leadal/flowstream-ui-plus'
74
+ import '@leadal/flowstream-ui-plus/style.css'
75
+
76
+ configureWorkflow({
77
+ baseURL: import.meta.env.VITE_FLOWSTREAM_ORIGIN,
78
+ timeout: 60000,
79
+ getToken: () => localStorage.getItem('access_token') || undefined,
80
+ })
81
+ ```
82
+
83
+ ### 1.5 请求前缀
84
+
85
+ `baseURL` 会作为所有 FlowStream 接口的统一前缀,末尾 `/` 会被移除。
86
+
87
+ | 配置 | 最终行为 |
88
+ | ------------------------- | ---------------------------------------------------------- |
89
+ | 不配置 | 生产构建不自动添加前缀;开发/测试源码模式默认使用 `/api` |
90
+ | `/api` | 测试或本地代理环境显式使用 `/api` 前缀 |
91
+ | `http://127.0.0.1:19090` | 直连服务,接口形如 `http://127.0.0.1:19090/flowstream/...` |
92
+ | `https://example.com/api` | 使用业务网关的 `/api` 前缀 |
93
+
94
+ 本地代理使用 `/api` 时,应将 `/api` 转发到 FlowStream 服务,并按网关实际规则决定是否移除 `/api`。
95
+
96
+ ---
97
+
98
+ ## 2. 组件定义
99
+
100
+ | 组件名 | 全局标签 | 说明 |
101
+ | --------------- | ----------------- | ----------------------------------------------------- |
102
+ | `UiFlowButtons` | `ui-flow-buttons` | 根据工作项加载并执行流程操作 |
103
+ | `UiFlowButton` | `ui-flow-button` | 单个流程按钮,是 `FlowButtons` 的子组件,也可单独使用 |
104
+ | `UiFlowGrid` | `ui-flow-grid` | `todo` / `done` / `draft` 统一工作项列表 |
105
+ | `UiFlowSend` | `ui-flow-send` | 完整任务发送弹窗 |
106
+ | `UiFlowJump` | `ui-flow-jump` | 流程任务跳转能力 |
107
+ | `UiFlowDiagram` | `ui-flow-diagram` | BPMN 流程图、运行状态和办理轨迹 |
108
+
109
+ 除组件外,包入口还导出 `configureWorkflow`、请求实例 `workflowHttp`、类型定义以及流程 API 方法(例如 `startDraft`、`startNodes`)。
110
+
111
+ > `Editor`、内部基础表格、轨迹表格和图标组件不是公共导出,不要从 `@leadal/flowstream-ui-plus` 引入。
112
+
113
+ ---
114
+
115
+ ### 2.1 ui-flow-buttons
116
+
117
+ `ui-flow-buttons` 根据 `workId` 调用操作定义接口加载当前工作项可用按钮。可由组件独立完成的动作会弹出确认框并请求后端;需要业务页面参与的动作通过 `execute-action` 交给宿主处理。
118
+
119
+ | action | 处理方式 |
120
+ | --------------------------------------------------- | --------------------------------------------- |
121
+ | `revocation` / `taskWithdraw` | 确认后执行撤回 |
122
+ | `taskRecyle` | 确认后执行收回;后端接口保留历史拼写 `recyle` |
123
+ | `hang` | 确认后挂起流程实例 |
124
+ | `restore` | 确认后恢复流程 |
125
+ | `terminate` | 确认后终止流程 |
126
+ | `taskComplete` | 确认后办毕 |
127
+ | `taskRollback` | 确认后退回 |
128
+ | `save` / `start` / `taskSend` / `jump` / `taskJump` | 触发 `execute-action`,由宿主处理 |
129
+ | 其他未内置动作 | 触发 `execute-action`,由宿主处理 |
130
+
131
+ #### 1) 属性定义(Properties)
132
+
133
+ | 参数 | 说明 | 类型 | 必填 | 默认值 |
134
+ | ------------------- | ----------------------------------- | -------------------------------------- | ---- | ------ |
135
+ | `workId` | 当前工作项 ID,用于加载和执行操作 | `string` | 是 | — |
136
+ | `processInstanceId` | 流程实例 ID,挂起等动作会使用 | `string` | 否 | — |
137
+ | `beforeAction` | 动作执行前钩子;返回 `false` 可中断 | `(action, context) => boolean \| void` | 否 | — |
138
+ | `afterAction` | 内置动作成功后的函数型钩子 | `(action, result) => void` | 否 | — |
139
+
140
+ `beforeAction` 的 `context` 包含 `action`、`workId` 和 `processInstanceIds`。
141
+
142
+ #### 2) 事件定义(Events)
143
+
144
+ | 事件名称 | 回调参数 | 说明 |
145
+ | ---------------- | ------------------------------------- | ------------------------------------------------------ |
146
+ | `execute-action` | `action: string` | 需要宿主处理的动作;发送操作对应 `taskSend` |
147
+ | `after-action` | `action: string, result: ApiResponse` | 内置动作成功后触发,可用于成功提示、返回列表和刷新数据 |
148
+ | `error` | `error: unknown` | 内置操作失败时触发;用户取消确认框不会触发 |
149
+
150
+ #### 3) 方法定义(Methods)
151
+
152
+ | 方法 | 参数 | 返回 | 说明 |
153
+ | ----------------------- | -------------------- | ------------------------------- | ------------------------ |
154
+ | `getAvailableActions()` | — | `Promise<WorkflowActionItem[]>` | 重新加载可用按钮 |
155
+ | `executeAction(button)` | `WorkflowActionItem` | `Promise<void>` | 按按钮定义执行或分发动作 |
156
+
157
+ #### 4) 插槽定义(Slots)
158
+
159
+ | 插槽 | 插槽参数 | 说明 |
160
+ | --------- | ------------ | ---------------------------- |
161
+ | `prefix` | `{ action }` | 每个流程按钮前的内容 |
162
+ | `default` | `{ action }` | 每个流程按钮区域的自定义内容 |
163
+ | `suffix` | `{ action }` | 每个流程按钮后的内容 |
164
+
165
+ #### 5) 组件示例
166
+
167
+ ```vue
168
+ <ui-flow-buttons
169
+ :work-id="task.workId"
170
+ :process-instance-id="task.processInstanceId"
171
+ :before-action="validateBeforeAction"
172
+ @execute-action="handleFlowAction"
173
+ @after-action="handleAfterAction"
174
+ @error="handleError"
175
+ />
176
+ ```
177
+
178
+ 任务“办毕”等内置操作成功后,应在 `after-action` 中提示并刷新列表:
179
+
180
+ ```ts
181
+ function handleAfterAction(action: string, result: unknown) {
182
+ ElMessage.success('操作成功')
183
+ gridRef.value?.loadTableData()
184
+ }
185
+ ```
186
+
187
+ ### 2.2 ui-flow-button
188
+
189
+ `ui-flow-button` 是按钮组内部使用的单按钮子组件,也可以单独导入。
190
+
191
+ #### 1) 属性定义(Properties)
192
+
193
+ | 参数 | 说明 | 类型 | 默认值 |
194
+ | ------- | -------------------------------- | -------- | ------ |
195
+ | `type` | 预设动作类型,决定默认文字和图标 | `string` | — |
196
+ | `label` | 覆盖预设按钮文字 | `string` | — |
197
+
198
+ 内置类型包括 `save`、`start`、`revocation`、`taskWithdraw`、`taskRecyle`、`hang`、`restore`、`terminate`、`jump`、`taskJump`、`taskComplete`、`taskSend` 和 `taskRollback`。
199
+
200
+ #### 2) 事件定义(Events)
201
+
202
+ | 类型 | 名称 | 参数 | 说明 |
203
+ | ----- | ------- | --------------- | ---------------------- |
204
+ | Event | `click` | `type?: string` | 点击后返回对应动作类型 |
205
+
206
+ #### 3) 插槽定义(Slots)
207
+
208
+ | 插槽 | 参数 | 说明 |
209
+ | --------- | ---- | ---------------------------------------- |
210
+ | `default` | — | 当 `type` 不匹配预设按钮时显示自定义内容 |
211
+
212
+ #### 4) 组件示例
213
+
214
+ ```vue
215
+ <ui-flow-button type="save" label="保存草稿" @click="saveForm" />
216
+ ```
217
+
218
+ ---
219
+
220
+ ### 2.3 ui-flow-grid
221
+
222
+ `ui-flow-grid` 是待办、已办和草稿统一列表组件,内部完成接口请求、分页、状态显示和行操作。`type` 必填。
223
+
224
+ 内置列
225
+
226
+ - todo / done:业务标题 `businessName`、当前环节 `activityName`、发送人 `assigneesNames`、发送时间 `startTime`。
227
+ - draft:业务标题 `title`、当前环节 `currentActivity`、创建人 `createUserName`、创建时间 `createdTime`。
228
+ - done 根据 `stateName` 显示状态,draft 根据 `stateLabel` 显示状态。
229
+
230
+ > 发送人列必须读取接口字段 **`assigneesNames`**,不使用 `assignees` 或 `previousAssignee`。
231
+
232
+ done 状态映射:
233
+
234
+ | stateName | 显示文本 |
235
+ | ------------ | -------- |
236
+ | `executing` | 审批中 |
237
+ | `completed` | 已完成 |
238
+ | `deleted` | 已删除 |
239
+ | `canceled` | 已取消 |
240
+ | `withdrawed` | 已撤回 |
241
+ | `recyled` | 已回收 |
242
+ | `rollbacked` | 已退回 |
243
+ | `jumped` | 已跳转 |
244
+
245
+ ####
246
+
247
+ #### 1) 属性定义(Properties)
248
+
249
+ | 参数 | 说明 | 类型 | 可选值 | 默认值 |
250
+ | ------------- | ------------------------------------------------------------ | -------- | ------------------------- | ------ |
251
+ | `type` | 列表类型 | `string` | `todo` / `done` / `draft` | — |
252
+ | `dealUserId` | 当前用户 ID;todo/done 查询使用 assignee,draft 查询使用 createUserId | `string` | — | `''` |
253
+ | `appId` | 草稿查询的应用 ID | `string` | — | `''` |
254
+ | `appModuleId` | 草稿查询的应用模块 ID | `string` | — | `''` |
255
+
256
+ #### 2) 事件定义(Events)
257
+
258
+ | 事件名称 | 回调参数 | 说明 |
259
+ | ----------- | ---------------------- | ---------------------- |
260
+ | `on-handle` | `{ action, workData }` | 行办理、查看或新建草稿 |
261
+ | `error` | `error: unknown` | 列表加载失败 |
262
+
263
+ `action` 规则:todo 办理为 `view`,done 查看为 `handle`,draft 查看为 `view`,调用 `create(flow)` 新建草稿为 `create`。
264
+
265
+ todo/done 的 `workData` 会统一保留并补齐 `workId`、`processDefinitionId`、`processInstanceId`、`activityId` 和 `activityName`。
266
+
267
+ #### 3) 方法定义(Methods)
268
+
269
+ | 名称 | 类型 | 说明 |
270
+ | ----------------- | -------- | --------------------------------------------------- |
271
+ | `loadTableData()` | Method | 按当前 type、用户和页码重新加载数据 |
272
+ | `create(flow)` | Method | 生成默认业务标题并触发 `on-handle` 的 `create` 动作 |
273
+ | `data` | Ref | 当前列表数据 |
274
+ | `loading` | Ref | 加载状态 |
275
+ | `pageConfig` | Reactive | `{ currentPage, pageSize, total }` |
276
+
277
+ #### 4) 组件示例
278
+
279
+ ```vue
280
+ <script setup lang="ts">
281
+ import { ref } from 'vue'
282
+ import { FlowGrid } from '@leadal/flowstream-ui-plus'
283
+
284
+ const gridRef = ref<InstanceType<typeof FlowGrid>>()
285
+
286
+ function handleWork({ action, workData }: {
287
+ action: 'view' | 'handle' | 'create'
288
+ workData: Record<string, unknown>
289
+ }) {
290
+ console.log(action, workData)
291
+ }
292
+ </script>
293
+
294
+ <template>
295
+ <div class="flow-grid-page">
296
+ <ui-flow-grid
297
+ ref="gridRef"
298
+ type="todo"
299
+ :deal-user-id="currentUserId"
300
+ @on-handle="handleWork"
301
+ @error="handleError"
302
+ />
303
+ </div>
304
+ </template>
305
+
306
+ <style scoped>
307
+ .flow-grid-page {
308
+ width: 100%;
309
+ height: 100%;
310
+ min-height: 500px;
311
+ box-sizing: border-box;
312
+ }
313
+ </style>
314
+ ```
315
+
316
+ ---
317
+
318
+ ### 2.4 ui-flow-send
319
+
320
+ `ui-flow-send` 是完整的任务发送弹窗,不只是一个“发送”按钮。组件内置以下交互:
321
+
322
+ - 根据当前流程定义、节点、工作项和变量计算下一环节;
323
+ - 按下一环节加载候选办理人,支持列表和懒加载树;
324
+ - 选择各下一环节的办理人;
325
+ - 新增、删除和转换流程变量,并重新计算下一环节;
326
+ - 填写审批意见;
327
+ - 确认后调用任务发送接口,成功后关闭弹窗并提示“发送成功”。
328
+
329
+ #### 1) 属性定义(Properties)
330
+
331
+ | 参数 | 说明 | 类型 | 必填 | 默认值 |
332
+ | --------------------- | ---------------------------------------------------- | ------------------------- | ---- | ---------- |
333
+ | `modelValue` | 弹窗可见状态,使用 `v-model` | `boolean` | 否 | `false` |
334
+ | `processDefinitionId` | 流程定义 ID | `string \| number` | 是 | — |
335
+ | `activity` | 当前节点,至少包含 `activityId`,可带 `activityName` | `object` | 是 | — |
336
+ | `workId` | 当前工作项 ID | `string \| number` | 是 | — |
337
+ | `processInstanceId` | 流程实例 ID | `string \| number` | 否 | `''` |
338
+ | `variables` | 当前业务流程变量 | `Record<string, unknown>` | 否 | `{}` |
339
+ | `dealUser` | 当前用户,可传 `id` 或 `userId` | `object` | 否 | `{}` |
340
+ | `bpmnXml` | BPMN XML;用于辅助判断下一节点是单人还是多人办理 | `string` | 否 | `''` |
341
+ | `showTrigger` | 是否显示组件自身的发送按钮 | `boolean` | 否 | `true` |
342
+ | `dialogTitle` | 弹窗标题 | `string` | 否 | `'发送'` |
343
+ | `dialogWidth` | 弹窗宽度 | `string` | 否 | `'1200px'` |
344
+ | `defaultOpinion` | 每次打开弹窗时的默认意见 | `string` | 否 | `''` |
345
+
346
+ #### 2) 事件定义(Events)
347
+
348
+ | 事件名称 | 回调参数 | 说明 |
349
+ | --------------------- | --------------------- | -------------------------------------------------- |
350
+ | `update:modelValue` | `visible: boolean` | `v-model` 更新 |
351
+ | `click` | — | 点击组件自身发送按钮时触发,随后组件会自行打开弹窗 |
352
+ | `open` | — | 弹窗开始打开并解析下一环节 |
353
+ | `close` | — | 弹窗完成关闭 |
354
+ | `next-nodes-resolved` | `nodes: FlowNode[]` | 下一环节解析成功 |
355
+ | `before-send` | `data` | 请求发送前触发,参数是即将提交的数据 |
356
+ | `after-send` | `result: ApiResponse` | 发送成功后触发 |
357
+ | `error` | `error: unknown` | 下一环节、候选人或发送请求失败 |
358
+
359
+ #### 3) 方法定义(Methods)
360
+
361
+ | 名称 | 类型 | 说明 |
362
+ | ------------------------- | ------ | -------------------------------------------------------- |
363
+ | `open()` | Method | 打开弹窗、重置意见与变量、解析下一环节 |
364
+ | `close()` | Method | 关闭弹窗 |
365
+ | `getNextNode(variables?)` | Method | 根据变量重新解析下一环节 |
366
+ | `assembleData()` | Method | 组装 `{ workId, flowNodeAssignees, variables, opinion }` |
367
+ | `send(formData?)` | Method | 提交发送;不传参数时使用 `assembleData()` |
368
+ | `visible` | Ref | 内部弹窗状态 |
369
+ | `loading` | Ref | 发送状态 |
370
+ | `nodeLoading` | Ref | 下一环节计算状态 |
371
+ | `nodeResolved` | Ref | 下一环节是否已完成计算 |
372
+ | `nextNodes` | Ref | 下一环节列表 |
373
+
374
+ #### 4) 组件示例
375
+
376
+ 与 `ui-flow-buttons` 配合时,隐藏 FlowSend 自身按钮,并通过 `v-model` 打开完整发送弹窗:
377
+
378
+ ```vue
379
+ <script setup lang="ts">
380
+ import { ref } from 'vue'
381
+ import { FlowButtons, FlowSend } from '@leadal/flowstream-ui-plus'
382
+
383
+ const sendVisible = ref(false)
384
+
385
+ function handleFlowAction(action: string) {
386
+ if (action === 'taskSend') sendVisible.value = true
387
+ }
388
+
389
+ function handleAfterSend() {
390
+ sendVisible.value = false
391
+ gridRef.value?.loadTableData()
392
+ }
393
+ </script>
394
+
395
+ <template>
396
+ <ui-flow-buttons
397
+ :work-id="task.workId"
398
+ :process-instance-id="task.processInstanceId"
399
+ @execute-action="handleFlowAction"
400
+ />
401
+
402
+ <ui-flow-send
403
+ v-model="sendVisible"
404
+ :process-definition-id="task.processDefinitionId"
405
+ :process-instance-id="task.processInstanceId"
406
+ :activity="{
407
+ activityId: task.activityId,
408
+ activityName: task.activityName,
409
+ }"
410
+ :work-id="task.workId"
411
+ :deal-user="currentUser"
412
+ :variables="variables"
413
+ :show-trigger="false"
414
+ default-opinion="同意"
415
+ @after-send="handleAfterSend"
416
+ @error="handleError"
417
+ />
418
+ </template>
419
+ ```
420
+
421
+ 也可以保留默认 `showTrigger=true`,直接点击 FlowSend 自身按钮打开弹窗。推荐使用 `v-model` 控制弹窗;需要命令式调用时可使用 `sendRef.value?.open()`。
422
+
423
+ ---
424
+
425
+ ### 2.5 ui-flow-jump
426
+
427
+ `ui-flow-jump` 提供跳转按钮、内置节点/办理人选择弹窗和跳转接口封装。选择开始节点后,组件通过办理人接口懒加载组织树;如果节点没有返回办理人,会回填 `dealUser`。跳转不提供变量编辑,请求固定提交 `variables: {}`。
428
+
429
+ #### 1) 属性定义(Properties)
430
+
431
+ | 参数 | 说明 | 类型 | 必填 |
432
+ | --------------------- | ------------------------------------- | ------------------ | ------------ |
433
+ | `processDefinitionId` | 流程定义 ID | `string \| number` | 是 |
434
+ | `workId` | 当前待办工作项 ID | `string \| number` | 确认跳转时是 |
435
+ | `processInstanceId` | 流程实例 ID(预留上下文) | `string \| number` | 否 |
436
+ | `dealUser` | 当前用户,支持 `{ id, userId, name }` | `object` | 否 |
437
+ | `modelValue` | 弹窗显示状态,支持 `v-model` | `boolean` | 否 |
438
+ | `showTrigger` | 是否显示组件自带跳转按钮,默认 `true` | `boolean` | 否 |
439
+ | `dialogTitle` | 弹窗标题,默认“跳转” | `string` | 否 |
440
+ | `dialogWidth` | 弹窗宽度,默认 `960px` | `string` | 否 |
441
+
442
+ #### 2) 事件定义(Events)
443
+
444
+ | 事件名称 | 回调参数 | 说明 |
445
+ | ------------------- | --------- | ------------------------------ |
446
+ | `update:modelValue` | `visible` | 弹窗显示状态变化 |
447
+ | `click` | — | 点击跳转按钮 |
448
+ | `open` | — | 弹窗打开 |
449
+ | `close` | — | 弹窗关闭 |
450
+ | `before-jump` | `data` | 提交跳转前 |
451
+ | `after-jump` | `result` | 跳转成功后 |
452
+ | `error` | `error` | 加载节点、办理人或提交跳转失败 |
453
+
454
+ #### 3) 方法定义(Methods)
455
+
456
+ | 名称 | 类型 | 说明 |
457
+ | ---------------------------------------- | ------ | ------------------------------ |
458
+ | `open()` / `close()` | Method | 打开或关闭内置弹窗 |
459
+ | `getStartNodes()` | Method | 加载可跳转用户任务节点 |
460
+ | `assembleData(targetNode?, assigneeId?)` | Method | 组装跳转数据,变量固定为空对象 |
461
+ | `jump(formData?)` | Method | 执行跳转 |
462
+ | `loading` | Ref | 跳转请求状态 |
463
+ | `startNodeList` | Ref | 可跳转节点列表 |
464
+
465
+ #### 4) 组件示例
466
+
467
+ ```vue
468
+ <script setup lang="ts">
469
+ import { ref } from 'vue'
470
+ import { FlowJump } from '@leadal/flowstream-ui-plus'
471
+
472
+ const jumpVisible = ref(false)
473
+ </script>
474
+
475
+ <template>
476
+ <ui-flow-jump
477
+ v-model="jumpVisible"
478
+ :process-definition-id="task.processDefinitionId"
479
+ :process-instance-id="task.processInstanceId"
480
+ :work-id="task.workId"
481
+ :deal-user="currentUser"
482
+ :show-trigger="false"
483
+ @before-jump="handleBeforeJump"
484
+ @after-jump="handleAfterJump"
485
+ @error="handleError"
486
+ />
487
+ </template>
488
+ ```
489
+
490
+ 保留默认 `showTrigger=true` 时,点击组件自身按钮即可打开弹窗。与 `ui-flow-buttons` 配合时,将其设为 `false`,在按钮组触发 `taskJump` 或 `jump` 后把 `jumpVisible` 设为 `true`。
491
+
492
+ ---
493
+
494
+ ### 2.6 ui-flow-diagram
495
+
496
+ `ui-flow-diagram` 基于 bpmn-js 渲染 BPMN XML,同时查询运行节点状态和办理轨迹。父容器必须有明确高度,否则流程图可能看起来是一片空白。
497
+
498
+ #### 1) 属性定义(Properties)
499
+
500
+ | 参数 | 说明 | 类型 | 必填 |
501
+ | --------------------- | ----------------------------------- | -------- | ---- |
502
+ | `processDefinitionId` | 流程定义 ID,用于下载 BPMN XML | `string` | 是 |
503
+ | `processInstanceId` | 流程实例 ID,用于查询运行状态和轨迹 | `string` | 是 |
504
+
505
+ #### 2) 事件定义(Events)
506
+
507
+ | 事件名称 | 回调参数 | 说明 |
508
+ | -------- | ---------------- | -------------------------------------- |
509
+ | `loaded` | — | BPMN、运行状态和轨迹全部加载并渲染完成 |
510
+ | `error` | `error: unknown` | 任一加载或渲染步骤失败 |
511
+
512
+ #### 3) 方法定义(Methods)
513
+
514
+ | 名称 | 类型 | 说明 |
515
+ | --------------- | ---------- | --------------------------------- |
516
+ | `refresh()` | Method | 重新加载 BPMN、运行状态和办理轨迹 |
517
+ | `viewer` | ShallowRef | bpmn-js Viewer 实例 |
518
+ | `trackData` | Ref | 办理轨迹数据 |
519
+ | `isTrackHidden` | Ref | 轨迹区域是否折叠 |
520
+
521
+ #### 4) 节点颜色
522
+
523
+ | 状态 | 颜色 | 说明 |
524
+ | ----------------------- | --------- | ---------------- |
525
+ | 当前环节 `executing` | `#ffd37e` | 正在办理 |
526
+ | 已办理节点 / StartEvent | `#98e5b5` | 已办理或开始节点 |
527
+ | EndEvent | `#f14b12` | 结束节点 |
528
+ | 其余 Task | `#eee` | 未办理节点 |
529
+
530
+ #### 5) 组件示例
531
+
532
+ ```vue
533
+ <script setup lang="ts">
534
+ import { ref } from 'vue'
535
+ import { FlowDiagram } from '@leadal/flowstream-ui-plus'
536
+
537
+ const diagramRef = ref<InstanceType<typeof FlowDiagram>>()
538
+ </script>
539
+
540
+ <template>
541
+ <div class="diagram-container">
542
+ <ui-flow-diagram
543
+ ref="diagramRef"
544
+ :process-definition-id="task.processDefinitionId"
545
+ :process-instance-id="task.processInstanceId"
546
+ @loaded="handleDiagramLoaded"
547
+ @error="handleError"
548
+ />
549
+ </div>
550
+ </template>
551
+
552
+ <style scoped>
553
+ .diagram-container {
554
+ height: 700px;
555
+ }
556
+ </style>
557
+ ```
558
+
559
+ 任务流转后可调用 `diagramRef.value?.refresh()` 刷新节点颜色和办理轨迹。
560
+
561
+ ---
562
+
563
+ ## 3. 请求与错误处理
564
+
565
+ ### 3.1 成功响应
566
+
567
+ 组件将服务端 `code` 为 `0` 或 `200` 的响应视为成功。其他 code 会被转换为 `Error`,错误信息优先读取 `msg`,其次读取 `message`。
568
+
569
+ ### 3.2 认证
570
+
571
+ 通过全量注册参数或 `configureWorkflow()` 设置 `getToken`。返回非空 token 时,请求头会写入:
572
+
573
+ ```http
574
+ Authorization: <token>
575
+ ```
576
+
577
+ ### 3.3 常见排查
578
+
579
+ | 现象 | 优先检查 |
580
+ | -------------------------------- | ------------------------------------------------------------ |
581
+ | 请求出现 `Cannot POST /api/...` | 本地代理是否配置、是否需要移除 `/api`,以及 `baseURL` 是否只在测试环境设为 `/api` |
582
+ | 点击发送没有反应 | `FlowButtons` 是否监听 `execute-action`,`taskSend` 时是否把 FlowSend 的 `v-model` 设为 `true` |
583
+ | 提示缺少流程定义或节点信息 | Grid 行数据是否包含 `processDefinitionId`、`processInstanceId`、`activityId`、`workId` |
584
+ | `sendRef.open is not a function` | 是否引用了当前 Vue3 包的完整 FlowSend;推荐改用 `v-model` 打开 |
585
+ | 办毕成功后页面无反馈 | 是否监听 `ui-flow-buttons` 的 `after-action` 并提示、刷新列表 |
586
+ | 流程图空白 | 父容器是否有明确高度,流程定义 ID、流程实例 ID 和 BPMN 下载接口是否正确 |
587
+ | 发送人显示错误 | Grid 列必须使用 `assigneesNames`,不是 `assignees` |
588
+
589
+ ### 3.4 任务发送请求结构
590
+
591
+ `ui-flow-send` 最终向 `/flowstream/server/task/event/send` 提交:
592
+
593
+ ```json
594
+ {
595
+ "workId": "工作项ID",
596
+ "flowNodeAssignees": [
597
+ {
598
+ "activityId": "下一环节ID",
599
+ "assignees": [
600
+ {
601
+ "name": "用户ID",
602
+ "userId": "用户ID"
603
+ }
604
+ ]
605
+ }
606
+ ],
607
+ "variables": {},
608
+ "opinion": "同意"
609
+ }
610
+ ```
611
+
612
+ 发送必须使用当前有效工作项的 `workId`。若服务端返回 `the current work is null!`,应重新查询当前用户待办,并使用最新工作项 ID,不能重复发送已流转或已失效的工作项。