mirror of
http://git.pig4cloud.com/pig/pigx.git
synced 2026-11-10 21:19:00 +08:00
docs(flow): add withdraw resubmit design
This commit is contained in:
1 parent
2c70387ace
commit
b553787cfd
1 file changed
+377
@@ -0,0 +1,377 @@
|
||||
# Flow Withdraw Resubmit Design
|
||||
|
||||
## Scope
|
||||
|
||||
This design covers starter-side "resubmit after withdraw" behavior for:
|
||||
|
||||
- `pigx-ui-pro/src/views/flow/task/started.vue`
|
||||
- dynamic flow forms
|
||||
- custom business forms
|
||||
|
||||
The capability is limited to processes already withdrawn by the starter. It does not reopen the old process instance.
|
||||
|
||||
## Problem Statement
|
||||
|
||||
The current flow center supports:
|
||||
|
||||
- withdraw for starter-side in-progress instances
|
||||
- resubmit for `rejectToStarter`
|
||||
|
||||
But it does not support the common case where the starter withdraws because they found mistakes in the form and wants to:
|
||||
|
||||
1. edit the old submitted data
|
||||
2. keep the withdrawn record as history
|
||||
3. start a brand new process instance from the corrected data
|
||||
|
||||
This must work for both:
|
||||
|
||||
- dynamic flow forms
|
||||
- custom business forms
|
||||
|
||||
## Confirmed Product Decisions
|
||||
|
||||
1. After withdraw, resubmission must create a new process instance
|
||||
2. The old withdrawn record must remain as a separate historical record
|
||||
3. The entry point should be a single user-facing capability: `重新编辑提交`
|
||||
4. The implementation path should split by form type:
|
||||
- dynamic flow form: edit in flow center drawer
|
||||
- business form: edit in a page/container path
|
||||
5. Previous manually selected approvers / copy recipients should be carried as defaults and remain editable
|
||||
|
||||
## Goals
|
||||
|
||||
1. Add `重新编辑提交` for withdrawn starter records
|
||||
2. Let users correct form mistakes before submitting again
|
||||
3. Preserve withdrawn process history
|
||||
4. Reuse existing form loading and start-process capabilities where possible
|
||||
5. Support both dynamic and business forms in the same product capability
|
||||
|
||||
## Non-Goals
|
||||
|
||||
1. Do not reopen the old withdrawn Flowable instance
|
||||
2. Do not merge new submission into the old withdrawn record
|
||||
3. Do not copy approval history from the old instance to the new one
|
||||
4. Do not introduce a dedicated backend "withdraw-resubmit" API in V1
|
||||
|
||||
## Recommended Approach
|
||||
|
||||
### Option 1: Unified Entry, Split by Form Type
|
||||
|
||||
Description:
|
||||
|
||||
- show one action named `重新编辑提交`
|
||||
- branch internally by form type
|
||||
- dynamic flow forms open an editable drawer in flow center
|
||||
- business forms go through a common restart container page
|
||||
|
||||
Pros:
|
||||
|
||||
- unified user mental model
|
||||
- minimal duplication
|
||||
- works for both form types
|
||||
- avoids forcing every business form page to implement workflow-side participant editing on its own
|
||||
|
||||
Cons:
|
||||
|
||||
- needs a common restart context loader
|
||||
- needs one new common business-form restart container page
|
||||
|
||||
Conclusion:
|
||||
|
||||
- recommend
|
||||
|
||||
### Option 2: Always Jump to a Full Page
|
||||
|
||||
Description:
|
||||
|
||||
- both dynamic forms and business forms always jump to a dedicated page
|
||||
|
||||
Pros:
|
||||
|
||||
- interaction form is consistent
|
||||
|
||||
Cons:
|
||||
|
||||
- duplicates current dynamic-form drawer flow
|
||||
- larger change surface
|
||||
|
||||
Conclusion:
|
||||
|
||||
- not recommended for V1
|
||||
|
||||
### Option 3: Always Stay in started.vue Drawer
|
||||
|
||||
Description:
|
||||
|
||||
- both dynamic forms and business forms are handled inside `started.vue`
|
||||
|
||||
Pros:
|
||||
|
||||
- entry is centralized
|
||||
|
||||
Cons:
|
||||
|
||||
- business forms often depend on route/page context
|
||||
- harder to keep complex custom forms maintainable
|
||||
|
||||
Conclusion:
|
||||
|
||||
- reject
|
||||
|
||||
## Product Behavior
|
||||
|
||||
### Starter List
|
||||
|
||||
On [started.vue](/Users/lengleng/work/dev1227/pigx-ui-pro/src/views/flow/task/started.vue):
|
||||
|
||||
- records with process status `已撤回` should display `重新编辑提交`
|
||||
- records with `rejectToStarter` should keep the current `重新提交`
|
||||
- these are different capabilities and must remain separate
|
||||
|
||||
### Old Record Handling
|
||||
|
||||
After successful resubmission:
|
||||
|
||||
- the old record remains `已撤回`
|
||||
- a new record appears as `进行中`
|
||||
|
||||
### Button Naming
|
||||
|
||||
Use a single starter-facing action name:
|
||||
|
||||
- `重新编辑提交`
|
||||
|
||||
Reason:
|
||||
|
||||
- it makes the user intent explicit
|
||||
- it distinguishes this flow from `驳回待提交 -> 重新提交`
|
||||
|
||||
## Data Flow Design
|
||||
|
||||
### Shared Source Data
|
||||
|
||||
When the user clicks `重新编辑提交`, frontend should load:
|
||||
|
||||
1. old instance snapshot via `detail(processInstanceId)`
|
||||
2. current flow definition via `getFlowDetail(flowId)`
|
||||
|
||||
The old instance snapshot provides:
|
||||
|
||||
- previous form data
|
||||
- previous manually selected participant values stored in submitted process params
|
||||
|
||||
The current flow definition provides:
|
||||
|
||||
- current form type
|
||||
- current form component path / dynamic form schema
|
||||
- current selectable participant nodes
|
||||
|
||||
### Participant Default Value Strategy
|
||||
|
||||
Only carry forward values the user explicitly selected before.
|
||||
|
||||
Use old submitted process params such as:
|
||||
|
||||
- `nodeId_assignee_select`
|
||||
|
||||
Do not carry forward:
|
||||
|
||||
- historical approval results
|
||||
- historical comments
|
||||
- runtime-derived approval outcomes
|
||||
|
||||
If a previously selected node no longer exists in the current flow definition:
|
||||
|
||||
- ignore the old value
|
||||
|
||||
If a new required selectable node is present in the current definition:
|
||||
|
||||
- require the user to select it again before submit
|
||||
|
||||
## Form-Type Split
|
||||
|
||||
### Dynamic Flow Form
|
||||
|
||||
When `formType=10`:
|
||||
|
||||
- stay in [started.vue](/Users/lengleng/work/dev1227/pigx-ui-pro/src/views/flow/task/started.vue)
|
||||
- open an editable restart drawer
|
||||
- left side reuses dynamic form rendering
|
||||
- right side reuses [FlowNodeFormatData.vue](/Users/lengleng/work/dev1227/pigx-ui-pro/src/views/flow/form/tools/FlowNodeFormatData.vue)
|
||||
- old participant selections are injected into `nodeUser`
|
||||
- submit starts a new process instance
|
||||
|
||||
### Business Form
|
||||
|
||||
When `formType=20`:
|
||||
|
||||
- do not jump directly to each existing business create page as the primary architecture
|
||||
- add a common restart container page under flow task module
|
||||
- the container page is responsible for:
|
||||
- loading the business form create component
|
||||
- loading the current flow definition
|
||||
- rendering the right-side participant panel
|
||||
- orchestrating final submit as a new process start
|
||||
|
||||
Reason:
|
||||
|
||||
- existing business pages usually do not own a common workflow participant panel
|
||||
- a common restart container keeps workflow behavior centralized and reusable
|
||||
|
||||
## Frontend Component Boundary
|
||||
|
||||
### started.vue
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- expose `重新编辑提交` entry for withdrawn records
|
||||
- decide route vs drawer by form type
|
||||
- continue handling current starter list concerns
|
||||
|
||||
### New Restart Context Loader
|
||||
|
||||
Add a shared loader/composable responsible for:
|
||||
|
||||
- fetching old instance detail
|
||||
- fetching current flow detail
|
||||
- building initial form values
|
||||
- building initial participant defaults
|
||||
- exposing the resolved restart mode
|
||||
|
||||
### FlowNodeFormatData.vue
|
||||
|
||||
Needs a small enhancement:
|
||||
|
||||
- allow external default `nodeUser` injection for restart scenarios
|
||||
|
||||
### New Business Restart Container Page
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- render the business create component dynamically
|
||||
- render `FlowNodeFormatData`
|
||||
- merge edited business form data and participant selections
|
||||
- start a new process instance
|
||||
|
||||
## Existing Capabilities Reused
|
||||
|
||||
### Frontend
|
||||
|
||||
- [dynamicComponent.ts](/Users/lengleng/work/dev1227/pigx-ui-pro/src/views/flow/workflow/utils/dynamicComponent.ts)
|
||||
- [useTaskForm.ts](/Users/lengleng/work/dev1227/pigx-ui-pro/src/views/flow/task/composables/useTaskForm.ts)
|
||||
- [FlowNodeFormatData.vue](/Users/lengleng/work/dev1227/pigx-ui-pro/src/views/flow/form/tools/FlowNodeFormatData.vue)
|
||||
- [startFlow](/Users/lengleng/work/dev1227/pigx-ui-pro/src/api/flow/flow/index.ts)
|
||||
|
||||
### Backend
|
||||
|
||||
V1 should reuse existing APIs:
|
||||
|
||||
- `detail(processInstanceId)`
|
||||
- `getFlowDetail(flowId)`
|
||||
- `startProcessInstance / startFlow`
|
||||
|
||||
No dedicated backend restart API is required in V1.
|
||||
|
||||
## Business Form Compatibility
|
||||
|
||||
For business forms to participate in V1:
|
||||
|
||||
- their create component must support loading old data by `processInstanceId`
|
||||
|
||||
Example:
|
||||
|
||||
- [create.vue](/Users/lengleng/work/dev1227/pigx-ui-pro/src/views/flow/oaLeave/create.vue) already supports querying old data with `processInstanceId`
|
||||
|
||||
If some business form cannot load old data this way:
|
||||
|
||||
- it is out of V1 support unless adapted
|
||||
|
||||
## Submit Semantics
|
||||
|
||||
### Dynamic Form Submit
|
||||
|
||||
Payload:
|
||||
|
||||
- edited dynamic form data
|
||||
- participant selections from `FlowNodeFormatData`
|
||||
|
||||
Behavior:
|
||||
|
||||
- call process start API
|
||||
- create a new process instance
|
||||
|
||||
### Business Form Submit
|
||||
|
||||
Payload:
|
||||
|
||||
- edited business form data from the business create component
|
||||
- participant selections from `FlowNodeFormatData`
|
||||
|
||||
Behavior:
|
||||
|
||||
- call business-form submit path that starts a new process instance
|
||||
- create a new process instance
|
||||
|
||||
## Success and Failure UX
|
||||
|
||||
### Success
|
||||
|
||||
Message:
|
||||
|
||||
- `已重新发起流程`
|
||||
|
||||
Behavior:
|
||||
|
||||
- close restart drawer or leave restart page
|
||||
- return to starter list
|
||||
- refresh list
|
||||
|
||||
### Failure
|
||||
|
||||
If current flow definition is unavailable:
|
||||
|
||||
- `当前流程已不可发起`
|
||||
|
||||
If business form component path is invalid:
|
||||
|
||||
- `业务表单不可用,无法重新发起`
|
||||
|
||||
If old participant values are no longer valid:
|
||||
|
||||
- do not block opening
|
||||
- require reselection at validation time
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
1. Withdrawn starter records show `重新编辑提交`
|
||||
2. Dynamic flow forms open editable restart drawer with old form values
|
||||
3. Business forms open common restart container with old form values
|
||||
4. Previous manually selected approvers/copy users are prefilled when possible
|
||||
5. User can change both form data and participant selections before submit
|
||||
6. Submit creates a new process instance
|
||||
7. Old withdrawn record remains unchanged
|
||||
8. New record appears independently in starter list
|
||||
|
||||
## Risks
|
||||
|
||||
1. Business forms vary in how much they depend on route context
|
||||
2. Some business create components may not yet support restart-container integration cleanly
|
||||
3. Participant default values rely on old submitted explicit selections, not on all runtime assignment types
|
||||
|
||||
## Recommended V1 Rollout
|
||||
|
||||
1. Dynamic flow forms first
|
||||
2. Common restart container for business forms
|
||||
3. Verify `oaLeave` as the first business-form example
|
||||
4. Expand to additional business forms that already support `processInstanceId`-based reload
|
||||
|
||||
## Implementation Outline
|
||||
|
||||
The `writing-plans` skill referenced by brainstorming is unavailable in this workspace. As a fallback, implement in this order:
|
||||
|
||||
1. Add withdrawn-record `重新编辑提交` action to starter list
|
||||
2. Add restart context loader and split logic by form type
|
||||
3. Add dynamic-form restart drawer path
|
||||
4. Add business-form restart container page
|
||||
5. Enhance participant panel to accept default values
|
||||
6. Verify `oaLeave` and one dynamic form end to end
|
||||
Reference in new issue
Block a user