20260923165454

This commit is contained in:
oneao committed 2026-09-23 16:54:54 +08:00
1 parent 0abe3706c8
commit e6935b8fa4
173 files changed
+14975 -2295

No files matched your search

@@ -0,0 +1,308 @@
/**
* 流程设计器 —— 枚举与节点元数据。
*
* 取值全部来自《FMS工作流与审批设计》与《FMS审批流程交互重构设计》:
* - 节点类型 b_node_type §4.4 / §6.4
* - 审批方式 b_approval_mode §6.4 / §9
* - 驳回策略 b_reject_mode §6.4 / §9.7
* - 审批人解析 b_actor_type §6.6
* - 条件操作符 §7.1
* - 审批行为开关 §5.2(全部落 b_config_json,不新增列)
*
* 数据库存稳定编码,中文文案只在本文件出现一次,页面直接引用。
* 唯一的例外是条件操作符文案:高级查询(fms-module-common/queryUtils.js)已经
* 定义了同一批操作符的文案与多语言键,这里复用而不是复制第二份翻译。
*/
import { operatorLabel } from '@/components/fms-module-common/queryUtils'
/** 领域草稿结构版本(《FMS审批流程交互重构设计》§6.1) */
export const SCHEMA_VERSION = 2
/** 工作流节点类型(落 wf_node.b_node_type) */
export const NODE_TYPES = {
START: 'start',
USER_TASK: 'user_task',
CC_TASK: 'cc_task',
EXCLUSIVE_GATEWAY: 'exclusive_gateway',
PARALLEL_GATEWAY: 'parallel_gateway',
SERVICE_TASK: 'service_task',
END: 'end',
}
/**
* 领域节点类型 ↔ LogicFlow 画布类型(《FMS工作流与审批设计》§19.5)。
* 画布类型只是前端渲染类型,落库一律用领域类型。
*/
export const NODE_TYPE_TO_CANVAS = {
[NODE_TYPES.START]: 'fms-start',
[NODE_TYPES.USER_TASK]: 'fms-user-task',
[NODE_TYPES.CC_TASK]: 'fms-cc-task',
[NODE_TYPES.EXCLUSIVE_GATEWAY]: 'fms-exclusive-gateway',
[NODE_TYPES.PARALLEL_GATEWAY]: 'fms-parallel-gateway',
[NODE_TYPES.SERVICE_TASK]: 'fms-service-task',
[NODE_TYPES.END]: 'fms-end',
}
/** 画布类型 → 领域节点类型(事件回调里反查用) */
export const CANVAS_TO_NODE_TYPE = Object.fromEntries(
Object.entries(NODE_TYPE_TO_CANVAS).map(([nodeType, canvasType]) => [canvasType, nodeType]),
)
/**
* 卡片模式(钉钉式纵向卡片)允许的节点类型(§3.1)。
* 出现其它类型说明流程不再是单链路,只能留在高级模式编辑。
*/
export const LINEAR_NODE_TYPES = [NODE_TYPES.START, NODE_TYPES.USER_TASK, NODE_TYPES.CC_TASK, NODE_TYPES.END]
/** 会让流程超出单链路的节点类型(§3.1 单链路判定) */
export const BRANCH_NODE_TYPES = [
NODE_TYPES.EXCLUSIVE_GATEWAY,
NODE_TYPES.PARALLEL_GATEWAY,
NODE_TYPES.SERVICE_TASK,
]
/**
* 节点元数据:左侧面板顺序、显示名、形状、尺寸与配色。
*
* 画布是 SVG,fill/stroke 走的是表现属性而不是 CSS,`var(--fms-*)` 在这里不生效,
* 因此配色写成字面量(与 tokens.css 同色系)。深色模式下的画布配色待后续统一处理。
*/
export const NODE_META = {
[NODE_TYPES.START]: {
label: '开始',
shape: 'circle',
size: { r: 26 },
style: { fill: '#ecfdf5', stroke: '#16a34a' },
/** 开始节点不可删除、不可改属性 */
fixed: true,
hint: '流程入口,有且只有一个',
},
[NODE_TYPES.USER_TASK]: {
label: '人工审批',
shape: 'rect',
size: { width: 160, height: 48 },
style: { fill: '#eef2ff', stroke: '#4f46e5' },
hint: '由审批人处理的节点',
},
[NODE_TYPES.CC_TASK]: {
label: '抄送',
shape: 'rect',
size: { width: 160, height: 48 },
style: { fill: '#f0f9ff', stroke: '#0284c7' },
hint: '只通知不产生待办,自动完成',
},
[NODE_TYPES.EXCLUSIVE_GATEWAY]: {
label: '条件分支',
shape: 'diamond',
size: { rx: 34, ry: 34 },
style: { fill: '#fff7ed', stroke: '#ea580c' },
hint: '按连线条件择一分支,必须有默认出口',
},
[NODE_TYPES.PARALLEL_GATEWAY]: {
label: '并行分支',
shape: 'diamond',
size: { rx: 34, ry: 34 },
style: { fill: '#f5f3ff', stroke: '#7c3aed' },
hint: '所有出线同时激活',
},
[NODE_TYPES.SERVICE_TASK]: {
label: '服务节点',
shape: 'rect',
size: { width: 160, height: 48 },
style: { fill: '#fefce8', stroke: '#ca8a04' },
hint: '后端服务动作,第一阶段仅占位',
},
[NODE_TYPES.END]: {
label: '结束',
shape: 'circle',
size: { r: 26 },
style: { fill: '#f4f4f5', stroke: '#71717a' },
fixed: true,
hint: '流程出口,可以有多个',
},
}
/** 左侧面板的展示顺序 */
export const NODE_PALETTE_ORDER = [
NODE_TYPES.START,
NODE_TYPES.USER_TASK,
NODE_TYPES.CC_TASK,
NODE_TYPES.EXCLUSIVE_GATEWAY,
NODE_TYPES.PARALLEL_GATEWAY,
NODE_TYPES.SERVICE_TASK,
NODE_TYPES.END,
]
/** 卡片模式「插入节点」可选的类型(开始/结束是固定端点,不参与插入) */
export const INSERTABLE_NODE_TYPES = [NODE_TYPES.USER_TASK, NODE_TYPES.CC_TASK]
/** 需要配审批人/抄送人的节点类型 */
export const ACTOR_NODE_TYPES = [NODE_TYPES.USER_TASK, NODE_TYPES.CC_TASK]
/**
* 审批方式 b_approval_mode(§6.4)。
* param 指向需要额外填写的参数:N 人通过要人数、按比例通过要比例。
*/
export const APPROVAL_MODES = [
{ value: 'single', label: '单人审批', param: null },
{ value: 'any', label: '或签(任一人通过)', param: null },
{ value: 'all', label: '会签(全部通过)', param: null },
{ value: 'serial', label: '串行会签', param: null },
{ value: 'n_of_m', label: 'N 人通过', param: 'requiredCount' },
{ value: 'percentage', label: '按比例通过', param: 'requiredRatio' },
]
/** 驳回策略 b_reject_mode(§9.7) */
export const REJECT_MODES = [
{ value: 'terminate', label: '驳回即结束(一票否决)' },
{ value: 'return_initiator', label: '退回发起人' },
{ value: 'return_previous', label: '退回上一节点' },
]
/**
* 审批人解析类型 b_actor_type(§6.6)。
* control 决定属性抽屉用哪种控件取 b_actor_ref:
* user/position/org_role → 选择器(提交稳定编码)
* field → 字段选择器(字段必须来自当前模块 s_field)
* dept → 部门来源固定选项
* resolver → 后端注册的解析器编码
* none → 无参,靠流程上下文解析
*/
export const ACTOR_TYPES = [
{ value: 'user', label: '指定用户', control: 'user' },
{ value: 'initiator', label: '发起人', control: 'none' },
{ value: 'initiator_manager', label: '发起人直属领导', control: 'none' },
{ value: 'dept_manager', label: '部门负责人', control: 'dept' },
{ value: 'position', label: '岗位', control: 'position' },
{ value: 'org_role', label: '组织角色', control: 'org_role' },
{ value: 'field_user', label: '业务字段用户', control: 'field' },
{ value: 'custom', label: '自定义解析器', control: 'resolver' },
]
/** 需要填 b_actor_ref 的解析类型(由 control 派生,避免两处维护) */
export const ACTOR_TYPES_WITH_REF = ACTOR_TYPES.filter((item) => item.control !== 'none').map(
(item) => item.value,
)
/** 部门负责人的部门来源(§5.2「可选择发起人部门或业务部门」,编码存 b_actor_ref) */
export const DEPT_MANAGER_SOURCES = [
{ value: 'initiator_dept', label: '发起人所属部门' },
{ value: 'business_dept', label: '业务归属部门' },
]
/** 审批人解析为空时的兜底 b_fallback_type(§6.6) */
export const FALLBACK_TYPES = [
{ value: 'none', label: '不兜底(阻塞并告警)' },
{ value: 'admin', label: '转交管理员' },
{ value: 'initiator', label: '转交发起人' },
{ value: 'custom', label: '自定义解析器' },
]
/** 兜底策略里需要填编码的类型 */
export const FALLBACK_TYPES_WITH_REF = ['custom']
/**
* 节点审批行为开关(§5.2)。
* 全部落在 wf_node.b_config_json,不为了每个开关新增一列(§7.2)。
*/
export const NODE_BEHAVIOR_FLAGS = [
{
key: 'allowInitiator',
label: '允许申请人自审',
hint: '默认关闭;关闭时发起人不会成为本节点审批人',
},
{
key: 'excludePreviousActors',
label: '排除前序审批人',
hint: '已在前面节点审批过的人不再重复收到待办',
},
{ key: 'allowClaim', label: '允许抢占', hint: '候选人可主动认领待办' },
{ key: 'allowTransfer', label: '允许转交', hint: '审批人可把待办转交他人' },
{ key: 'allowDelegate', label: '允许委托', hint: '审批人可临时委托他人处理' },
{ key: 'allowAddApprover', label: '允许加签', hint: '审批人可向当前节点追加审批人' },
{ key: 'commentRequired', label: '审批意见必填', hint: '提交审批动作时必须填写意见' },
]
/** 业务事件 b_event(§6.3) */
export const BINDING_EVENTS = [
{ value: 'submit', label: '送审' },
{ value: 'resubmit', label: '重新提交' },
{ value: 'change', label: '变更' },
]
/** 版本状态 b_status(§4.2) */
export const VERSION_STATUS = [
{ value: 'draft', label: '草稿', tag: 'secondary' },
{ value: 'published', label: '已发布', tag: 'success' },
{ value: 'retired', label: '已停用', tag: 'default' },
]
/** 草稿保存状态(§8.2 工具栏),仅前端状态 */
export const DRAFT_STATUS = {
IDLE: 'idle',
DIRTY: 'dirty',
SAVING: 'saving',
SAVED: 'saved',
ERROR: 'error',
}
export const DRAFT_STATUS_LABEL = {
idle: '未修改',
dirty: '未保存',
saving: '保存中',
saved: '已保存',
error: '保存失败',
}
/** 编辑器模式(§3.3)——只放组件状态,不落库、不进草稿 */
export const EDITOR_MODES = {
STEP: 'step',
CANVAS: 'canvas',
}
/**
* 条件 AST 的逻辑节点(§7.1)。
* 连线条件为空表示默认出口,条件分支节点必须保留一条这样的连线。
*/
export const CONDITION_LOGICS = [
{ value: 'all', label: '全部满足(且)' },
{ value: 'any', label: '任一满足(或)' },
]
/**
* 工作流条件支持的操作符(§7.1)。
* 只列编码,文案由 queryUtils.operatorLabel 提供(高级查询与工作流共用一套翻译)。
*/
export const CONDITION_OPERATORS = [
'eq',
'ne',
'gt',
'ge',
'lt',
'le',
'in',
'not_in',
'like',
'is_null',
'is_not_null',
'between',
]
/** 不需要填值的操作符 */
export const OPERATORS_WITHOUT_VALUE = ['is_null', 'is_not_null']
/** 值是多选列表的操作符 */
export const OPERATORS_WITH_LIST_VALUE = ['in', 'not_in']
/** 值是区间的操作符 */
export const OPERATORS_WITH_RANGE_VALUE = ['between']
/** 操作符显示文案:多语言键优先,缺翻译回退中文(与高级查询同一份定义) */
export function conditionOperatorLabel(operator, translate) {
return operatorLabel(operator, translate)
}
/** 按编码取中文名,找不到回落到编码本身 */
export function labelOf(list, value) {
return list.find((item) => item.value === value)?.label || value || ''
}