Skip to content

Commit 592c0a5

Browse files
xlorneclaude
andcommitted
refactor: 统一 Groovy 脚本相关服务到 script/service 目录
- 移除重复的 services 和 utils 目录,统一使用 script/service - 合并 TitleConfigModal 到 node-title-config-modal - 将变量选择器样式从 less 迁移到 scss - 添加样式规范到 CLAUDE.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 52cfe90 commit 592c0a5

18 files changed

Lines changed: 560 additions & 732 deletions

CLAUDE.md

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,11 @@ flow-types (类型定义)
135135
## 开发规范
136136

137137
- **与用户沟通及编写文档时,所有内容必须使用中文表述**
138+
- **在每次修改代码以后,要执行本地化的编译验证确保代码没有错误**
138139
- 前端包管理使用 pnpm(根据用户配置)
139140
- 前端文件命名规范:使用小写字母 + 下划线组合(如 `script_editor.tsx``variable_picker.tsx`
140141
- **前端导入规范**:引入当前文件夹下的内容使用 `./` 相对路径,引入其他模块的代码使用 `@/` 路径别名
142+
- **前端样式规范**:组件样式使用 `.module.scss` 模块化方式引入,禁止在 TSX 文件中使用内联 `style` 对象定义样式
141143
- 设计涉及流程或 UML 图形的解决方案时,使用 Mermaid Markdown 语法
142144
- 在编写计划的时候要遵循 TDD 的开发规范,务必要在方案中进行对实现代码逻辑的单元测试设计。
143145
- 在设计计划方案或执行方案过程中,对于代码的设计规划与调整修改要遵循本项目的代码风格和架构设计规则
@@ -158,14 +160,21 @@ import { GroovySyntaxConverter } from '../../../src/components/...';
158160

159161
### 面向对象开发规范
160162

161-
TypeScript 代码根据类型采用不同的开发风格
163+
TypeScript 代码根据类型和复杂度选择合适的开发风格
162164

163-
- **Service、Context、Convert、Utils 等业务处理类**:使用 class 面向对象方式定义,支持依赖注入和扩展
164165
- **Hooks**:使用函数式方式定义,遵循 React Hooks 规范
166+
- **业务处理类**(Service、Context、Converter、Utils 等):根据复杂度选择,复杂逻辑使用 class 便于扩展和维护,简单功能可用函数式
165167
- **工具函数**:根据场景选择,复杂逻辑使用 class,简单工具可用函数式
166168

167169
```typescript
168-
// ✅ 正确:使用 class 定义业务处理类
170+
// ✅ 正确:Hooks 使用函数式定义
171+
export const useFlowDesigner = () => {
172+
const [nodes, setNodes] = useState<Node[]>([]);
173+
// ...
174+
return { nodes, setNodes };
175+
};
176+
177+
// ✅ 正确:复杂业务逻辑使用 class 便于扩展
169178
export class GroovySyntaxConverter {
170179
private adapters: Map<ScriptType, ScriptAdapter> = new Map();
171180

@@ -176,16 +185,14 @@ export class GroovySyntaxConverter {
176185
public toScript(...): string { ... }
177186
}
178187

179-
// ✅ 正确:Hooks 使用函数式定义
180-
export const useFlowDesigner = () => {
181-
const [nodes, setNodes] = useState<Node[]>([]);
182-
// ...
183-
return { nodes, setNodes };
184-
};
185-
186188
// ✅ 正确:简单的工具函数可用函数式
187189
export const formatDate = (date: Date): string => {
188190
return date.toLocaleDateString();
189191
};
192+
193+
// ✅ 正确:简单的业务处理也可用函数式
194+
export const createDefaultMappings = (): GroovyVariableMapping[] => {
195+
return [...];
196+
};
190197
```
191198

frontend/packages/flow-pc/flow-pc-design/src/components/design-editor/node-components/scripts/components/variable-picker.module.less renamed to frontend/packages/flow-pc/flow-pc-design/src/components/design-editor/node-components/scripts/components/variable-picker.module.scss

File renamed without changes.

frontend/packages/flow-pc/flow-pc-design/src/components/design-editor/node-components/scripts/components/variable-picker.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import React, { useMemo, useState } from 'react';
22
import { Modal, Input, Empty } from 'antd';
33
import { SearchOutlined } from '@ant-design/icons';
44
import { GroovyVariableMapping } from '@flow-engine/flow-types';
5-
import { groovyVariableService } from '@/components/design-editor/script/service/groovy-variable-service';
6-
import styles from './variable-picker.module.less';
5+
import { GroovyVariableService } from '@/components/design-editor/script/service/groovy-variable-service';
6+
import styles from './variable-picker.module.scss';
77

88
export interface VariablePickerProps {
99
/** 变量映射列表 */
@@ -43,7 +43,7 @@ export const VariablePicker: React.FC<VariablePickerProps> = ({
4343

4444
// 按tag分组
4545
const groupedMappings = useMemo(() => {
46-
return groovyVariableService.groupByTag(filteredMappings);
46+
return GroovyVariableService.groupByTag(filteredMappings);
4747
}, [filteredMappings]);
4848

4949
const handleVariableClick = (mapping: GroovyVariableMapping) => {
@@ -75,11 +75,11 @@ export const VariablePicker: React.FC<VariablePickerProps> = ({
7575
{groupedMappings.size === 0 ? (
7676
<Empty description="未找到匹配的变量" />
7777
) : (
78-
Array.from(groupedMappings.entries()).map(([tag, variables]) => (
78+
Array.from(groupedMappings.entries()).map(([tag, variables]: [string, GroovyVariableMapping[]]) => (
7979
<div key={tag} className={styles.variableGroup}>
8080
<div className={styles.groupTitle}>{tag}</div>
8181
<div className={styles.variableItems}>
82-
{variables.map(variable => (
82+
{variables.map((variable: GroovyVariableMapping) => (
8383
<div
8484
key={variable.label}
8585
className={styles.variableItem}

frontend/packages/flow-pc/flow-pc-design/src/components/design-editor/node-components/scripts/condition-config-modal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React from 'react';
22
import { GroovyVariableMapping } from '@flow-engine/flow-types';
33
import { ScriptConfigModal, ScriptConfigModalProps } from './components/script-config-modal';
44
import { ScriptType } from '@/components/design-editor/typings/groovy-script';
5-
import { groovyVariableService } from '@/components/design-editor/script/service/groovy-variable-service';
5+
import { GroovyVariableService } from '@/components/design-editor/script/service/groovy-variable-service';
66

77
export interface ConditionConfigModalProps extends Omit<ScriptConfigModalProps, 'scriptType' | 'title'> {
88
/** 额外的变量(可选) */
@@ -21,7 +21,7 @@ export const ConditionConfigModal: React.FC<ConditionConfigModalProps> = ({
2121
extraVariables = [],
2222
}) => {
2323
// 获取系统变量
24-
const systemVariables = groovyVariableService.getSystemVariables(ScriptType.CONDITION);
24+
const systemVariables = GroovyVariableService.getSystemVariables(ScriptType.CONDITION);
2525

2626
// 合并变量
2727
const allVariables = [...systemVariables, ...extraVariables];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
.container {
2+
display: flex;
3+
flex-direction: column;
4+
gap: 16px;
5+
}
6+
7+
.section {
8+
display: flex;
9+
flex-direction: column;
10+
gap: 8px;
11+
}
12+
13+
.sectionLabel {
14+
font-size: 12px;
15+
color: rgba(0, 0, 0, 0.45);
16+
}
17+
18+
.preview {
19+
padding: 12px;
20+
background-color: rgba(0, 0, 0, 0.02);
21+
border-radius: 4px;
22+
min-height: 40px;
23+
color: rgba(0, 0, 0, 0.65);
24+
}
25+
26+
.hint {
27+
font-size: 12px;
28+
color: rgba(0, 0, 0, 0.25);
29+
}
30+
31+
.footer {
32+
display: flex;
33+
justify-content: flex-start;
34+
padding-top: 8px;
35+
border-top: 1px solid #f0f0f0;
36+
}
37+
38+
.pickerContainer {
39+
width: 400px;
40+
max-height: 300px;
41+
overflow: auto;
42+
}
43+
44+
.pickerList {
45+
max-height: 250px;
46+
overflow: auto;
47+
}
48+
49+
.pickerGroupTitle {
50+
font-size: 12px;
51+
font-weight: 500;
52+
color: rgba(0, 0, 0, 0.45);
53+
padding: 8px 0 4px;
54+
}
55+
56+
.pickerItems {
57+
display: flex;
58+
flex-wrap: wrap;
59+
gap: 8px;
60+
}
61+
62+
.pickerItem {
63+
padding: 4px 8px;
64+
background-color: #f5f5f5;
65+
border-radius: 4px;
66+
cursor: pointer;
67+
display: flex;
68+
flex-direction: column;
69+
gap: 2px;
70+
}
71+
72+
.pickerItemLabel {
73+
font-size: 13px;
74+
color: rgba(0, 0, 0, 0.88);
75+
}
76+
77+
.pickerItemValue {
78+
font-size: 11px;
79+
color: rgba(0, 0, 0, 0.45);
80+
}

0 commit comments

Comments
 (0)