diff --git a/packages/flow-approval-presenter/CHANGELOG.md b/packages/flow-approval-presenter/CHANGELOG.md index 4d1114a..ebd3139 100644 --- a/packages/flow-approval-presenter/CHANGELOG.md +++ b/packages/flow-approval-presenter/CHANGELOG.md @@ -1,5 +1,12 @@ # @coding-flow/flow-approval-presenter +## 0.1.9 + +### Patch Changes + +- @coding-flow/flow-core@0.1.9 +- @coding-flow/flow-types@0.1.9 + ## 0.1.8 ### Patch Changes diff --git a/packages/flow-approval-presenter/package.json b/packages/flow-approval-presenter/package.json index cd407fe..775d976 100644 --- a/packages/flow-approval-presenter/package.json +++ b/packages/flow-approval-presenter/package.json @@ -1,6 +1,6 @@ { "name": "@coding-flow/flow-approval-presenter", - "version": "0.1.8", + "version": "0.1.9", "description": "flow-engine approval presenter framework ", "type": "module", "sideEffects": [ diff --git a/packages/flow-core/CHANGELOG.md b/packages/flow-core/CHANGELOG.md index 81ab23e..b66288a 100644 --- a/packages/flow-core/CHANGELOG.md +++ b/packages/flow-core/CHANGELOG.md @@ -1,5 +1,7 @@ # @coding-flow/flow-core +## 0.1.9 + ## 0.1.8 ## 0.1.7 diff --git a/packages/flow-core/package.json b/packages/flow-core/package.json index 002b736..ff18191 100644 --- a/packages/flow-core/package.json +++ b/packages/flow-core/package.json @@ -1,6 +1,6 @@ { "name": "@coding-flow/flow-core", - "version": "0.1.8", + "version": "0.1.9", "description": "flow-engine core lib framework ", "type": "module", "sideEffects": [ diff --git a/packages/flow-design/CHANGELOG.md b/packages/flow-design/CHANGELOG.md index 0c19c20..4cf041b 100644 --- a/packages/flow-design/CHANGELOG.md +++ b/packages/flow-design/CHANGELOG.md @@ -1,5 +1,14 @@ # @coding-flow/flow-design +## 0.1.9 + +### Patch Changes + +- @coding-flow/flow-core@0.1.9 +- @coding-flow/flow-icons@0.1.9 +- @coding-flow/flow-pc-ui@0.1.9 +- @coding-flow/flow-types@0.1.9 + ## 0.1.8 ### Patch Changes diff --git a/packages/flow-design/package.json b/packages/flow-design/package.json index 0cfa88f..fa6737f 100644 --- a/packages/flow-design/package.json +++ b/packages/flow-design/package.json @@ -1,6 +1,6 @@ { "name": "@coding-flow/flow-design", - "version": "0.1.8", + "version": "0.1.9", "description": "flow-engine design components ", "type": "module", "sideEffects": [ diff --git a/packages/flow-icons/CHANGELOG.md b/packages/flow-icons/CHANGELOG.md index 6eb2ccd..e2ecb35 100644 --- a/packages/flow-icons/CHANGELOG.md +++ b/packages/flow-icons/CHANGELOG.md @@ -1,5 +1,11 @@ # @coding-flow/flow-icons +## 0.1.9 + +### Patch Changes + +- @coding-flow/flow-core@0.1.9 + ## 0.1.8 ### Patch Changes diff --git a/packages/flow-icons/package.json b/packages/flow-icons/package.json index 81dfb5b..0f5dbe2 100644 --- a/packages/flow-icons/package.json +++ b/packages/flow-icons/package.json @@ -1,6 +1,6 @@ { "name": "@coding-flow/flow-icons", - "version": "0.1.8", + "version": "0.1.9", "description": "flow-engine icons ", "type": "module", "sideEffects": [ diff --git a/packages/flow-mobile/flow-mobile-approval/CHANGELOG.md b/packages/flow-mobile/flow-mobile-approval/CHANGELOG.md index 517c8f9..66cb1da 100644 --- a/packages/flow-mobile/flow-mobile-approval/CHANGELOG.md +++ b/packages/flow-mobile/flow-mobile-approval/CHANGELOG.md @@ -1,5 +1,17 @@ # @coding-flow/flow-mobile-approval +## 0.1.9 + +### Patch Changes + +- 789fa8c: 修复移动端转办(transfer)动作渲染覆盖视图时未透传 props 导致选人弹框 `action` 丢失崩溃;并为 `triggerFrontEvent` 自定义按钮补齐审批操作拦截器(先执行 `interceptAction`,全部放行后才派发事件,与 PC 语义对齐)。 + - @coding-flow/flow-approval-presenter@0.1.9 + - @coding-flow/flow-core@0.1.9 + - @coding-flow/flow-icons@0.1.9 + - @coding-flow/flow-mobile-form@0.1.9 + - @coding-flow/flow-mobile-ui@0.1.9 + - @coding-flow/flow-types@0.1.9 + ## 0.1.8 ### Patch Changes diff --git a/packages/flow-mobile/flow-mobile-approval/package.json b/packages/flow-mobile/flow-mobile-approval/package.json index 5ee097b..26c4107 100644 --- a/packages/flow-mobile/flow-mobile-approval/package.json +++ b/packages/flow-mobile/flow-mobile-approval/package.json @@ -1,6 +1,6 @@ { "name": "@coding-flow/flow-mobile-approval", - "version": "0.1.8", + "version": "0.1.9", "description": "flow-engine pc mobile approval components", "type": "module", "sideEffects": [ diff --git a/packages/flow-mobile/flow-mobile-approval/src/components/flow-approval/components/action-front-event.ts b/packages/flow-mobile/flow-mobile-approval/src/components/flow-approval/components/action-front-event.ts new file mode 100644 index 0000000..fd27ef3 --- /dev/null +++ b/packages/flow-mobile/flow-mobile-approval/src/components/flow-approval/components/action-front-event.ts @@ -0,0 +1,27 @@ +import { EventBus } from "@coding-flow/flow-core"; +import { FlowActionPresenter } from "@coding-flow/flow-approval-presenter"; + +/** + * 派发前端触发事件前执行审批操作拦截器(与 PC 端语义一致)。 + * + * 配置了 `triggerFrontEvent` 的自定义按钮不调用 `action()`,因此不会自动执行拦截器。 + * 本方法手动执行 `interceptAction`:全部拦截器放行后才派发事件, + * 任一拦截器返回 false 则终止本次派发。 + * + * @param actionPresenter 审批动作 Presenter(用于执行拦截器) + * @param actionId 触发的动作 ID + * @param triggerFrontEvent 前端触发事件名 + * @returns 是否放行并已派发事件 + */ +export async function dispatchApprovalFrontEvent( + actionPresenter: FlowActionPresenter, + actionId: string, + triggerFrontEvent: string, +): Promise { + const passed = await actionPresenter.interceptAction(actionId); + if (!passed) { + return false; + } + EventBus.getInstance().emit(triggerFrontEvent); + return true; +} \ No newline at end of file diff --git a/packages/flow-mobile/flow-mobile-approval/src/components/flow-approval/components/action/transfer.tsx b/packages/flow-mobile/flow-mobile-approval/src/components/flow-approval/components/action/transfer.tsx index e32387d..1cb05a0 100644 --- a/packages/flow-mobile/flow-mobile-approval/src/components/flow-approval/components/action/transfer.tsx +++ b/packages/flow-mobile/flow-mobile-approval/src/components/flow-approval/components/action/transfer.tsx @@ -82,6 +82,7 @@ export const TransferAction: React.FC = (props) => { if (ActionView) { return ( ) } diff --git a/packages/flow-mobile/flow-mobile-approval/src/components/flow-approval/components/flow-approval-actions.tsx b/packages/flow-mobile/flow-mobile-approval/src/components/flow-approval/components/flow-approval-actions.tsx index 8bec78c..b401994 100644 --- a/packages/flow-mobile/flow-mobile-approval/src/components/flow-approval/components/flow-approval-actions.tsx +++ b/packages/flow-mobile/flow-mobile-approval/src/components/flow-approval/components/flow-approval-actions.tsx @@ -6,6 +6,7 @@ import { ActionSheet, Button, Space, Toast } from "antd-mobile"; import { RevokeAction } from "@/components/flow-approval/components/action/revoke"; import { UrgeAction } from "@/components/flow-approval/components/action/urge"; import { ActionFactory } from "@/components/flow-approval/components/action/factory"; +import { dispatchApprovalFrontEvent } from "@/components/flow-approval/components/action-front-event"; import { EventBus, ObjectUtils, FlowMessageKey, FlowMessageRegistry } from "@coding-flow/flow-core"; import { useApprovalContext } from "@coding-flow/flow-approval-presenter"; @@ -33,7 +34,8 @@ export const FlowApprovalActions = () => { if (action) { const triggerFrontEvent = action.triggerFrontEvent; if (triggerFrontEvent) { - EventBus.getInstance().emit(triggerFrontEvent); + // 前端触发事件不经过 action(),需手动执行拦截器:全部放行后才派发事件 + dispatchApprovalFrontEvent(actionPresenter, id, triggerFrontEvent); } else { EventBus.getInstance().emit(id); } @@ -67,7 +69,7 @@ export const FlowApprovalActions = () => { onClick={() => { const triggerFrontEvent = action.triggerFrontEvent; if (triggerFrontEvent) { - EventBus.getInstance().emit(triggerFrontEvent); + dispatchApprovalFrontEvent(actionPresenter, action.id, triggerFrontEvent); } else { handlerAction(action.id); } diff --git a/packages/flow-mobile/flow-mobile-approval/tests/action-front-event.test.ts b/packages/flow-mobile/flow-mobile-approval/tests/action-front-event.test.ts new file mode 100644 index 0000000..90f1469 --- /dev/null +++ b/packages/flow-mobile/flow-mobile-approval/tests/action-front-event.test.ts @@ -0,0 +1,72 @@ +import { describe, expect, it, rs } from "@rstest/core"; +import { EventBus } from "@coding-flow/flow-core"; +import { + dispatchApprovalFrontEvent, +} from "@/components/flow-approval/components/action-front-event"; +import { FlowActionPresenter } from "@coding-flow/flow-approval-presenter"; + +/** + * 构造一个只暴露 interceptAction 的假 Presenter。 + * 事件触发逻辑仅依赖拦截器放行结果,无需完整 Presenter 栈。 + */ +const buildPresenter = (interceptAction: () => Promise | boolean) => { + return { + interceptAction: rs.fn(interceptAction), + } as unknown as FlowActionPresenter; +}; + +describe.sequential('移动端前端触发事件(triggerFrontEvent)拦截器', () => { + + it('拦截器全部放行后派发事件', async () => { + // given:一个放行的拦截器 + 事件监听 + const presenter = buildPresenter(async () => true); + let emitted = 0; + EventBus.getInstance().on('front-event-b', () => { + emitted += 1; + }); + + // when + const passed = await dispatchApprovalFrontEvent(presenter, 'custom-1', 'front-event-b'); + + // then:放行且事件已派发 + expect(passed).toBe(true); + expect(presenter.interceptAction).toHaveBeenCalledWith('custom-1'); + expect(emitted).toBe(1); + EventBus.getInstance().off('front-event-b'); + }); + + it('任一拦截器拦截则不派发事件', async () => { + // given:一个拦截的拦截器 + 事件监听 + const presenter = buildPresenter(async () => false); + let emitted = 0; + EventBus.getInstance().on('front-event-blocked', () => { + emitted += 1; + }); + + // when + const passed = await dispatchApprovalFrontEvent(presenter, 'custom-1', 'front-event-blocked'); + + // then:被拦截且未派发事件 + expect(passed).toBe(false); + expect(presenter.interceptAction).toHaveBeenCalledWith('custom-1'); + expect(emitted).toBe(0); + EventBus.getInstance().off('front-event-blocked'); + }); + + it('放行拦截器返回空 payload 也可派发', async () => { + // given + const presenter = buildPresenter(() => true); + let emitted = 0; + EventBus.getInstance().on('front-event-ok', () => { + emitted += 1; + }); + + // when + const passed = await dispatchApprovalFrontEvent(presenter, 'custom-ok', 'front-event-ok'); + + // then + expect(passed).toBe(true); + expect(emitted).toBe(1); + EventBus.getInstance().off('front-event-ok'); + }); +}); \ No newline at end of file diff --git a/packages/flow-mobile/flow-mobile-approval/tests/transfer-action-forward-props.test.tsx b/packages/flow-mobile/flow-mobile-approval/tests/transfer-action-forward-props.test.tsx new file mode 100644 index 0000000..bb0afad --- /dev/null +++ b/packages/flow-mobile/flow-mobile-approval/tests/transfer-action-forward-props.test.tsx @@ -0,0 +1,64 @@ +import { afterEach, describe, expect, test, rs } from "@rstest/core"; +import { Provider } from "react-redux"; +import { render, cleanup } from "@testing-library/react"; +import { configureStore } from "@reduxjs/toolkit"; +import { + ApprovalContext, + approvalSlice, + updateState, +} from "@coding-flow/flow-approval-presenter"; +import { FlowAction } from "@coding-flow/flow-types"; +import { ViewBindPlugin } from "@coding-flow/flow-core"; +import { APPROVAL_ACTION_TRANSFER_KEY } from "@/components/flow-approval"; +import { TransferAction } from "@/components/flow-approval/components/action/transfer"; + +const buildTransferAction = (id: string): FlowAction => ({ + id, + title: '转办', + type: 'TRANSFER', + display: { title: '转办', style: 'primary', icon: '' }, + enable: true, +} as FlowAction); + +/** 覆盖视图收到的 props(结构上等同于 FlowActionProps) */ +interface FlowActionProps { + action: FlowAction; +} + +describe.sequential('移动端转办动作(TransferAction)覆盖视图 props 透传', () => { + + afterEach(() => { + cleanup(); + }); + + test('渲染覆盖视图时应透传 action(回归:未透传导致 PersonSelectModal 崩溃)', () => { + // given:注册一个 spy 覆盖视图,并搭建 redux + ApprovalContext 环境 + const transferAction = buildTransferAction('transfer-1'); + const spy = rs.fn((props: FlowActionProps) =>
转办覆盖视图
); + ViewBindPlugin.getInstance().register(APPROVAL_ACTION_TRANSFER_KEY, spy); + + const store = configureStore({ + reducer: { approval: approvalSlice.reducer }, + }); + store.dispatch(updateState({ flow: { actions: [transferAction] }, actionLoading: false })); + + // 最小可用的 context:TransferAction 仅在选中 ActionView 分支前读取 + // state.actionLoading 与 context.getPresenter().getFlowActionPresenter() + const fakeContext = { + getPresenter: () => ({ getFlowActionPresenter: () => null }), + }; + + render( + + + + + + ); + + // then:覆盖视图被渲染,且收到 action props + expect(spy).toHaveBeenCalledTimes(1); + const receivedProps = spy.mock.calls[0][0]; + expect(receivedProps.action).toBe(transferAction); + }); +}); \ No newline at end of file diff --git a/packages/flow-mobile/flow-mobile-form/CHANGELOG.md b/packages/flow-mobile/flow-mobile-form/CHANGELOG.md index f5b12e4..76d8c2b 100644 --- a/packages/flow-mobile/flow-mobile-form/CHANGELOG.md +++ b/packages/flow-mobile/flow-mobile-form/CHANGELOG.md @@ -1,5 +1,12 @@ # @coding-flow/flow-mobile-form +## 0.1.9 + +### Patch Changes + +- @coding-flow/flow-core@0.1.9 +- @coding-flow/flow-types@0.1.9 + ## 0.1.8 ### Patch Changes diff --git a/packages/flow-mobile/flow-mobile-form/package.json b/packages/flow-mobile/flow-mobile-form/package.json index 2b1257b..c853433 100644 --- a/packages/flow-mobile/flow-mobile-form/package.json +++ b/packages/flow-mobile/flow-mobile-form/package.json @@ -1,6 +1,6 @@ { "name": "@coding-flow/flow-mobile-form", - "version": "0.1.8", + "version": "0.1.9", "description": "flow-engine mobile form engine", "type": "module", "sideEffects": [ diff --git a/packages/flow-mobile/flow-mobile-ui/CHANGELOG.md b/packages/flow-mobile/flow-mobile-ui/CHANGELOG.md index b4cb206..a03988b 100644 --- a/packages/flow-mobile/flow-mobile-ui/CHANGELOG.md +++ b/packages/flow-mobile/flow-mobile-ui/CHANGELOG.md @@ -1,5 +1,11 @@ # @coding-flow/flow-mobile-ui +## 0.1.9 + +### Patch Changes + +- @coding-flow/flow-core@0.1.9 + ## 0.1.8 ### Patch Changes diff --git a/packages/flow-mobile/flow-mobile-ui/package.json b/packages/flow-mobile/flow-mobile-ui/package.json index eca0df8..0ffc6a6 100644 --- a/packages/flow-mobile/flow-mobile-ui/package.json +++ b/packages/flow-mobile/flow-mobile-ui/package.json @@ -1,6 +1,6 @@ { "name": "@coding-flow/flow-mobile-ui", - "version": "0.1.8", + "version": "0.1.9", "description": "flow-engine mobile ui components", "type": "module", "sideEffects": [ diff --git a/packages/flow-pc/flow-pc-approval/CHANGELOG.md b/packages/flow-pc/flow-pc-approval/CHANGELOG.md index b5adc1e..83b9eb7 100644 --- a/packages/flow-pc/flow-pc-approval/CHANGELOG.md +++ b/packages/flow-pc/flow-pc-approval/CHANGELOG.md @@ -1,5 +1,16 @@ # @coding-flow/flow-pc-approval +## 0.1.9 + +### Patch Changes + +- @coding-flow/flow-approval-presenter@0.1.9 +- @coding-flow/flow-core@0.1.9 +- @coding-flow/flow-icons@0.1.9 +- @coding-flow/flow-pc-form@0.1.9 +- @coding-flow/flow-pc-ui@0.1.9 +- @coding-flow/flow-types@0.1.9 + ## 0.1.8 ### Patch Changes diff --git a/packages/flow-pc/flow-pc-approval/package.json b/packages/flow-pc/flow-pc-approval/package.json index 49737c0..509f94a 100644 --- a/packages/flow-pc/flow-pc-approval/package.json +++ b/packages/flow-pc/flow-pc-approval/package.json @@ -1,6 +1,6 @@ { "name": "@coding-flow/flow-pc-approval", - "version": "0.1.8", + "version": "0.1.9", "description": "flow-engine pc form approval components", "type": "module", "sideEffects": [ diff --git a/packages/flow-pc/flow-pc-form/CHANGELOG.md b/packages/flow-pc/flow-pc-form/CHANGELOG.md index 4438fc6..6e3b66a 100644 --- a/packages/flow-pc/flow-pc-form/CHANGELOG.md +++ b/packages/flow-pc/flow-pc-form/CHANGELOG.md @@ -1,5 +1,12 @@ # @coding-flow/flow-pc-form +## 0.1.9 + +### Patch Changes + +- @coding-flow/flow-core@0.1.9 +- @coding-flow/flow-types@0.1.9 + ## 0.1.8 ### Patch Changes diff --git a/packages/flow-pc/flow-pc-form/package.json b/packages/flow-pc/flow-pc-form/package.json index 94cf6e5..30dfeeb 100644 --- a/packages/flow-pc/flow-pc-form/package.json +++ b/packages/flow-pc/flow-pc-form/package.json @@ -1,6 +1,6 @@ { "name": "@coding-flow/flow-pc-form", - "version": "0.1.8", + "version": "0.1.9", "description": "flow-engine pc form engine", "type": "module", "sideEffects": [ diff --git a/packages/flow-pc/flow-pc-ui/CHANGELOG.md b/packages/flow-pc/flow-pc-ui/CHANGELOG.md index bc67bf0..bbe30e2 100644 --- a/packages/flow-pc/flow-pc-ui/CHANGELOG.md +++ b/packages/flow-pc/flow-pc-ui/CHANGELOG.md @@ -1,5 +1,11 @@ # @coding-flow/flow-pc-ui +## 0.1.9 + +### Patch Changes + +- @coding-flow/flow-core@0.1.9 + ## 0.1.8 ### Patch Changes diff --git a/packages/flow-pc/flow-pc-ui/package.json b/packages/flow-pc/flow-pc-ui/package.json index 6718ba1..dacfbf3 100644 --- a/packages/flow-pc/flow-pc-ui/package.json +++ b/packages/flow-pc/flow-pc-ui/package.json @@ -1,6 +1,6 @@ { "name": "@coding-flow/flow-pc-ui", - "version": "0.1.8", + "version": "0.1.9", "description": "flow-engine pc ui components", "type": "module", "sideEffects": [ diff --git a/packages/flow-types/CHANGELOG.md b/packages/flow-types/CHANGELOG.md index c095356..cb26988 100644 --- a/packages/flow-types/CHANGELOG.md +++ b/packages/flow-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @coding-flow/flow-types +## 0.1.9 + +### Patch Changes + +- @coding-flow/flow-core@0.1.9 + ## 0.1.8 ### Patch Changes diff --git a/packages/flow-types/package.json b/packages/flow-types/package.json index e141415..1ae2dfe 100644 --- a/packages/flow-types/package.json +++ b/packages/flow-types/package.json @@ -1,6 +1,6 @@ { "name": "@coding-flow/flow-types", - "version": "0.1.8", + "version": "0.1.9", "description": "flow-engine types", "type": "module", "sideEffects": [