yyd-flow-designer 0.1.7 → 0.1.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yyd-flow-designer",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "private": false,
5
5
  "description": "YYD Flow designer (process orchestration UI)",
6
6
  "keywords": [
@@ -59,7 +59,7 @@ ExclusiveGateway.nodeSchema = {
59
59
  code: '',
60
60
  name: '判断',
61
61
  description: '',
62
- // 约定:续跑 UserTask 时 command.inputs.action = approve | reject
62
+ // 约定:续跑 UserTask 时 command.inputs.__action = approve | reject
63
63
  inputs: [{ key: FLOW_ACTION_KEY, mode: 'value', value: '' }],
64
64
  branches: DEFAULT_BRANCHES,
65
65
  },
@@ -32,7 +32,7 @@ UserTask.nodeSchema = {
32
32
  },
33
33
  timeoutSetting: [],
34
34
  inputs: [],
35
- // 提交时写入 command.inputs.action(approve | reject),供后续判断节点使用
35
+ // 提交时写入 command.inputs.__action(approve | reject),供后续判断节点使用
36
36
  outputs: [{ key: FLOW_ACTION_KEY, mode: 'value', value: '' }],
37
37
  outputNotifyWebhook: { enabled: false, url: '', body: [] },
38
38
  },
@@ -1,4 +1,5 @@
1
- import { Form, Input, Select } from 'antd';
1
+ import { Form, Input } from 'antd';
2
+ import { Select } from '../../../../ui/antd';
2
3
  import { memo } from 'react';
3
4
  import AssigneeRulesEditor from './components/AssigneeRulesEditor';
4
5
  import TimeoutSettingEditor from './components/TimeoutSettingEditor';
@@ -1,5 +1,6 @@
1
1
  import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
2
- import { Button, Form, Input, Select, Space } from 'antd';
2
+ import { Button, Form, Input, Space } from 'antd';
3
+ import { Select } from '../../../../../ui/antd';
3
4
  import { memo, useCallback, useMemo } from 'react';
4
5
  import { useReactFlow } from '@xyflow/react';
5
6
  import {
@@ -1,7 +1,8 @@
1
1
  import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
2
- import { Button, Input, Segmented, Select } from 'antd';
2
+ import { Button, Input, Segmented } from 'antd';
3
3
  import { useReactFlow } from '@xyflow/react';
4
4
  import { memo, useCallback } from 'react';
5
+ import { Select } from '../../../../../ui/antd';
5
6
  import { BPMN_CONDITION_MODE_OPTIONS, isEmptyConditionMode } from '../../../config';
6
7
 
7
8
  export interface BranchConditionItem {
@@ -283,11 +284,20 @@ const GatewayBranchesEditor = ({
283
284
  </div>
284
285
  <div className="bpmn-gateway-branches__field">
285
286
  <div className="bpmn-gateway-branches__label">运算符</div>
286
- <Select
287
+ {/* 固定短列表用原生 select,避开 antd 虚拟列表被宿主样式撑乱 */}
288
+ <select
289
+ className="bpmn-gateway-branches__native-select"
287
290
  value={cond.mode}
288
- options={BPMN_CONDITION_MODE_OPTIONS}
289
- onChange={(mode) => handleUpdateCondition(index, cIndex, { mode })}
290
- />
291
+ onChange={(e) => handleUpdateCondition(index, cIndex, {
292
+ mode: e.target.value,
293
+ })}
294
+ >
295
+ {BPMN_CONDITION_MODE_OPTIONS.map((opt) => (
296
+ <option key={opt.value} value={opt.value}>
297
+ {opt.label}
298
+ </option>
299
+ ))}
300
+ </select>
291
301
  </div>
292
302
  {!isEmptyConditionMode(cond.mode) && (
293
303
  <div className="bpmn-gateway-branches__field">
@@ -1,7 +1,8 @@
1
1
  import { ApiOutlined, DeleteOutlined, EditOutlined, PlusOutlined } from '@ant-design/icons';
2
2
  import { useGlobalPopover } from '../../../../../shared/flow/PopoverContext';
3
3
  import { useReactFlow } from '@xyflow/react';
4
- import { Button, Form, Input, Select, Space, Switch, Tag, Tooltip, message } from 'antd';
4
+ import { Button, Form, Input, Space, Switch, Tag, Tooltip, message } from 'antd';
5
+ import { Select } from '../../../../../ui/antd';
5
6
  import { memo } from 'react';
6
7
 
7
8
  /** 统一 KV 参数:值可直接填,也可 Webhook POST 读取 */
@@ -1,5 +1,6 @@
1
1
  import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
2
- import { Button, Form, Input, InputNumber, Select, Space } from 'antd';
2
+ import { Button, Form, Input, InputNumber, Space } from 'antd';
3
+ import { Select } from '../../../../../ui/antd';
3
4
  import { memo, useCallback } from 'react';
4
5
  import { useReactFlow } from '@xyflow/react';
5
6
 
@@ -57,8 +57,8 @@ export const SERVICE_TYPE_OPTIONS = [
57
57
  { label: 'HTTP 调用', value: 'http' },
58
58
  ];
59
59
 
60
- /** 审批结果约定:UserTask 提交 / ExclusiveGateway 默认分支共用 */
61
- export const FLOW_ACTION_KEY = 'action';
60
+ /** 审批结果系统保留键(双下划线前缀,避免与业务字段冲突) */
61
+ export const FLOW_ACTION_KEY = '__action';
62
62
  export const FLOW_ACTION_APPROVE = 'approve';
63
63
  export const FLOW_ACTION_REJECT = 'reject';
64
64
 
@@ -103,17 +103,15 @@ export const validateFlowGraph = (nodes: Node[] = [], edges: Edge[] = []): FlowI
103
103
  if (!(outgoingByHandle.get(`${node.id}::${handle}`) ?? 0)) {
104
104
  issues.push({ level: 'error', message: `${label}:分支「${branchLabel}」未连出` });
105
105
  }
106
- // 非末条分支若条件 key 全空,引擎会跳过;末条作兜底。空 equal 曾会恒真导致回环死循环。
107
- const isLast = idx === branches.length - 1;
108
- if (!isLast) {
109
- const conditions = Array.isArray(branch?.conditions) ? branch.conditions : [];
110
- const hasKeyed = conditions.some((c: any) => String(c?.key ?? '').trim());
111
- if (!hasKeyed) {
112
- issues.push({
113
- level: 'warning',
114
- message: `${label}:分支「${branchLabel}」未配置条件字段,执行时不会命中(仅末条可作兜底)`,
115
- });
116
- }
106
+ // 条件 key 全空时不会命中;全部未命中引擎会报错(不再静默走末条)
107
+ const conditions = Array.isArray(branch?.conditions) ? branch.conditions : [];
108
+ const hasKeyed = conditions.length === 0
109
+ || conditions.some((c: any) => String(c?.key ?? '').trim());
110
+ if (!hasKeyed) {
111
+ issues.push({
112
+ level: 'warning',
113
+ message: `${label}:分支「${branchLabel}」未配置条件字段,执行时无法命中`,
114
+ });
117
115
  }
118
116
  });
119
117
  }
@@ -599,9 +599,71 @@
599
599
  }
600
600
 
601
601
  .ant-select,
602
- .ant-input {
602
+ .ant-input,
603
+ &__native-select {
603
604
  width: 100%;
604
605
  }
606
+
607
+ &__native-select {
608
+ box-sizing: border-box;
609
+ height: 32px;
610
+ padding: 4px 11px;
611
+ font-size: 14px;
612
+ line-height: 1.5714285714285714;
613
+ color: rgba(0, 0, 0, 0.88);
614
+ background: #fff;
615
+ border: 1px solid #d9d9d9;
616
+ border-radius: 6px;
617
+ outline: none;
618
+ transition: border-color 0.2s, box-shadow 0.2s;
619
+ appearance: auto;
620
+
621
+ &:hover {
622
+ border-color: #4096ff;
623
+ }
624
+
625
+ &:focus {
626
+ border-color: #1677ff;
627
+ box-shadow: 0 0 0 2px rgba(5, 145, 255, 0.1);
628
+ }
629
+ }
630
+
631
+ /* 宿主全局样式常把 Select 选中态字色洗成浅灰;强制可读 */
632
+ .ant-select-selector {
633
+ color: rgba(0, 0, 0, 0.88) !important;
634
+ }
635
+
636
+ .ant-select-selection-item {
637
+ color: rgba(0, 0, 0, 0.88) !important;
638
+ opacity: 1 !important;
639
+ }
640
+ }
641
+
642
+ /* Select 下拉(挂 body):压住宿主/Tailwind 对虚拟列表行高的干扰 */
643
+ .yyd-flow-select-dropdown {
644
+ z-index: 1100;
645
+
646
+ .rc-virtual-list-holder-inner {
647
+ transform: none !important;
648
+ }
649
+
650
+ .ant-select-item {
651
+ min-height: 32px !important;
652
+ height: 32px !important;
653
+ padding: 5px 12px !important;
654
+ line-height: 22px !important;
655
+ color: rgba(0, 0, 0, 0.88) !important;
656
+ margin: 0 !important;
657
+ }
658
+
659
+ .ant-select-item-option-content {
660
+ line-height: 22px !important;
661
+ color: rgba(0, 0, 0, 0.88) !important;
662
+ }
663
+
664
+ .ant-select-item-option-selected {
665
+ font-weight: 600;
666
+ }
605
667
  }
606
668
 
607
669
  /* ---- 来自 lowcode db/flow:工具栏 / handle 悬停(旧 global.less 会注入) ---- */
package/src/ui/antd.tsx CHANGED
@@ -1,2 +1,32 @@
1
+ import { Select as AntSelect } from 'antd';
2
+ import type { SelectProps } from 'antd';
3
+
1
4
  export { Card, Collapse, Dropdown, Modal, Popover, Tooltip } from 'antd';
2
5
  export type { MenuProps, TooltipProps } from 'antd';
6
+
7
+ /**
8
+ * 统一 Select:避免宿主全局行高把虚拟列表行距撑乱;
9
+ * antd5 用 popupClassName,antd4 overlay 会映射为 dropdownClassName。
10
+ */
11
+ export function Select(props: SelectProps) {
12
+ const {
13
+ listItemHeight = 32,
14
+ // 选项不多时关掉虚拟列表,避免宿主/Tailwind 行高把选项间距撑乱
15
+ virtual = false,
16
+ popupClassName,
17
+ // 挂到 body,避免属性面板 overflow / transform 裁切、错位
18
+ getPopupContainer = () => document.body,
19
+ ...rest
20
+ } = props;
21
+ return (
22
+ <AntSelect
23
+ {...rest}
24
+ virtual={virtual}
25
+ listItemHeight={listItemHeight}
26
+ popupClassName={['yyd-flow-select-dropdown', popupClassName].filter(Boolean).join(' ')}
27
+ getPopupContainer={getPopupContainer}
28
+ />
29
+ );
30
+ }
31
+
32
+ Object.assign(Select, AntSelect);