@zat-design/sisyphus-scene 4.5.9 → 4.5.10-beta.2

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.
@@ -38,30 +38,36 @@ if (!['sisyphus-scene', 'sisyphus-scene-legacy'].includes(options.skill)) {
38
38
  throw new Error(`不支持的 skill:${options.skill}`);
39
39
  }
40
40
 
41
- const platform = options.platform === 'all'
42
- ? 'claude,cursor,codex'
43
- : options.platform;
41
+ const platform = options.platform === 'all' ? 'claude,cursor,codex' : options.platform;
44
42
  const selectedPlatforms = platform.split(',');
45
43
  for (const item of selectedPlatforms) {
46
44
  if (!['claude', 'cursor', 'codex'].includes(item)) throw new Error(`不支持的平台:${item}`);
47
45
  }
48
46
 
49
- const run = (script, args) => execFileSync(process.execPath, [path.join(scripts, script), ...args], {
50
- encoding: 'utf8',
51
- stdio: ['ignore', 'pipe', 'pipe'],
52
- });
47
+ const run = (script, args) =>
48
+ execFileSync(process.execPath, [path.join(scripts, script), ...args], {
49
+ encoding: 'utf8',
50
+ stdio: ['ignore', 'pipe', 'pipe'],
51
+ });
53
52
 
54
53
  const skillArgs = [
55
- '--platform', platform,
56
- '--scope', options.scope,
57
- '--skill', options.skill,
58
- '--project', path.resolve(options.project),
54
+ '--platform',
55
+ platform,
56
+ '--scope',
57
+ options.scope,
58
+ '--skill',
59
+ options.skill,
60
+ '--project',
61
+ path.resolve(options.project),
59
62
  ];
60
63
  const configureMcp = options.skill === 'sisyphus-scene' && !options.skipMcp;
61
64
  const mcpArgs = [
62
- '--platform', platform,
63
- '--scope', options.scope,
64
- '--project', path.resolve(options.project),
65
+ '--platform',
66
+ platform,
67
+ '--scope',
68
+ options.scope,
69
+ '--project',
70
+ path.resolve(options.project),
65
71
  ];
66
72
 
67
73
  const preview = {
@@ -2,10 +2,7 @@
2
2
  "mcpServers": {
3
3
  "sisyphus-react": {
4
4
  "command": "npx",
5
- "args": [
6
- "-y",
7
- "@zat-design/sisyphus-react-mcp@4.5.9"
8
- ]
5
+ "args": ["-y", "@zat-design/sisyphus-react-mcp@4.5.10-beta.2"]
9
6
  }
10
7
  }
11
8
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zat-design/sisyphus-scene",
3
- "version": "4.5.9",
3
+ "version": "4.5.10-beta.2",
4
4
  "description": "Sisyphus 业务场景 Agent 技能,跨 Claude Code、Codex、Cursor 分发 Sisyphus 4 + Ant Design 6 场景与 MCP 配置",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -29,7 +29,8 @@ const parseArgs = (argv) => {
29
29
 
30
30
  const args = parseArgs(process.argv.slice(2));
31
31
  const platformInput = String(args.platform || 'all');
32
- const platforms = platformInput === 'all' ? ['claude', 'cursor', 'codex'] : platformInput.split(',');
32
+ const platforms =
33
+ platformInput === 'all' ? ['claude', 'cursor', 'codex'] : platformInput.split(',');
33
34
  const projectRoot = path.resolve(String(args.project || process.cwd()));
34
35
  const scope = String(args.scope || 'project');
35
36
  const write = Boolean(args.write);
@@ -49,32 +50,36 @@ const fragment = JSON.parse(fs.readFileSync(fragmentPath, 'utf8'));
49
50
  const server = fragment?.mcpServers?.['sisyphus-react'];
50
51
  if (!server || typeof server !== 'object') throw new Error(`MCP 片段无效:${fragmentPath}`);
51
52
 
52
- const targets = scope === 'user'
53
- ? {
54
- claude: path.join(os.homedir(), '.claude.json'),
55
- cursor: path.join(os.homedir(), '.cursor', 'mcp.json'),
56
- }
57
- : {
58
- claude: path.join(projectRoot, '.mcp.json'),
59
- cursor: path.join(projectRoot, '.cursor', 'mcp.json'),
60
- };
61
-
62
- const codexHome = scope === 'user'
63
- ? path.resolve(process.env.CODEX_HOME || path.join(os.homedir(), '.codex'))
64
- : path.join(projectRoot, '.codex');
53
+ const targets =
54
+ scope === 'user'
55
+ ? {
56
+ claude: path.join(os.homedir(), '.claude.json'),
57
+ cursor: path.join(os.homedir(), '.cursor', 'mcp.json'),
58
+ }
59
+ : {
60
+ claude: path.join(projectRoot, '.mcp.json'),
61
+ cursor: path.join(projectRoot, '.cursor', 'mcp.json'),
62
+ };
63
+
64
+ const codexHome =
65
+ scope === 'user'
66
+ ? path.resolve(process.env.CODEX_HOME || path.join(os.homedir(), '.codex'))
67
+ : path.join(projectRoot, '.codex');
65
68
 
66
69
  const codexEnv = { ...process.env, CODEX_HOME: codexHome };
67
70
 
68
- const runCodex = (commandArgs) => spawnSync('codex', commandArgs, {
69
- encoding: 'utf8',
70
- env: codexEnv,
71
- });
71
+ const runCodex = (commandArgs) =>
72
+ spawnSync('codex', commandArgs, {
73
+ encoding: 'utf8',
74
+ env: codexEnv,
75
+ });
72
76
 
73
77
  const inspectCodex = () => {
74
78
  if (!fs.existsSync(codexHome)) {
75
79
  const version = runCodex(['--version']);
76
80
  if (version.error?.code === 'ENOENT') throw new Error('未找到 Codex CLI,无法配置 Codex MCP。');
77
- if (version.status !== 0) throw new Error(`Codex CLI 不可用:${version.stderr || version.stdout}`);
81
+ if (version.status !== 0)
82
+ throw new Error(`Codex CLI 不可用:${version.stderr || version.stdout}`);
78
83
  return { status: 'missing' };
79
84
  }
80
85
 
@@ -90,7 +95,9 @@ const inspectCodex = () => {
90
95
  const transport = value.transport || value;
91
96
  const expectedArgs = server.args || [];
92
97
  if (transport.command !== server.command || !sameJson(transport.args || [], expectedArgs)) {
93
- throw new Error(`${path.join(codexHome, 'config.toml')} 已存在不同的 sisyphus-react 配置;请人工确认。`);
98
+ throw new Error(
99
+ `${path.join(codexHome, 'config.toml')} 已存在不同的 sisyphus-react 配置;请人工确认。`,
100
+ );
94
101
  }
95
102
  return { status: 'unchanged' };
96
103
  };
@@ -102,7 +109,11 @@ const readConfig = (target) => {
102
109
  throw new Error(`${target} 必须是 JSON 对象。`);
103
110
  }
104
111
  if (value.mcpServers === undefined) value.mcpServers = {};
105
- if (!value.mcpServers || typeof value.mcpServers !== 'object' || Array.isArray(value.mcpServers)) {
112
+ if (
113
+ !value.mcpServers ||
114
+ typeof value.mcpServers !== 'object' ||
115
+ Array.isArray(value.mcpServers)
116
+ ) {
106
117
  throw new Error(`${target}.mcpServers 必须是对象。`);
107
118
  }
108
119
  return value;
@@ -112,10 +123,16 @@ const sameJson = (left, right) => {
112
123
  if (Object.is(left, right)) return true;
113
124
  if (!left || !right || typeof left !== 'object' || typeof right !== 'object') return false;
114
125
  if (Array.isArray(left) !== Array.isArray(right)) return false;
115
- if (Array.isArray(left)) return left.length === right.length && left.every((value, index) => sameJson(value, right[index]));
126
+ if (Array.isArray(left))
127
+ return (
128
+ left.length === right.length && left.every((value, index) => sameJson(value, right[index]))
129
+ );
116
130
  const leftKeys = Object.keys(left).sort();
117
131
  const rightKeys = Object.keys(right).sort();
118
- return leftKeys.length === rightKeys.length && leftKeys.every((key, index) => key === rightKeys[index] && sameJson(left[key], right[key]));
132
+ return (
133
+ leftKeys.length === rightKeys.length &&
134
+ leftKeys.every((key, index) => key === rightKeys[index] && sameJson(left[key], right[key]))
135
+ );
119
136
  };
120
137
  const results = [];
121
138
 
@@ -124,8 +141,16 @@ for (const platform of platforms) {
124
141
  const inspected = inspectCodex();
125
142
  if (inspected.status === 'missing' && write) {
126
143
  fs.mkdirSync(codexHome, { recursive: true });
127
- const result = runCodex(['mcp', 'add', 'sisyphus-react', '--', server.command, ...(server.args || [])]);
128
- if (result.status !== 0) throw new Error(`写入 Codex MCP 配置失败:${result.stderr || result.stdout}`);
144
+ const result = runCodex([
145
+ 'mcp',
146
+ 'add',
147
+ 'sisyphus-react',
148
+ '--',
149
+ server.command,
150
+ ...(server.args || []),
151
+ ]);
152
+ if (result.status !== 0)
153
+ throw new Error(`写入 Codex MCP 配置失败:${result.stderr || result.stdout}`);
129
154
  }
130
155
  results.push({
131
156
  platform,
@@ -155,4 +180,6 @@ for (const platform of platforms) {
155
180
  results.push({ platform, target, status: write ? 'added' : 'would-add' });
156
181
  }
157
182
 
158
- process.stdout.write(`${JSON.stringify({ projectRoot, scope, mode: write ? 'write' : 'check', results }, null, 2)}\n`);
183
+ process.stdout.write(
184
+ `${JSON.stringify({ projectRoot, scope, mode: write ? 'write' : 'check', results }, null, 2)}\n`,
185
+ );
@@ -1,8 +1,7 @@
1
1
  interface:
2
- display_name: "Sisyphus 业务场景生成"
3
- short_description: "从截图或需求生成可验证的保险业务页面脚手架"
4
- default_prompt: "Use $sisyphus-scene to match this requirement to a business scene and generate a verified React scaffold."
2
+ display_name: 'Sisyphus 业务场景生成'
3
+ short_description: '从截图或需求生成可验证的保险业务页面脚手架'
4
+ default_prompt: 'Use $sisyphus-scene to match this requirement to a business scene and generate a verified React scaffold.'
5
5
 
6
6
  policy:
7
7
  allow_implicit_invocation: true
8
-
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.5.9",
2
+ "version": "4.5.10-beta.2",
3
3
  "schemaVersion": 2,
4
4
  "tools": [
5
5
  "sisyphus-get-meta-status",
@@ -1,5 +1,6 @@
1
1
  import { Tabs } from 'antd';
2
2
  import { ProTable } from '@zat-design/sisyphus-react';
3
3
 
4
- export const InvalidFallback = () => <ProTable tableId="invalid" columns={[]} tabs={<Tabs items={[]} />} />;
5
-
4
+ export const InvalidFallback = () => (
5
+ <ProTable tableId="invalid" columns={[]} tabs={<Tabs items={[]} />} />
6
+ );
@@ -8,13 +8,13 @@
8
8
  "apiEvidence": {
9
9
  "tool": "sisyphus-get-component-api",
10
10
  "target": "ProForm",
11
- "libraryVersion": "4.5.9",
11
+ "libraryVersion": "4.5.10-beta.2",
12
12
  "schemaVersion": 2
13
13
  },
14
14
  "demoEvidence": {
15
15
  "tool": "sisyphus-get-example",
16
16
  "target": "ProForm/demos/base.tsx",
17
- "libraryVersion": "4.5.9",
17
+ "libraryVersion": "4.5.10-beta.2",
18
18
  "schemaVersion": 2,
19
19
  "exampleId": "ProForm/demos/base.tsx"
20
20
  }
@@ -28,13 +28,13 @@
28
28
  "apiEvidence": {
29
29
  "tool": "sisyphus-get-component-api",
30
30
  "target": "ProTable",
31
- "libraryVersion": "4.5.9",
31
+ "libraryVersion": "4.5.10-beta.2",
32
32
  "schemaVersion": 2
33
33
  },
34
34
  "demoEvidence": {
35
35
  "tool": "sisyphus-get-example",
36
36
  "target": "ProTable/demos/base.tsx",
37
- "libraryVersion": "4.5.9",
37
+ "libraryVersion": "4.5.10-beta.2",
38
38
  "schemaVersion": 2,
39
39
  "exampleId": "ProTable/demos/base.tsx"
40
40
  }
@@ -5,10 +5,13 @@ const { useAntdTable } = ProTable;
5
5
 
6
6
  export const PolicyQueryPage = () => {
7
7
  const [form] = ProForm.useForm();
8
- const { tableProps, onSearch, onReset } = useAntdTable(async () => ({ data: { list: [], total: 0 } }), {
9
- form,
10
- rowKey: 'id',
11
- });
8
+ const { tableProps, onSearch, onReset } = useAntdTable(
9
+ async () => ({ data: { list: [], total: 0 } }),
10
+ {
11
+ form,
12
+ rowKey: 'id',
13
+ },
14
+ );
12
15
 
13
16
  return (
14
17
  <>
@@ -22,4 +25,3 @@ export const PolicyQueryPage = () => {
22
25
  </>
23
26
  );
24
27
  };
25
-
@@ -1,13 +1,12 @@
1
1
  schema_version: 1
2
2
  should_trigger:
3
- - "根据这张截图生成一个保单查询列表页骨架"
4
- - "做一个带状态 Tab 和新增抽屉的理赔配置页面"
5
- - "参考 claim 应用实现一个多 Tab 详情编辑页"
6
- - "这个布局不在已有场景里,请根据 Sisyphus demo 组合"
7
- - "做一个右侧步骤锚点、统一校验的长表单"
3
+ - '根据这张截图生成一个保单查询列表页骨架'
4
+ - '做一个带状态 Tab 和新增抽屉的理赔配置页面'
5
+ - '参考 claim 应用实现一个多 Tab 详情编辑页'
6
+ - '这个布局不在已有场景里,请根据 Sisyphus demo 组合'
7
+ - '做一个右侧步骤锚点、统一校验的长表单'
8
8
  should_not_trigger:
9
- - "解释一下 React useEffect"
10
- - "修复这个现有组件的业务 bug"
11
- - "给 antd4 项目生成 CRUD 页面"
12
- - "给 Sisyphus v3 项目兼容一个旧页面"
13
-
9
+ - '解释一下 React useEffect'
10
+ - '修复这个现有组件的业务 bug'
11
+ - '给 antd4 项目生成 CRUD 页面'
12
+ - '给 Sisyphus v3 项目兼容一个旧页面'
@@ -7,7 +7,7 @@ examples: []
7
7
  # status: approved
8
8
  # application: xk-wjs-claim-web
9
9
  # capabilities: [search-form, data-table, table-tabs, drawer-form]
10
- # sisyphus_version: "4.5.9"
10
+ # sisyphus_version: "4.5.10-beta.2"
11
11
  # antd_range: ">=6 <7"
12
12
  # paths:
13
13
  # - src/pages/litigationManagement/index.tsx
@@ -9,28 +9,28 @@
9
9
 
10
10
  ## 页面原语
11
11
 
12
- | 能力 | 说明 |
13
- |---|---|
14
- | search-form | 查询条件与查询/重置行为 |
15
- | data-table | 表格、分页、加载和数据源 |
16
- | table-tabs | 同列表状态过滤或独立子页面切换 |
17
- | drawer-form | 新增、编辑、查看弹窗或抽屉 |
18
- | detail-navigation | 列表到详情、返回和 URL 状态 |
19
- | detail-tabs | 横向 Tab 切换的详情/编辑分区 |
20
- | detail-sections | 纵向详情或折叠分区 |
21
- | step-anchor-form | 纵向步骤锚点和跨分区统一校验 |
12
+ | 能力 | 说明 |
13
+ | ----------------- | ------------------------------ |
14
+ | search-form | 查询条件与查询/重置行为 |
15
+ | data-table | 表格、分页、加载和数据源 |
16
+ | table-tabs | 同列表状态过滤或独立子页面切换 |
17
+ | drawer-form | 新增、编辑、查看弹窗或抽屉 |
18
+ | detail-navigation | 列表到详情、返回和 URL 状态 |
19
+ | detail-tabs | 横向 Tab 切换的详情/编辑分区 |
20
+ | detail-sections | 纵向详情或折叠分区 |
21
+ | step-anchor-form | 纵向步骤锚点和跨分区统一校验 |
22
22
 
23
23
  ## 注册场景
24
24
 
25
- | 中文场景 | 必需能力 | 关键识别信号 |
26
- |---|---|---|
27
- | 查询列表页 | search-form + data-table | 查询区 + 表格 |
28
- | Tab 分组列表页 | search-form + data-table + table-tabs | 表格上方状态/业务 Tab |
29
- | 列表弹窗操作页 | search-form + data-table + drawer-form | 头部或操作列打开表单 |
30
- | 多 Tab 详情编辑页 | detail-tabs | 横向 Tab,一次显示一个分区 |
31
- | 分区块详情页 | detail-sections | 纵向分区,无步骤锚点 |
32
- | 列表跳转详情页 | data-table + detail-navigation + detail-* | 操作列进入独立详情路由 |
33
- | 步骤条分区表单页 | detail-sections + step-anchor-form | 纵向分区 + 右侧步骤锚点 + 统一校验 |
25
+ | 中文场景 | 必需能力 | 关键识别信号 |
26
+ | ----------------- | ------------------------------------------ | ---------------------------------- |
27
+ | 查询列表页 | search-form + data-table | 查询区 + 表格 |
28
+ | Tab 分组列表页 | search-form + data-table + table-tabs | 表格上方状态/业务 Tab |
29
+ | 列表弹窗操作页 | search-form + data-table + drawer-form | 头部或操作列打开表单 |
30
+ | 多 Tab 详情编辑页 | detail-tabs | 横向 Tab,一次显示一个分区 |
31
+ | 分区块详情页 | detail-sections | 纵向分区,无步骤锚点 |
32
+ | 列表跳转详情页 | data-table + detail-navigation + detail-\* | 操作列进入独立详情路由 |
33
+ | 步骤条分区表单页 | detail-sections + step-anchor-form | 纵向分区 + 右侧步骤锚点 + 统一校验 |
34
34
 
35
35
  ## 识别规则
36
36
 
@@ -48,4 +48,3 @@
48
48
  3. 对每个追加原语查询 Sisyphus demo。
49
49
  4. 组合后重新检查表单所有权、校验边界、数据源和导航职责。
50
50
  5. 组合冲突时以用户明确交互为准,必要时改为 `none` 并构造临时场景。
51
-
@@ -42,4 +42,3 @@
42
42
  6. GitNexus detect changes
43
43
 
44
44
  任一检查未执行都必须在交付报告中标注“未验证”,不能省略。
45
-
@@ -56,12 +56,12 @@
56
56
 
57
57
  每条 `CapabilityRequirement` 必须对应一条 `ComponentDecision`。
58
58
 
59
- | 状态 | 判定 | 下一步 |
60
- |---|---|---|
61
- | covered | API 与 demo 足以实现 | 进入生成 |
62
- | partial | 需要多个 Sisyphus 原语或项目适配 | 继续组合并复查 |
63
- | missing | MCP 明确无对应能力 | 允许查询 Ant Design |
64
- | unverified | MCP 不可用、版本不符或证据不足 | 立即阻断 |
59
+ | 状态 | 判定 | 下一步 |
60
+ | ---------- | -------------------------------- | ------------------- |
61
+ | covered | API 与 demo 足以实现 | 进入生成 |
62
+ | partial | 需要多个 Sisyphus 原语或项目适配 | 继续组合并复查 |
63
+ | missing | MCP 明确无对应能力 | 允许查询 Ant Design |
64
+ | unverified | MCP 不可用、版本不符或证据不足 | 立即阻断 |
65
65
 
66
66
  不得把“搜索没找到”“白名单没写”“记忆中不存在”判为 `missing`。
67
67
 
@@ -91,4 +91,3 @@ Ant Design 仍无法覆盖时检索项目公共组件。只使用有源码、调
91
91
  - 无法确认会改变公共接口或业务数据流的关键需求
92
92
 
93
93
  停止时输出已完成的证据、未解决能力、建议的独立前置任务,不用占位代码伪装完成。
94
-
@@ -226,4 +226,3 @@ const profile = {
226
226
  };
227
227
 
228
228
  process.stdout.write(`${JSON.stringify(profile, null, 2)}\n`);
229
-
@@ -39,9 +39,18 @@ if (!['copy', 'link'].includes(mode)) throw new Error(`不支持的 mode:${mod
39
39
 
40
40
  const projectRoot = path.resolve(String(args.project || process.cwd()));
41
41
  const platformDirectories = {
42
- claude: scope === 'user' ? path.join(os.homedir(), '.claude', 'skills') : path.join(projectRoot, '.claude', 'skills'),
43
- codex: scope === 'user' ? path.join(os.homedir(), '.agents', 'skills') : path.join(projectRoot, '.agents', 'skills'),
44
- cursor: scope === 'user' ? path.join(os.homedir(), '.cursor', 'skills') : path.join(projectRoot, '.cursor', 'skills'),
42
+ claude:
43
+ scope === 'user'
44
+ ? path.join(os.homedir(), '.claude', 'skills')
45
+ : path.join(projectRoot, '.claude', 'skills'),
46
+ codex:
47
+ scope === 'user'
48
+ ? path.join(os.homedir(), '.agents', 'skills')
49
+ : path.join(projectRoot, '.agents', 'skills'),
50
+ cursor:
51
+ scope === 'user'
52
+ ? path.join(os.homedir(), '.cursor', 'skills')
53
+ : path.join(projectRoot, '.cursor', 'skills'),
45
54
  };
46
55
 
47
56
  const selectedPlatforms = platform === 'all' ? Object.keys(platformDirectories) : [platform];
@@ -97,4 +106,3 @@ for (const name of selectedPlatforms) {
97
106
  }
98
107
 
99
108
  process.stdout.write(`${JSON.stringify({ source, mode, scope, dryRun, results }, null, 2)}\n`);
100
-
@@ -10,6 +10,7 @@ description: 基于旧版 @zat-design/sisyphus-react v3 与 antd4 规则生成
10
10
  ## 触发条件
11
11
 
12
12
  用户提供以下任意组合时触发:
13
+
13
14
  - 查询/搜索字段描述
14
15
  - 表格列描述
15
16
  - 抽屉/弹框表单字段描述
@@ -20,6 +21,7 @@ description: 基于旧版 @zat-design/sisyphus-react v3 与 antd4 规则生成
20
21
  触发后,首先从用户描述中提取以下信息。缺少必要项时主动追问,可选项缺失则使用默认值:
21
22
 
22
23
  ### 必要项
24
+
23
25
  1. **页面名称**(中文 + 英文,用于文件命名和注释)
24
26
  2. **查询字段**:字段名、label、类型
25
27
  3. **表格列**:字段名、label、渲染方式
@@ -27,6 +29,7 @@ description: 基于旧版 @zat-design/sisyphus-react v3 与 antd4 规则生成
27
29
  5. **主接口**:list / add / update 的 URL 和请求方法
28
30
 
29
31
  ### 可选项
32
+
30
33
  6. **抽屉表单字段**:字段名、label、类型、必填、联动规则(缺省时沿用查询字段生成基础表单)
31
34
  7. **是否分组**(ProCollapse):默认不分组;用户说"分组"或"分 XX 区域"时启用
32
35
  8. **字典映射字段**:需要用接口映射显示名的字段(如 teamId → teamName)
@@ -39,12 +42,12 @@ description: 基于旧版 @zat-design/sisyphus-react v3 与 antd4 规则生成
39
42
 
40
43
  **检查 package.json 确认版本:**
41
44
 
42
- | 特征 | v3 | v4 |
43
- |------|----|----|
44
- | `@zat-design/sisyphus-react` | `^3.x` | `^4.x` |
45
- | antd | `antd4` | `antd` |
46
- | 列类型 | `ProColumnProps` / `ProTableColumn` | `ProFormColumnType` / `ProTableColumnType` |
47
- | 日期 | `moment` | `dayjs` |
45
+ | 特征 | v3 | v4 |
46
+ | ---------------------------- | ----------------------------------- | ------------------------------------------ |
47
+ | `@zat-design/sisyphus-react` | `^3.x` | `^4.x` |
48
+ | antd | `antd4` | `antd` |
49
+ | 列类型 | `ProColumnProps` / `ProTableColumn` | `ProFormColumnType` / `ProTableColumnType` |
50
+ | 日期 | `moment` | `dayjs` |
48
51
 
49
52
  找不到 package.json 则询问用户版本,默认给 v3(当前项目主要版本)。
50
53
 
@@ -231,10 +234,15 @@ const XxxPage: React.FC = () => {
231
234
  form={searchForm}
232
235
  columns={formColumns}
233
236
  onFinish={() => refresh()}
234
- onCancel={() => { searchForm.resetFields(); refresh(); }}
237
+ onCancel={() => {
238
+ searchForm.resetFields();
239
+ refresh();
240
+ }}
235
241
  />
236
242
  <div style={{ margin: '0 0 12px' }}>
237
- <Button type="primary" onClick={handleAdd}>新增</Button>
243
+ <Button type="primary" onClick={handleAdd}>
244
+ 新增
245
+ </Button>
238
246
  </div>
239
247
  <ProTable
240
248
  {...tableProps}
@@ -272,14 +280,25 @@ export const getFormColumns = (): ProFormColumnType[] => [
272
280
  { type: 'Input', label: '工号', name: 'query_no' },
273
281
 
274
282
  // ProEnum:枚举下拉,allowClear 必加(查询表单允许清空)
275
- { type: 'ProEnum', label: '状态', name: 'onDuty', fieldProps: { code: 'onDuty', allowClear: true } },
283
+ {
284
+ type: 'ProEnum',
285
+ label: '状态',
286
+ name: 'onDuty',
287
+ fieldProps: { code: 'onDuty', allowClear: true },
288
+ },
276
289
 
277
290
  // Select/Radio 静态选项:用 dataSource(不是 options)
278
291
  {
279
292
  type: 'Select',
280
293
  label: '类型',
281
294
  name: 'type',
282
- fieldProps: { dataSource: [{ label: '启用', value: 'Y' }, { label: '停用', value: 'N' }], allowClear: true },
295
+ fieldProps: {
296
+ dataSource: [
297
+ { label: '启用', value: 'Y' },
298
+ { label: '停用', value: 'N' },
299
+ ],
300
+ allowClear: true,
301
+ },
283
302
  },
284
303
 
285
304
  // ProSelect:接口数据下拉
@@ -291,7 +310,7 @@ export const getFormColumns = (): ProFormColumnType[] => [
291
310
  allowClear: true,
292
311
  fieldNames: { label: 'teamName', value: 'id' },
293
312
  useRequest: { service: getTeamOptions },
294
- transformResponse: (res: any) => res?.data?.status === 200 ? res.data.data || [] : [],
313
+ transformResponse: (res: any) => (res?.data?.status === 200 ? res.data.data || [] : []),
295
314
  },
296
315
  },
297
316
  ];
@@ -321,9 +340,13 @@ const getTableColumns = (): ProTableColumnType[] => {
321
340
  width: 150,
322
341
  render: (_: any, record: XxxRecord) => (
323
342
  <Space>
324
- <Button type="link" onClick={() => handleEdit(record)}>编辑</Button>
343
+ <Button type="link" onClick={() => handleEdit(record)}>
344
+ 编辑
345
+ </Button>
325
346
  {record.enable === 'N' && (
326
- <Button type="link" danger onClick={() => handleDelete(record)}>删除</Button>
347
+ <Button type="link" danger onClick={() => handleDelete(record)}>
348
+ 删除
349
+ </Button>
327
350
  )}
328
351
  </Space>
329
352
  ),
@@ -332,7 +355,7 @@ const getTableColumns = (): ProTableColumnType[] => {
332
355
  };
333
356
 
334
357
  // JSX 调用
335
- <ProTable {...tableProps} rowKey="id" columns={getTableColumns()} scroll={{ x: 'max-content' }} />
358
+ <ProTable {...tableProps} rowKey="id" columns={getTableColumns()} scroll={{ x: 'max-content' }} />;
336
359
  ```
337
360
 
338
361
  操作列按钮如果逻辑复杂,可以提取为 `render` 辅助函数放在 `getTableColumns` 上方:
@@ -352,7 +375,9 @@ const getTableColumns = () => [
352
375
  width: 150,
353
376
  render: (_: any, record: XxxRecord) => (
354
377
  <Space>
355
- <Button type="link" onClick={() => handleEdit(record)}>编辑</Button>
378
+ <Button type="link" onClick={() => handleEdit(record)}>
379
+ 编辑
380
+ </Button>
356
381
  {renderStatusAction(record)}
357
382
  </Space>
358
383
  ),
@@ -365,7 +390,10 @@ const getTableColumns = () => [
365
390
  #### 默认模式(平铺,字段少时使用)
366
391
 
367
392
  ```tsx
368
- export const getModalFormColumns = (currentRecord?: XxxRecord | null, form?: any): ProFormColumnType[] => [
393
+ export const getModalFormColumns = (
394
+ currentRecord?: XxxRecord | null,
395
+ form?: any,
396
+ ): ProFormColumnType[] => [
369
397
  { type: 'Input', label: '名称', name: 'name', required: true },
370
398
 
371
399
  // ProSelect 多选
@@ -378,7 +406,7 @@ export const getModalFormColumns = (currentRecord?: XxxRecord | null, form?: any
378
406
  mode: 'multiple',
379
407
  fieldNames: { label: 'roleName', value: 'id' },
380
408
  useRequest: { service: getRoleOptions },
381
- transformResponse: (res: any) => res?.data?.status === 200 ? res.data.data || [] : [],
409
+ transformResponse: (res: any) => (res?.data?.status === 200 ? res.data.data || [] : []),
382
410
  },
383
411
  },
384
412
 
@@ -411,7 +439,7 @@ export const getModalFormColumns = (currentRecord?: XxxRecord | null, form?: any
411
439
  service: () => getLeaderList(values.dutieId),
412
440
  options: { ready: !!values.dutieId, refreshDeps: [values.dutieId] },
413
441
  },
414
- transformResponse: (res: any) => res?.data?.status === 200 ? res.data.data || [] : [],
442
+ transformResponse: (res: any) => (res?.data?.status === 200 ? res.data.data || [] : []),
415
443
  }),
416
444
  },
417
445
  ];
@@ -420,7 +448,10 @@ export const getModalFormColumns = (currentRecord?: XxxRecord | null, form?: any
420
448
  #### 分组模式(用户明确要求时)
421
449
 
422
450
  ```tsx
423
- export const getModalFormColumns = (currentRecord?: XxxRecord | null, form?: any): ProFormColumnType[] => [
451
+ export const getModalFormColumns = (
452
+ currentRecord?: XxxRecord | null,
453
+ form?: any,
454
+ ): ProFormColumnType[] => [
424
455
  {
425
456
  type: 'ProCollapse',
426
457
  fieldProps: {
@@ -437,9 +468,7 @@ export const getModalFormColumns = (currentRecord?: XxxRecord | null, form?: any
437
468
  fieldProps: {
438
469
  title: '服务范围',
439
470
  level: '2',
440
- children: [
441
- { type: 'Input', label: '软电账户', name: 'callNo', required: true },
442
- ],
471
+ children: [{ type: 'Input', label: '软电账户', name: 'callNo', required: true }],
443
472
  },
444
473
  },
445
474
  ];
@@ -455,11 +484,9 @@ import axios from '../../../../utils/intercept'; // 路径按项目层级调整
455
484
  export const getXxxList = (params: any) =>
456
485
  axios({ method: 'post', url: `/xxx/list/${params.pageSize}/${params.pageNum}`, data: params });
457
486
 
458
- export const addXxx = (data: any) =>
459
- axios({ method: 'post', url: '/xxx/add', data });
487
+ export const addXxx = (data: any) => axios({ method: 'post', url: '/xxx/add', data });
460
488
 
461
- export const updateXxx = (data: any) =>
462
- axios({ method: 'post', url: '/xxx/update', data });
489
+ export const updateXxx = (data: any) => axios({ method: 'post', url: '/xxx/update', data });
463
490
 
464
491
  // 字典接口(有字典映射时)
465
492
  // export const getXxxOptions = () =>
@@ -493,6 +520,7 @@ export interface XxxFormValues {
493
520
  **仅在有特殊转换时生成。无转换需求则不创建此文件。**
494
521
 
495
522
  常见需要转换的场景:
523
+
496
524
  - 多选数组 → 逗号分隔字符串(提交前)/ 逗号字符串 → 数组(回显)
497
525
  - `depId` 数字 → `[depId]` 数组(ProTree/ProCascader 回显)
498
526
  - 日期 moment/dayjs → 格式化字符串(提交前)
@@ -526,25 +554,30 @@ export const transformRecordToFormValues = (record: any): any => {
526
554
  生成代码时逐条核对:
527
555
 
528
556
  ### 状态
557
+
529
558
  - [ ] 多个状态用一个 `useSetState<PageState>`,不拆成多个 `useState`
530
559
  - [ ] PageState 用 interface 声明,不用内联类型
531
560
 
532
561
  ### Hooks 使用
562
+
533
563
  - [ ] `useMemo` 仅用于无外部依赖的纯配置(如 `getFormColumns()`)
534
564
  - [ ] `getTableColumns`(依赖 handler)不加 `useMemo`
535
565
  - [ ] `getModalFormColumns`(依赖运行时数据)不加 `useMemo`
536
566
  - [ ] `useEffect` 依赖数组不含函数、form 实例
537
567
 
538
568
  ### Placeholder
569
+
539
570
  - [ ] **禁止** `fieldProps: { placeholder: '请输入' }` 或 `placeholder: '请选择'`(组件自动添加)
540
571
  - [ ] 仅特殊 placeholder 才手动指定(如 `placeholder: '自动获取'`)
541
572
  - [ ] 如 fieldProps 只有 placeholder 且为默认值,移除整个 fieldProps
542
573
 
543
574
  ### 区块顺序
575
+
544
576
  - [ ] 导入 → Props/Hooks → 状态 → 配置 → 事件处理 → API → useEffect → JSX
545
577
  - [ ] 所有 `useEffect` 集中在 return 之前,不分散
546
578
 
547
579
  ### Config 纯净性
580
+
548
581
  - [ ] config 文件不含 `useState`/`useRequest`/`useEffect`
549
582
  - [ ] 运行时数据(dictMaps、form、currentRecord)通过参数传入
550
583
 
@@ -552,29 +585,29 @@ export const transformRecordToFormValues = (record: any): any => {
552
585
 
553
586
  ## 字段类型速查
554
587
 
555
- | 场景 | sisyphus type | 关键 fieldProps |
556
- |------|--------------|----------------|
557
- | 普通文本输入 | `Input` | `maxLength` |
558
- | 数字输入 | `InputNumber` | `min`, `max`, `precision` |
559
- | 静态选项下拉 | `Select` / `Radio` | `dataSource: [{label, value}]`(**不是 options**) |
560
- | 枚举/字典下拉 | `ProEnum` | `code`, `allowClear`, `mode: 'multiple'` |
561
- | 接口数据下拉 | `ProSelect` | `useRequest.service`, `transformResponse`, `fieldNames`, `mode` |
562
- | 树形选择 | `ProTree` | `mode: 'treeSelect'`, `useRequest`, `transformResponse`, `onFieldChange` |
563
- | 日期 | `DatePicker` | `valueType: 'date'` 或 `'dateTime'` |
564
- | 日期范围 | `RangePicker` | `valueType: 'date'` |
565
- | 分组折叠 | `ProCollapse` | `title`, `level: '2'`, `children: [...]` |
566
- | 文件上传 | `ProUpload` | 见 sisyphus-assistant |
588
+ | 场景 | sisyphus type | 关键 fieldProps |
589
+ | ------------- | ------------------ | ------------------------------------------------------------------------ |
590
+ | 普通文本输入 | `Input` | `maxLength` |
591
+ | 数字输入 | `InputNumber` | `min`, `max`, `precision` |
592
+ | 静态选项下拉 | `Select` / `Radio` | `dataSource: [{label, value}]`(**不是 options**) |
593
+ | 枚举/字典下拉 | `ProEnum` | `code`, `allowClear`, `mode: 'multiple'` |
594
+ | 接口数据下拉 | `ProSelect` | `useRequest.service`, `transformResponse`, `fieldNames`, `mode` |
595
+ | 树形选择 | `ProTree` | `mode: 'treeSelect'`, `useRequest`, `transformResponse`, `onFieldChange` |
596
+ | 日期 | `DatePicker` | `valueType: 'date'` 或 `'dateTime'` |
597
+ | 日期范围 | `RangePicker` | `valueType: 'date'` |
598
+ | 分组折叠 | `ProCollapse` | `title`, `level: '2'`, `children: [...]` |
599
+ | 文件上传 | `ProUpload` | 见 sisyphus-assistant |
567
600
 
568
601
  ---
569
602
 
570
603
  ## 联动规则速查
571
604
 
572
- | 需求 | 写法 |
573
- |------|------|
574
- | 条件显示字段 | `show: (values) => !!values.xxx` |
575
- | 动态必填 | `required: (values) => values.xxx === 'Y'` |
605
+ | 需求 | 写法 |
606
+ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
607
+ | 条件显示字段 | `show: (values) => !!values.xxx` |
608
+ | 动态必填 | `required: (values) => values.xxx === 'Y'` |
576
609
  | 选项依赖另一字段 | `fieldProps: (values) => ({ useRequest: { service: () => getXxx(values.dep), options: { ready: !!values.dep, refreshDeps: [values.dep] } } })` |
577
- | 字段变化时联动 | `fieldProps: { onFieldChange: (value, _, { form }) => form.setFieldValue('xxx', undefined) }` |
610
+ | 字段变化时联动 | `fieldProps: { onFieldChange: (value, _, { form }) => form.setFieldValue('xxx', undefined) }` |
578
611
 
579
612
  ---
580
613
 
@@ -597,6 +630,7 @@ export const transformRecordToFormValues = (record: any): any => {
597
630
  ## 示例
598
631
 
599
632
  **用户输入:**
633
+
600
634
  ```
601
635
  页面:角色管理(RolePage)
602
636
  查询:角色名(roleName:Input), 状态(status:ProEnum/code=status)
@@ -606,6 +640,7 @@ export const transformRecordToFormValues = (record: any): any => {
606
640
  ```
607
641
 
608
642
  **生成结果:**
643
+
609
644
  - 无 ProCollapse(字段少,默认平铺)
610
645
  - 无 utils(无特殊转换)
611
646
  - 无字典映射(状态用 enumName 直接渲染)
@@ -1,7 +1,7 @@
1
1
  interface:
2
- display_name: "Sisyphus 旧版业务页面"
3
- short_description: "仅为 v3 与 antd4 项目生成兼容页面"
4
- default_prompt: "Use $sisyphus-scene-legacy only for projects that explicitly use Sisyphus v3 or antd4."
2
+ display_name: 'Sisyphus 旧版业务页面'
3
+ short_description: '仅为 v3 与 antd4 项目生成兼容页面'
4
+ default_prompt: 'Use $sisyphus-scene-legacy only for projects that explicitly use Sisyphus v3 or antd4.'
5
5
 
6
6
  policy:
7
7
  allow_implicit_invocation: false