@gadmin2n/schematics 0.0.107 → 0.0.108

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.
Files changed (45) hide show
  1. package/dist/lib/application/files/gadmin2-game-angle-demo/config/.types.d.ts +8 -9
  2. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/AgendaJob.ts +17 -15
  3. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Audit.ts +13 -17
  4. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Event.ts +48 -17
  5. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Game.ts +1 -2
  6. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/ITActivityDay.ts +14 -18
  7. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Log.ts +0 -1
  8. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Page.ts +42 -18
  9. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/PageResource.ts +28 -18
  10. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Resource.ts +42 -18
  11. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Role.ts +1 -2
  12. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/RolePages.ts +14 -18
  13. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/RoleResource.ts +28 -18
  14. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/SavedQuery.ts +13 -17
  15. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/User.ts +14 -18
  16. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowEventOutbox.ts +17 -17
  17. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowNodeInstance.ts +9 -14
  18. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowNodeType.ts +9 -14
  19. package/dist/lib/application/files/gadmin2-game-angle-demo/gitignore +1 -0
  20. package/dist/lib/application/files/gadmin2-game-angle-demo/server/package.json +1 -1
  21. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/temporal.service.ts +7 -1
  22. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/App.tsx +75 -71
  23. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/BulkActions.tsx +36 -6
  24. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/ListPageHeader.tsx +41 -14
  25. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/RowActions.tsx +153 -144
  26. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/inspectorActions.ts +3 -3
  27. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/agentAllowed.tsx +35 -0
  28. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/env.ts +2 -2
  29. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/DevShell.tsx +8 -2
  30. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/http.ts +20 -1
  31. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/list.tsx +48 -0
  32. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/plugins/devShellPlugin.ts +40 -2
  33. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/index.tsx +3 -2
  34. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/list.tsx +6 -6
  35. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasCell.tsx +4 -3
  36. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasListPage.tsx +4 -3
  37. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasPage.tsx +99 -5
  38. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasToolbar.tsx +28 -30
  39. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/CanvasAiModal.tsx +80 -0
  40. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/game/list.tsx +6 -0
  41. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/editor.tsx +2 -1
  42. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/NodeInstanceForm.tsx +2 -1
  43. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/show.tsx +2 -1
  44. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/list.tsx +6 -6
  45. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import React, { useCallback, useEffect, useRef, useState } from 'react';
2
- import { isAgentEnabled } from 'config/env';
2
+ import { useIsAgentAllowed } from 'config/agentAllowed';
3
3
  import {
4
4
  Alert,
5
5
  Badge,
@@ -156,6 +156,7 @@ function formatDuration(ms: number): string {
156
156
  export default function AgendaJobsPage() {
157
157
  const navigate = useNavigate();
158
158
  const [jobs, setJobs] = useState<JobItem[]>([]);
159
+ const isAgentAllowed = useIsAgentAllowed();
159
160
  const [overview, setOverview] = useState<Overview | null>(null);
160
161
  const [metricsOverview, setMetricsOverview] =
161
162
  useState<MetricsOverview | null>(null);
@@ -483,7 +484,7 @@ export default function AgendaJobsPage() {
483
484
  任务原始表
484
485
  </Button>
485
486
  </Tooltip>
486
- {isAgentEnabled && (
487
+ {isAgentAllowed && (
487
488
  <Button
488
489
  type="primary"
489
490
  icon={<PlusOutlined />}
@@ -177,7 +177,6 @@ export const AgendaJobList: React.FC<IResourceComponentsProps> = () => {
177
177
  exportLoading={exportSelectedLoading}
178
178
  t={t}
179
179
  resourceName={resourceName}
180
- showDelete={false}
181
180
  // Render props examples (uncomment to customize):
182
181
  // renderDeleteButton={(onClick, loading) => <Button danger onClick={onClick} loading={loading}>Delete</Button>}
183
182
  // renderSelectionCount={(count) => <Badge count={count}><Tag>Selected</Tag></Badge>}
@@ -186,12 +185,15 @@ export const AgendaJobList: React.FC<IResourceComponentsProps> = () => {
186
185
  ),
187
186
  extra: (
188
187
  <ListPageHeader
188
+ actions={[
189
+ ...tableConfig.toolbar.actions,
190
+ ...tableConfig.rowSelection.actions,
191
+ ]}
189
192
  importProps={importProps}
190
193
  onExport={triggerExport}
191
194
  exportLoading={exportLoading}
195
+ onRefresh={() => tableQueryResult.refetch()}
192
196
  resourceName={resourceName}
193
- showCreate={false}
194
- showImport={false}
195
197
  />
196
198
  ),
197
199
  }}
@@ -223,13 +225,11 @@ export const AgendaJobList: React.FC<IResourceComponentsProps> = () => {
223
225
  <RowActions
224
226
  record={record}
225
227
  actions={tableConfig.rowActions.actions}
228
+ visibleNum={tableConfig.rowActions.visibleNum}
226
229
  onUpdate={batchOps.updateOne}
227
230
  updateLoading={batchOps.updateManyIsLoading}
228
231
  t={t}
229
232
  resourceName={resourceName}
230
- showEdit={false}
231
- showDelete={false}
232
- showClone={false}
233
233
  // Render props examples (uncomment to customize):
234
234
  // showClone={false}
235
235
  // showDelete={false}
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import IsolatedLivePreview from './IsolatedLivePreview';
3
- import { isAgentEnabled } from 'config/env';
3
+ import { useIsAgentAllowed } from 'config/agentAllowed';
4
4
 
5
5
  interface CanvasCellProps extends React.HTMLAttributes<HTMLDivElement> {
6
6
  code: string;
@@ -34,6 +34,7 @@ const CanvasCell = React.forwardRef<HTMLDivElement, CanvasCellProps>(
34
34
  ref,
35
35
  ) => {
36
36
  const isSection = componentType === 'Section';
37
+ const isAgentAllowed = useIsAgentAllowed();
37
38
 
38
39
  return (
39
40
  <div
@@ -54,12 +55,12 @@ const CanvasCell = React.forwardRef<HTMLDivElement, CanvasCellProps>(
54
55
  onClick(e);
55
56
  }}
56
57
  onDoubleClick={(e) => {
57
- if (isPreview || !isAgentEnabled) return;
58
+ if (isPreview || !isAgentAllowed) return;
58
59
  e.stopPropagation();
59
60
  onDoubleClick(e);
60
61
  }}
61
62
  onContextMenu={(e) => {
62
- if (isPreview || !isAgentEnabled) return;
63
+ if (isPreview || !isAgentAllowed) return;
63
64
  e.preventDefault();
64
65
  e.stopPropagation();
65
66
  onContextMenu(e);
@@ -24,7 +24,7 @@ import IsolatedLivePreview from './IsolatedLivePreview';
24
24
  import { useTranslation } from 'react-i18next';
25
25
  import { useUserPageAccess } from 'hooks/useUserPageAccess';
26
26
  import { customRequest } from 'helpers/http';
27
- import { isAgentEnabled } from 'config/env';
27
+ import { useIsAgentAllowed } from 'config/agentAllowed';
28
28
 
29
29
  const COLS = 48;
30
30
  const ROW_HEIGHT = 10;
@@ -71,6 +71,7 @@ const CanvasListPage: React.FC = () => {
71
71
  const [canvases, setCanvases] = useState<SavedCanvas[]>([]);
72
72
  const [loading, setLoading] = useState(true);
73
73
  const { t } = useTranslation();
74
+ const isAgentAllowed = useIsAgentAllowed();
74
75
 
75
76
  const { roleNames } = useUserPageAccess();
76
77
  const isSystemAdmin = roleNames.includes('SYSTEM_ADMIN');
@@ -232,7 +233,7 @@ const CanvasListPage: React.FC = () => {
232
233
  <Typography.Title level={4} style={{ margin: 0 }}>
233
234
  {t('canvas.list.title')}
234
235
  </Typography.Title>
235
- {isAgentEnabled && (
236
+ {isAgentAllowed && (
236
237
  <Button
237
238
  type="primary"
238
239
  icon={<PlusOutlined />}
@@ -359,7 +360,7 @@ const CanvasListPage: React.FC = () => {
359
360
  {new Date(canvas.updatedAt).toLocaleString('zh-CN')}
360
361
  </span>
361
362
  <div style={{ display: 'flex', gap: 4 }}>
362
- {isAgentEnabled && (
363
+ {isAgentAllowed && (
363
364
  <>
364
365
  <Button
365
366
  type="text"
@@ -29,7 +29,7 @@ import { generatePrompt } from '@/components/agentPanel/promptGenerator';
29
29
  import { CANVAS_CONTEXT_MENU_REGISTRY } from './canvasContextMenuRegistry';
30
30
  import type { MenuActionContext } from './canvasContextMenuRegistry';
31
31
  import type { CanvasConfigModalProps } from './canvasConfigRegistry';
32
- import { isAgentEnabled } from 'config/env';
32
+ import { useIsAgentAllowed } from 'config/agentAllowed';
33
33
  import NumCardDataSourceModal from './components/NumCardDataSourceModal';
34
34
  import TableDataSourceModal from './components/TableDataSourceModal';
35
35
  import BarChartDataSourceModal from './components/BarChartDataSourceModal';
@@ -38,6 +38,7 @@ import RadarChartDataSourceModal from './components/RadarChartDataSourceModal';
38
38
  import MultiChartDataSourceModal from './components/MultiChartDataSourceModal';
39
39
  import TableConfigModal from './components/TableConfigModal';
40
40
  import PromptModal from './components/PromptModal';
41
+ import CanvasAiModal from './components/CanvasAiModal';
41
42
  import { createSectionCompactor } from './sectionCompactor';
42
43
  import type { CanvasItem as CanvasItemType } from './types';
43
44
  import { useTranslation } from 'react-i18next';
@@ -149,6 +150,7 @@ const CanvasPage: React.FC<CanvasPageProps> = ({
149
150
  const [isPreview, setIsPreview] = useState(false);
150
151
  const [editingId, setEditingId] = useState<string | null>(null);
151
152
  const [isDragging, setIsDragging] = useState(false);
153
+ const isAgentAllowed = useIsAgentAllowed();
152
154
  const [configModal, setConfigModal] = useState<{
153
155
  id: string;
154
156
  componentType: string;
@@ -160,6 +162,9 @@ const CanvasPage: React.FC<CanvasPageProps> = ({
160
162
  code: string;
161
163
  } | null>(null);
162
164
 
165
+ // ── AI 配置弹窗 state ──
166
+ const [aiModalOpen, setAiModalOpen] = useState(false);
167
+
163
168
  // ── PromptModal state(通用文本输入弹窗)──
164
169
  const [promptModal, setPromptModal] = useState<{
165
170
  label: string;
@@ -218,6 +223,56 @@ const CanvasPage: React.FC<CanvasPageProps> = ({
218
223
  [agent],
219
224
  );
220
225
 
226
+ // ── AI 配置:构造包含全量 canvas skill + 所有 items 上下文的 prompt ──
227
+ const handleAiSubmit = useCallback(
228
+ (userPrompt: string) => {
229
+ if (!agent) return;
230
+ const parts: string[] = [];
231
+
232
+ parts.push(`请帮我实现这个功能:${userPrompt}`);
233
+ parts.push('');
234
+ parts.push('严格按照以下 skill 完成任务:');
235
+ parts.push(
236
+ '1. **canvas-component-edit skill**(位于 .claude/skills/canvas-component-edit/SKILL.md):修改已有组件的流程和推送(POST /canvas-patch)',
237
+ );
238
+ parts.push(
239
+ '2. **canvas-item-create skill**(位于 .claude/skills/canvas-item-create/SKILL.md):新增组件的流程和推送(POST /canvas-add-item)',
240
+ );
241
+ parts.push(
242
+ '3. **canvas-design-standard skill**(位于 .claude/skills/canvas-design-standard/SKILL.md):所有 UI 代码规范,禁止原生 HTML 元素',
243
+ );
244
+ parts.push(
245
+ '4. **canvas-sql-query skill**(位于 .claude/skills/canvas-sql-query/SKILL.md):数据查询相关',
246
+ );
247
+ parts.push(
248
+ '5. **canvas skill**(位于 .claude/skills/canvas/SKILL.md):组件库总规范',
249
+ );
250
+ parts.push('');
251
+ parts.push('### 当前 Canvas 完整内容:');
252
+ parts.push(`共 ${items.length} 个组件:`);
253
+ items.forEach((item, idx) => {
254
+ parts.push('');
255
+ parts.push(
256
+ `#### 组件 ${idx + 1}:${item.componentType}(ID: ${item.id})`,
257
+ );
258
+ parts.push('```tsx');
259
+ parts.push(item.code);
260
+ parts.push('```');
261
+ });
262
+ parts.push('');
263
+ parts.push(
264
+ '- 修改已有组件:按照 canvas-component-edit skill 通过 POST /canvas-patch 推送新代码',
265
+ );
266
+ parts.push(
267
+ '- 新增组件:按照 canvas-item-create skill 通过 POST /canvas-add-item 推送',
268
+ );
269
+ parts.push('- 不要修改任何 .tsx 文件');
270
+
271
+ agent.sendPrompt(parts.join('\n'));
272
+ },
273
+ [agent, items],
274
+ );
275
+
221
276
  const { width: containerWidth, containerRef, mounted } = useContainerWidth();
222
277
 
223
278
  const liveRef = useRef({
@@ -320,6 +375,39 @@ const CanvasPage: React.FC<CanvasPageProps> = ({
320
375
  };
321
376
  }, [updateCode]);
322
377
 
378
+ // ── canvas:add-item HMR 监听 — agent 通过 POST /canvas-add-item 新增画布组件 ──
379
+ useEffect(() => {
380
+ if (!import.meta.hot) return;
381
+ const handler = ({
382
+ item,
383
+ layout,
384
+ }: {
385
+ item: { id: string; componentType: string; code: string };
386
+ layout: { x: number; y: number; w: number; h: number };
387
+ }) => {
388
+ const { items, layout: currentLayout, onBothChange } = liveRef.current;
389
+ onBothChange(
390
+ [...items, item],
391
+ [
392
+ ...currentLayout,
393
+ {
394
+ i: item.id,
395
+ x: layout.x,
396
+ y: layout.y,
397
+ w: layout.w,
398
+ h: layout.h,
399
+ minW: 4,
400
+ minH: 2,
401
+ },
402
+ ],
403
+ );
404
+ };
405
+ import.meta.hot.on('canvas:add-item', handler);
406
+ return () => {
407
+ import.meta.hot?.off('canvas:add-item', handler);
408
+ };
409
+ }, []);
410
+
323
411
  // ── MultiChart 工具栏切换图表类型时,同步更新代码中的 defaultVariant ──
324
412
  useEffect(() => {
325
413
  const handler = (e: Event) => {
@@ -705,6 +793,7 @@ const CanvasPage: React.FC<CanvasPageProps> = ({
705
793
  onPublish={onPublish}
706
794
  onUnpublish={onUnpublish}
707
795
  onPreview={() => setIsPreview(true)}
796
+ onAiConfig={() => setAiModalOpen(true)}
708
797
  />
709
798
  )}
710
799
 
@@ -779,14 +868,14 @@ const CanvasPage: React.FC<CanvasPageProps> = ({
779
868
  margin: [MARGIN_Y, MARGIN_Y] as const,
780
869
  }}
781
870
  dragConfig={{
782
- enabled: !isPreview && isAgentEnabled,
871
+ enabled: !isPreview && isAgentAllowed,
783
872
  handle: '.canvas-item-drag',
784
873
  }}
785
874
  resizeConfig={{
786
- enabled: !isPreview && isAgentEnabled,
875
+ enabled: !isPreview && isAgentAllowed,
787
876
  }}
788
- dropConfig={isPreview || !isAgentEnabled ? undefined : dropConfig}
789
- onDrop={isPreview || !isAgentEnabled ? undefined : handleDrop}
877
+ dropConfig={isPreview || !isAgentAllowed ? undefined : dropConfig}
878
+ onDrop={isPreview || !isAgentAllowed ? undefined : handleDrop}
790
879
  compactor={sectionCompactor}
791
880
  onResizeStop={handleResizeStop}
792
881
  onDragStart={() => setIsDragging(true)}
@@ -1509,6 +1598,11 @@ const CanvasPage: React.FC<CanvasPageProps> = ({
1509
1598
  }}
1510
1599
  onCancel={() => setPromptModal(null)}
1511
1600
  />
1601
+ <CanvasAiModal
1602
+ open={aiModalOpen}
1603
+ onClose={() => setAiModalOpen(false)}
1604
+ onSubmit={handleAiSubmit}
1605
+ />
1512
1606
  </div>
1513
1607
  </div>
1514
1608
  );
@@ -1,12 +1,12 @@
1
1
  import React, { useCallback } from 'react';
2
2
  import { Button, Tooltip, Popover } from 'antd';
3
- import { isAgentEnabled } from 'config/env';
3
+ import { useIsAgentAllowed } from 'config/agentAllowed';
4
4
  import {
5
5
  SaveOutlined,
6
6
  ArrowLeftOutlined,
7
7
  RocketOutlined,
8
- AppstoreOutlined,
9
8
  EyeOutlined,
9
+ RobotOutlined,
10
10
  } from '@ant-design/icons';
11
11
  import ComponentThumbnail from './ComponentThumbnail';
12
12
  import { CANVAS_COMPONENTS, CANVAS_DEFAULTS } from './canvasDefaults';
@@ -22,6 +22,7 @@ interface CanvasToolbarProps {
22
22
  onPublish: () => void;
23
23
  onUnpublish: () => void;
24
24
  onPreview: () => void;
25
+ onAiConfig: () => void;
25
26
  }
26
27
 
27
28
  const CanvasToolbar: React.FC<CanvasToolbarProps> = ({
@@ -33,8 +34,10 @@ const CanvasToolbar: React.FC<CanvasToolbarProps> = ({
33
34
  onPublish,
34
35
  onUnpublish,
35
36
  onPreview,
37
+ onAiConfig,
36
38
  }) => {
37
39
  const { t } = useTranslation();
40
+ const isAgentAllowed = useIsAgentAllowed();
38
41
 
39
42
  const handleVariantDragStart = useCallback(
40
43
  (e: React.DragEvent, componentType: string, variantCode: string) => {
@@ -102,31 +105,8 @@ const CanvasToolbar: React.FC<CanvasToolbarProps> = ({
102
105
  </span>
103
106
  </div>
104
107
 
105
- {/* 中间: 组件库标题 */}
106
- <div
107
- style={{
108
- display: 'flex',
109
- alignItems: 'center',
110
- justifyContent: 'center',
111
- }}
112
- >
113
- <Button
114
- size="small"
115
- icon={<AppstoreOutlined />}
116
- style={{
117
- fontSize: 13,
118
- fontWeight: 500,
119
- borderRadius: 8,
120
- border: 'none',
121
- background: '#4361ee',
122
- color: '#fff',
123
- boxShadow: '0 2px 8px rgba(67,97,238,0.3)',
124
- cursor: 'default',
125
- }}
126
- >
127
- {t('canvas.componentLib')}
128
- </Button>
129
- </div>
108
+ {/* 中间: 占位(保持左右对称布局) */}
109
+ <div />
130
110
 
131
111
  {/* 右侧: 保存 + 发布 */}
132
112
  <div
@@ -138,7 +118,25 @@ const CanvasToolbar: React.FC<CanvasToolbarProps> = ({
138
118
  gap: 10,
139
119
  }}
140
120
  >
141
- {isAgentEnabled && (
121
+ {isAgentAllowed && (
122
+ <Button
123
+ size="small"
124
+ icon={<RobotOutlined />}
125
+ onClick={onAiConfig}
126
+ style={{
127
+ borderRadius: 8,
128
+ border: 'none',
129
+ background: '#4361ee',
130
+ color: '#fff',
131
+ fontWeight: 500,
132
+ boxShadow: '0 2px 12px rgba(67,97,238,0.45)',
133
+ transition: 'all 200ms ease',
134
+ }}
135
+ >
136
+ AI 配置
137
+ </Button>
138
+ )}
139
+ {isAgentAllowed && (
142
140
  <Button
143
141
  size="small"
144
142
  icon={<SaveOutlined />}
@@ -186,7 +184,7 @@ const CanvasToolbar: React.FC<CanvasToolbarProps> = ({
186
184
  >
187
185
  {t('canvas.preview')}
188
186
  </Button>
189
- {isAgentEnabled && (
187
+ {isAgentAllowed && (
190
188
  <Button
191
189
  size="small"
192
190
  icon={<RocketOutlined />}
@@ -208,7 +206,7 @@ const CanvasToolbar: React.FC<CanvasToolbarProps> = ({
208
206
  </div>
209
207
 
210
208
  {/* ── Thumbnail row (only in dev) ── */}
211
- {isAgentEnabled && (
209
+ {isAgentAllowed && (
212
210
  <div
213
211
  style={{
214
212
  display: 'flex',
@@ -0,0 +1,80 @@
1
+ import React, { useState, useEffect, useRef } from 'react';
2
+ import { Modal, Input } from 'antd';
3
+ import type { TextAreaRef } from 'antd/es/input/TextArea';
4
+ import { CANVAS_MODAL_TITLE_STYLE } from './canvasModalProps';
5
+
6
+ export interface CanvasAiModalProps {
7
+ /** 控制弹窗开关 */
8
+ open: boolean;
9
+ /** 关闭回调 */
10
+ onClose: () => void;
11
+ /** 提交回调,返回用户输入的 prompt(已 trim) */
12
+ onSubmit: (prompt: string) => void;
13
+ }
14
+
15
+ /**
16
+ * Canvas AI 配置弹窗 —— 用于向 AI 发送对整个 canvas 页面的配置指令。
17
+ * 特点:多行输入、自动聚焦、Ctrl+Enter 确认、ESC 取消。
18
+ */
19
+ const CanvasAiModal: React.FC<CanvasAiModalProps> = ({
20
+ open,
21
+ onClose,
22
+ onSubmit,
23
+ }) => {
24
+ const [value, setValue] = useState('');
25
+ const textAreaRef = useRef<TextAreaRef>(null);
26
+
27
+ useEffect(() => {
28
+ if (open) {
29
+ setValue('');
30
+ requestAnimationFrame(() => {
31
+ textAreaRef.current?.focus();
32
+ });
33
+ }
34
+ }, [open]);
35
+
36
+ const handleOk = () => {
37
+ const trimmed = value.trim();
38
+ if (!trimmed) return;
39
+ onSubmit(trimmed);
40
+ onClose();
41
+ };
42
+
43
+ return (
44
+ <Modal
45
+ width={520}
46
+ centered
47
+ destroyOnClose
48
+ closable={false}
49
+ styles={{
50
+ header: { padding: '16px 20px 0', marginBottom: 0 },
51
+ body: { padding: '12px 20px 16px' },
52
+ footer: { padding: '0 20px 16px', borderTop: 'none' },
53
+ }}
54
+ open={open}
55
+ onCancel={onClose}
56
+ onOk={handleOk}
57
+ okText="发送给 AI"
58
+ cancelText="取消"
59
+ title={<span style={CANVAS_MODAL_TITLE_STYLE}>AI 配置页面</span>}
60
+ >
61
+ <Input.TextArea
62
+ ref={textAreaRef}
63
+ value={value}
64
+ placeholder="描述你想要的页面效果,例如:把所有数字卡片改成蓝色主题,图表数据改为近7天趋势"
65
+ onChange={(e) => setValue(e.target.value)}
66
+ onKeyDown={(e) => {
67
+ if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {
68
+ e.preventDefault();
69
+ handleOk();
70
+ }
71
+ }}
72
+ style={{ borderRadius: 6 }}
73
+ autoSize={{ minRows: 4, maxRows: 10 }}
74
+ allowClear
75
+ />
76
+ </Modal>
77
+ );
78
+ };
79
+
80
+ export default CanvasAiModal;
@@ -180,9 +180,14 @@ export const GameList: React.FC<IResourceComponentsProps> = () => {
180
180
  ),
181
181
  extra: (
182
182
  <ListPageHeader
183
+ actions={[
184
+ ...tableConfig.toolbar.actions,
185
+ ...tableConfig.rowSelection.actions,
186
+ ]}
183
187
  importProps={importProps}
184
188
  onExport={triggerExport}
185
189
  exportLoading={exportLoading}
190
+ onRefresh={() => tableQueryResult.refetch()}
186
191
  resourceName={resourceName}
187
192
  />
188
193
  ),
@@ -215,6 +220,7 @@ export const GameList: React.FC<IResourceComponentsProps> = () => {
215
220
  <RowActions
216
221
  record={record}
217
222
  actions={tableConfig.rowActions.actions}
223
+ visibleNum={tableConfig.rowActions.visibleNum}
218
224
  onUpdate={batchOps.updateOne}
219
225
  updateLoading={batchOps.updateManyIsLoading}
220
226
  t={t}
@@ -31,7 +31,7 @@ import { FlowRenderer } from './components/FlowRenderer';
31
31
  import { NodePropertyPanel } from './components/NodePropertyPanel';
32
32
  import { DslView, type DslViewHandle } from './components/DslView';
33
33
  import { useWorkflowAgent } from './hooks/useWorkflowAgent';
34
- import { isAgentEnabled as isDev } from 'config/env';
34
+ import { useIsAgentAllowed } from 'config/agentAllowed';
35
35
  import type {
36
36
  Workflow,
37
37
  WorkflowDSL,
@@ -55,6 +55,7 @@ export default function WorkflowEditorPage() {
55
55
  const [versions, setVersions] = useState<WorkflowVersion[]>([]);
56
56
  const [nodeTypes, setNodeTypes] = useState<WorkflowNodeType[]>([]);
57
57
  const [loading, setLoading] = useState(!isNewMode);
58
+ const isDev = useIsAgentAllowed();
58
59
 
59
60
  const [dsl, setDsl] = useState<WorkflowDSL | null>(null);
60
61
  const [currentVersion, setCurrentVersion] = useState<number | null>(null);
@@ -19,7 +19,7 @@ import {
19
19
  import type { WorkflowNodeType } from '../../types';
20
20
 
21
21
  const { Title } = Typography;
22
- import { isAgentEnabled as isDev } from 'config/env';
22
+ import { useIsAgentAllowed } from 'config/agentAllowed';
23
23
 
24
24
  interface NodeInstanceFormProps {
25
25
  form: FormInstance;
@@ -43,6 +43,7 @@ export function NodeInstanceForm({
43
43
  onBack,
44
44
  }: NodeInstanceFormProps) {
45
45
  const [aiModalOpen, setAiModalOpen] = useState(false);
46
+ const isDev = useIsAgentAllowed();
46
47
 
47
48
  const selectedNodeTypeId = Form.useWatch('nodeTypeId', form);
48
49
 
@@ -48,7 +48,7 @@ const STATUS_COLOR: Record<string, string> = {
48
48
  PUBLISHED: 'success',
49
49
  };
50
50
 
51
- import { isAgentEnabled as isDev } from 'config/env';
51
+ import { useIsAgentAllowed } from 'config/agentAllowed';
52
52
 
53
53
  export default function WorkflowShowPage() {
54
54
  const { id } = useParams<{ id: string }>();
@@ -58,6 +58,7 @@ export default function WorkflowShowPage() {
58
58
  const [versions, setVersions] = useState<WorkflowVersion[]>([]);
59
59
  const [nodeTypes, setNodeTypes] = useState<WorkflowNodeType[]>([]);
60
60
  const [loading, setLoading] = useState(true);
61
+ const isDev = useIsAgentAllowed();
61
62
 
62
63
  const [dsl, setDsl] = useState<WorkflowDSL | null>(null);
63
64
  const [currentVersion, setCurrentVersion] = useState<number | null>(null);
@@ -186,7 +186,6 @@ export const WorkflowEventOutboxList: React.FC<
186
186
  exportLoading={exportSelectedLoading}
187
187
  t={t}
188
188
  resourceName={resourceName}
189
- showDelete={false}
190
189
  // Render props examples (uncomment to customize):
191
190
  // renderDeleteButton={(onClick, loading) => <Button danger onClick={onClick} loading={loading}>Delete</Button>}
192
191
  // renderSelectionCount={(count) => <Badge count={count}><Tag>Selected</Tag></Badge>}
@@ -195,12 +194,15 @@ export const WorkflowEventOutboxList: React.FC<
195
194
  ),
196
195
  extra: (
197
196
  <ListPageHeader
197
+ actions={[
198
+ ...tableConfig.toolbar.actions,
199
+ ...tableConfig.rowSelection.actions,
200
+ ]}
198
201
  importProps={importProps}
199
202
  onExport={triggerExport}
200
203
  exportLoading={exportLoading}
204
+ onRefresh={() => tableQueryResult.refetch()}
201
205
  resourceName={resourceName}
202
- showCreate={false}
203
- showImport={false}
204
206
  />
205
207
  ),
206
208
  }}
@@ -232,13 +234,11 @@ export const WorkflowEventOutboxList: React.FC<
232
234
  <RowActions
233
235
  record={record}
234
236
  actions={tableConfig.rowActions.actions}
237
+ visibleNum={tableConfig.rowActions.visibleNum}
235
238
  onUpdate={batchOps.updateOne}
236
239
  updateLoading={batchOps.updateManyIsLoading}
237
240
  t={t}
238
241
  resourceName={resourceName}
239
- showEdit={false}
240
- showDelete={false}
241
- showClone={false}
242
242
  // Render props examples (uncomment to customize):
243
243
  // showClone={false}
244
244
  // showDelete={false}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gadmin2n/schematics",
3
- "version": "0.0.107",
3
+ "version": "0.0.108",
4
4
  "description": "Gadmin - modern, fast, powerful node.js web framework (@schematics)",
5
5
  "main": "dist/index.js",
6
6
  "files": [