@gadmin2n/schematics 0.0.110 → 0.0.112
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/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Event.ts +0 -12
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/ITActivityDay.ts +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/taihu.ts +8 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/authProvider.ts +26 -27
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/DevShell.tsx +19 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/OnboardingModal.tsx +101 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/style.css +129 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/login.ts +0 -24
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useUserPageAccess.ts +17 -28
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/index.tsx +15 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/common.json +10 -9
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/common.json +12 -11
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasCell.tsx +103 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasComponentLibrary.tsx +449 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasPage.tsx +794 -713
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasToolbar.tsx +3 -239
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasContextMenuRegistry.tsx +3 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/hooks/useCanvasContextMenu.tsx +79 -8
- package/package.json +1 -1
package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasToolbar.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import { Button, Tooltip
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Button, Tooltip } from 'antd';
|
|
3
3
|
import { useIsAgentAllowed } from 'config/agentAllowed';
|
|
4
4
|
import {
|
|
5
5
|
SaveOutlined,
|
|
@@ -8,10 +8,7 @@ import {
|
|
|
8
8
|
EyeOutlined,
|
|
9
9
|
RobotOutlined,
|
|
10
10
|
} from '@ant-design/icons';
|
|
11
|
-
import ComponentThumbnail from './ComponentThumbnail';
|
|
12
|
-
import { CANVAS_COMPONENTS, CANVAS_DEFAULTS } from './canvasDefaults';
|
|
13
11
|
import { useTranslation } from 'react-i18next';
|
|
14
|
-
import { getComponentLabel, getVariantLabel } from './canvasI18n';
|
|
15
12
|
|
|
16
13
|
interface CanvasToolbarProps {
|
|
17
14
|
isDirty: boolean;
|
|
@@ -39,19 +36,6 @@ const CanvasToolbar: React.FC<CanvasToolbarProps> = ({
|
|
|
39
36
|
const { t } = useTranslation();
|
|
40
37
|
const isAgentAllowed = useIsAgentAllowed();
|
|
41
38
|
|
|
42
|
-
const handleVariantDragStart = useCallback(
|
|
43
|
-
(e: React.DragEvent, componentType: string, variantCode: string) => {
|
|
44
|
-
e.dataTransfer.setData('componentType', componentType);
|
|
45
|
-
e.dataTransfer.setData('variantCode', variantCode);
|
|
46
|
-
e.dataTransfer.setData(
|
|
47
|
-
`x-component-type/${componentType.toLowerCase()}`,
|
|
48
|
-
'',
|
|
49
|
-
);
|
|
50
|
-
e.dataTransfer.effectAllowed = 'copy';
|
|
51
|
-
},
|
|
52
|
-
[],
|
|
53
|
-
);
|
|
54
|
-
|
|
55
39
|
return (
|
|
56
40
|
<div
|
|
57
41
|
style={{
|
|
@@ -63,7 +47,6 @@ const CanvasToolbar: React.FC<CanvasToolbarProps> = ({
|
|
|
63
47
|
overflow: 'hidden',
|
|
64
48
|
}}
|
|
65
49
|
>
|
|
66
|
-
{/* ── Header row ── */}
|
|
67
50
|
<div
|
|
68
51
|
style={{
|
|
69
52
|
height: 52,
|
|
@@ -105,16 +88,11 @@ const CanvasToolbar: React.FC<CanvasToolbarProps> = ({
|
|
|
105
88
|
</span>
|
|
106
89
|
</div>
|
|
107
90
|
|
|
108
|
-
{/*
|
|
109
|
-
<div />
|
|
110
|
-
|
|
111
|
-
{/* 右侧: 保存 + 发布 */}
|
|
91
|
+
{/* 右侧: AI 配置 + 保存 + 预览 + 发布 */}
|
|
112
92
|
<div
|
|
113
93
|
style={{
|
|
114
|
-
flex: 1,
|
|
115
94
|
display: 'flex',
|
|
116
95
|
alignItems: 'center',
|
|
117
|
-
justifyContent: 'flex-end',
|
|
118
96
|
gap: 10,
|
|
119
97
|
}}
|
|
120
98
|
>
|
|
@@ -204,220 +182,6 @@ const CanvasToolbar: React.FC<CanvasToolbarProps> = ({
|
|
|
204
182
|
)}
|
|
205
183
|
</div>
|
|
206
184
|
</div>
|
|
207
|
-
|
|
208
|
-
{/* ── Thumbnail row (only in dev) ── */}
|
|
209
|
-
{isAgentAllowed && (
|
|
210
|
-
<div
|
|
211
|
-
style={{
|
|
212
|
-
display: 'flex',
|
|
213
|
-
alignItems: 'center',
|
|
214
|
-
gap: 24,
|
|
215
|
-
padding: '16px 24px 20px',
|
|
216
|
-
overflowX: 'auto',
|
|
217
|
-
overflowY: 'hidden',
|
|
218
|
-
borderTop: '1px solid #f0f0f0',
|
|
219
|
-
}}
|
|
220
|
-
>
|
|
221
|
-
{CANVAS_COMPONENTS.map((type) => {
|
|
222
|
-
const def = CANVAS_DEFAULTS[type];
|
|
223
|
-
const variants = def?.variants ?? [];
|
|
224
|
-
|
|
225
|
-
// ── 单 variant:thumbnail 直接可拖拽,跳过 Popover ──
|
|
226
|
-
if (variants.length === 1) {
|
|
227
|
-
return (
|
|
228
|
-
<div
|
|
229
|
-
key={type}
|
|
230
|
-
draggable
|
|
231
|
-
onDragStart={(e) =>
|
|
232
|
-
handleVariantDragStart(e, type, variants[0].code)
|
|
233
|
-
}
|
|
234
|
-
style={{
|
|
235
|
-
display: 'flex',
|
|
236
|
-
flexDirection: 'column',
|
|
237
|
-
alignItems: 'center',
|
|
238
|
-
gap: 8,
|
|
239
|
-
cursor: 'grab',
|
|
240
|
-
userSelect: 'none',
|
|
241
|
-
flexShrink: 0,
|
|
242
|
-
width: 140,
|
|
243
|
-
}}
|
|
244
|
-
>
|
|
245
|
-
<div
|
|
246
|
-
style={{
|
|
247
|
-
border: '1px solid #eaeaea',
|
|
248
|
-
borderRadius: 10,
|
|
249
|
-
overflow: 'hidden',
|
|
250
|
-
background: '#fff',
|
|
251
|
-
transition: 'all 200ms cubic-bezier(0.4, 0, 0.2, 1)',
|
|
252
|
-
}}
|
|
253
|
-
onMouseEnter={(e) => {
|
|
254
|
-
const el = e.currentTarget;
|
|
255
|
-
el.style.borderColor = '#4361ee';
|
|
256
|
-
el.style.boxShadow = '0 4px 16px rgba(67,97,238,0.12)';
|
|
257
|
-
el.style.transform = 'translateY(-3px) scale(1.03)';
|
|
258
|
-
}}
|
|
259
|
-
onMouseLeave={(e) => {
|
|
260
|
-
const el = e.currentTarget;
|
|
261
|
-
el.style.borderColor = '#eaeaea';
|
|
262
|
-
el.style.boxShadow = 'none';
|
|
263
|
-
el.style.transform = 'translateY(0) scale(1)';
|
|
264
|
-
}}
|
|
265
|
-
>
|
|
266
|
-
<ComponentThumbnail componentType={type} width={140} />
|
|
267
|
-
</div>
|
|
268
|
-
<span
|
|
269
|
-
style={{
|
|
270
|
-
fontSize: 11,
|
|
271
|
-
color: '#888',
|
|
272
|
-
fontWeight: 500,
|
|
273
|
-
letterSpacing: '0.3px',
|
|
274
|
-
textAlign: 'center',
|
|
275
|
-
pointerEvents: 'none',
|
|
276
|
-
}}
|
|
277
|
-
>
|
|
278
|
-
{getComponentLabel(type, t)}
|
|
279
|
-
</span>
|
|
280
|
-
</div>
|
|
281
|
-
);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// ── 多 variant:保持 Popover hover 展开 ──
|
|
285
|
-
const popoverContent = (
|
|
286
|
-
<div
|
|
287
|
-
style={{
|
|
288
|
-
display: 'flex',
|
|
289
|
-
alignItems: 'center',
|
|
290
|
-
gap: 16,
|
|
291
|
-
padding: 4,
|
|
292
|
-
}}
|
|
293
|
-
>
|
|
294
|
-
{variants.map((v) => (
|
|
295
|
-
<div
|
|
296
|
-
key={v.name}
|
|
297
|
-
draggable
|
|
298
|
-
onDragStart={(e) => handleVariantDragStart(e, type, v.code)}
|
|
299
|
-
style={{
|
|
300
|
-
display: 'flex',
|
|
301
|
-
flexDirection: 'column',
|
|
302
|
-
alignItems: 'center',
|
|
303
|
-
gap: 6,
|
|
304
|
-
cursor: 'grab',
|
|
305
|
-
userSelect: 'none',
|
|
306
|
-
flexShrink: 0,
|
|
307
|
-
}}
|
|
308
|
-
>
|
|
309
|
-
<div
|
|
310
|
-
style={{
|
|
311
|
-
border: '1px solid #e8e8e8',
|
|
312
|
-
borderRadius: 8,
|
|
313
|
-
overflow: 'hidden',
|
|
314
|
-
background: '#fff',
|
|
315
|
-
transition: 'all 180ms ease',
|
|
316
|
-
}}
|
|
317
|
-
onMouseEnter={(e) => {
|
|
318
|
-
const el = e.currentTarget;
|
|
319
|
-
el.style.borderColor = '#4361ee';
|
|
320
|
-
el.style.boxShadow = '0 4px 12px rgba(67,97,238,0.15)';
|
|
321
|
-
el.style.transform = 'translateY(-3px) scale(1.02)';
|
|
322
|
-
}}
|
|
323
|
-
onMouseLeave={(e) => {
|
|
324
|
-
const el = e.currentTarget;
|
|
325
|
-
el.style.borderColor = '#e8e8e8';
|
|
326
|
-
el.style.boxShadow = 'none';
|
|
327
|
-
el.style.transform = 'translateY(0) scale(1)';
|
|
328
|
-
}}
|
|
329
|
-
>
|
|
330
|
-
<ComponentThumbnail
|
|
331
|
-
componentType={type}
|
|
332
|
-
code={v.code}
|
|
333
|
-
width={124}
|
|
334
|
-
/>
|
|
335
|
-
</div>
|
|
336
|
-
<span
|
|
337
|
-
style={{
|
|
338
|
-
fontSize: 10,
|
|
339
|
-
color: '#666',
|
|
340
|
-
fontWeight: 500,
|
|
341
|
-
textAlign: 'center',
|
|
342
|
-
pointerEvents: 'none',
|
|
343
|
-
}}
|
|
344
|
-
>
|
|
345
|
-
{getVariantLabel(v.label, t)}
|
|
346
|
-
</span>
|
|
347
|
-
</div>
|
|
348
|
-
))}
|
|
349
|
-
</div>
|
|
350
|
-
);
|
|
351
|
-
|
|
352
|
-
return (
|
|
353
|
-
<Popover
|
|
354
|
-
key={type}
|
|
355
|
-
content={popoverContent}
|
|
356
|
-
title={
|
|
357
|
-
<span
|
|
358
|
-
style={{ fontSize: 12, fontWeight: 600, color: '#333' }}
|
|
359
|
-
>
|
|
360
|
-
{getComponentLabel(type, t)}
|
|
361
|
-
</span>
|
|
362
|
-
}
|
|
363
|
-
trigger="hover"
|
|
364
|
-
placement="bottomLeft"
|
|
365
|
-
mouseEnterDelay={0.2}
|
|
366
|
-
mouseLeaveDelay={0.3}
|
|
367
|
-
>
|
|
368
|
-
<div
|
|
369
|
-
style={{
|
|
370
|
-
display: 'flex',
|
|
371
|
-
flexDirection: 'column',
|
|
372
|
-
alignItems: 'center',
|
|
373
|
-
gap: 8,
|
|
374
|
-
cursor: 'grab',
|
|
375
|
-
userSelect: 'none',
|
|
376
|
-
flexShrink: 0,
|
|
377
|
-
width: 140,
|
|
378
|
-
}}
|
|
379
|
-
>
|
|
380
|
-
<div
|
|
381
|
-
style={{
|
|
382
|
-
border: '1px solid #eaeaea',
|
|
383
|
-
borderRadius: 10,
|
|
384
|
-
overflow: 'hidden',
|
|
385
|
-
background: '#fff',
|
|
386
|
-
transition: 'all 200ms cubic-bezier(0.4, 0, 0.2, 1)',
|
|
387
|
-
}}
|
|
388
|
-
onMouseEnter={(e) => {
|
|
389
|
-
const el = e.currentTarget;
|
|
390
|
-
el.style.borderColor = '#4361ee';
|
|
391
|
-
el.style.boxShadow = '0 4px 16px rgba(67,97,238,0.12)';
|
|
392
|
-
el.style.transform = 'translateY(-3px) scale(1.03)';
|
|
393
|
-
}}
|
|
394
|
-
onMouseLeave={(e) => {
|
|
395
|
-
const el = e.currentTarget;
|
|
396
|
-
el.style.borderColor = '#eaeaea';
|
|
397
|
-
el.style.boxShadow = 'none';
|
|
398
|
-
el.style.transform = 'translateY(0) scale(1)';
|
|
399
|
-
}}
|
|
400
|
-
>
|
|
401
|
-
<ComponentThumbnail componentType={type} width={140} />
|
|
402
|
-
</div>
|
|
403
|
-
<span
|
|
404
|
-
style={{
|
|
405
|
-
fontSize: 11,
|
|
406
|
-
color: '#888',
|
|
407
|
-
fontWeight: 500,
|
|
408
|
-
letterSpacing: '0.3px',
|
|
409
|
-
textAlign: 'center',
|
|
410
|
-
pointerEvents: 'none',
|
|
411
|
-
}}
|
|
412
|
-
>
|
|
413
|
-
{getComponentLabel(type, t)}
|
|
414
|
-
</span>
|
|
415
|
-
</div>
|
|
416
|
-
</Popover>
|
|
417
|
-
);
|
|
418
|
-
})}
|
|
419
|
-
</div>
|
|
420
|
-
)}
|
|
421
185
|
</div>
|
|
422
186
|
);
|
|
423
187
|
};
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
SwapOutlined,
|
|
8
8
|
DownloadOutlined,
|
|
9
9
|
SettingOutlined,
|
|
10
|
+
ColumnHeightOutlined,
|
|
10
11
|
} from '@ant-design/icons';
|
|
11
12
|
import {
|
|
12
13
|
readTableFlag,
|
|
@@ -597,8 +598,8 @@ function barChartActions(
|
|
|
597
598
|
: []),
|
|
598
599
|
{
|
|
599
600
|
key: 'bar-direction',
|
|
600
|
-
icon: <
|
|
601
|
-
label: t?.('canvas.menu.direction') ?? '
|
|
601
|
+
icon: <ColumnHeightOutlined />,
|
|
602
|
+
label: t?.('canvas.menu.direction') ?? '图表方向',
|
|
602
603
|
children: [
|
|
603
604
|
{
|
|
604
605
|
key: 'direction-vertical',
|
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
SettingOutlined,
|
|
8
8
|
DatabaseOutlined,
|
|
9
9
|
DeleteOutlined,
|
|
10
|
+
ToolOutlined,
|
|
11
|
+
EyeOutlined,
|
|
10
12
|
} from '@ant-design/icons';
|
|
11
13
|
import { CANVAS_CONFIG_REGISTRY } from '../canvasConfigRegistry';
|
|
12
14
|
import { CANVAS_CONTEXT_MENU_REGISTRY } from '../canvasContextMenuRegistry';
|
|
@@ -38,6 +40,51 @@ interface ItemMenuState {
|
|
|
38
40
|
id: string;
|
|
39
41
|
}
|
|
40
42
|
|
|
43
|
+
/** 显隐切换类菜单项的 key —— 这些会被收纳到「显示元素」子菜单 */
|
|
44
|
+
const VISIBILITY_TOGGLE_KEYS = new Set([
|
|
45
|
+
'toggle-grid',
|
|
46
|
+
'toggle-label',
|
|
47
|
+
'toggle-legend',
|
|
48
|
+
'toggle-axis',
|
|
49
|
+
'toggle-dots',
|
|
50
|
+
'toggle-dots-label',
|
|
51
|
+
'toggle-download',
|
|
52
|
+
]);
|
|
53
|
+
|
|
54
|
+
/** 把 specificActions 里的显隐切换项收纳到一个子菜单下 */
|
|
55
|
+
function regroupVisibilityToggles(
|
|
56
|
+
items: MenuProps['items'],
|
|
57
|
+
t: TFunction,
|
|
58
|
+
): MenuProps['items'] {
|
|
59
|
+
if (!items || items.length === 0) return items;
|
|
60
|
+
const visibility: NonNullable<MenuProps['items']> = [];
|
|
61
|
+
const rest: NonNullable<MenuProps['items']> = [];
|
|
62
|
+
for (const item of items) {
|
|
63
|
+
if (
|
|
64
|
+
item &&
|
|
65
|
+
typeof item === 'object' &&
|
|
66
|
+
'key' in item &&
|
|
67
|
+
typeof item.key === 'string' &&
|
|
68
|
+
VISIBILITY_TOGGLE_KEYS.has(item.key)
|
|
69
|
+
) {
|
|
70
|
+
// 子菜单里去掉 danger 红色,避免视觉过于扎眼
|
|
71
|
+
const { danger, icon: _icon, ...itemRest } = item as any;
|
|
72
|
+
visibility.push(itemRest);
|
|
73
|
+
} else {
|
|
74
|
+
rest.push(item);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// 少于 2 个不值得收
|
|
78
|
+
if (visibility.length < 2) return items;
|
|
79
|
+
rest.push({
|
|
80
|
+
key: 'visibility-group',
|
|
81
|
+
icon: <EyeOutlined />,
|
|
82
|
+
label: t('canvas.menu.visibilityGroup', { defaultValue: '显示元素' }),
|
|
83
|
+
children: visibility,
|
|
84
|
+
});
|
|
85
|
+
return rest;
|
|
86
|
+
}
|
|
87
|
+
|
|
41
88
|
/** 画布组件右键菜单:开关 state + 三层菜单项(组件特有 / 通用 / 代码级)的组装逻辑 */
|
|
42
89
|
export function useCanvasContextMenu({
|
|
43
90
|
items,
|
|
@@ -71,7 +118,7 @@ export function useCanvasContextMenu({
|
|
|
71
118
|
// ── 第 1 层:组件特有操作 ──
|
|
72
119
|
const specificActionsFactory =
|
|
73
120
|
CANVAS_CONTEXT_MENU_REGISTRY[componentType];
|
|
74
|
-
const
|
|
121
|
+
const rawSpecificActions = specificActionsFactory
|
|
75
122
|
? specificActionsFactory(
|
|
76
123
|
item?.code ?? '',
|
|
77
124
|
(newCode) => {
|
|
@@ -82,6 +129,8 @@ export function useCanvasContextMenu({
|
|
|
82
129
|
t,
|
|
83
130
|
)
|
|
84
131
|
: [];
|
|
132
|
+
// 把 grid/label/legend/axis/dots/download 等显隐项收纳到子菜单
|
|
133
|
+
const specificActions = regroupVisibilityToggles(rawSpecificActions, t);
|
|
85
134
|
|
|
86
135
|
// ── 第 2 层:通用操作(检查元素) ──
|
|
87
136
|
const commonActions: MenuProps['items'] = [
|
|
@@ -197,16 +246,19 @@ export function useCanvasContextMenu({
|
|
|
197
246
|
];
|
|
198
247
|
|
|
199
248
|
// ── 第 3 层:代码级操作 ──
|
|
200
|
-
const
|
|
249
|
+
const advancedActions: MenuProps['items'] = [
|
|
201
250
|
{
|
|
202
251
|
key: 'edit',
|
|
203
|
-
icon: <
|
|
204
|
-
label: t('canvas.
|
|
252
|
+
icon: <ToolOutlined />,
|
|
253
|
+
label: t('canvas.adjustCode', { defaultValue: '调整代码' }),
|
|
205
254
|
onClick: () => {
|
|
206
255
|
openEditCode(itemMenu.id);
|
|
207
256
|
setItemMenu(null);
|
|
208
257
|
},
|
|
209
258
|
},
|
|
259
|
+
];
|
|
260
|
+
|
|
261
|
+
const opActions: MenuProps['items'] = [
|
|
210
262
|
{
|
|
211
263
|
key: 'copy',
|
|
212
264
|
icon: <CopyOutlined />,
|
|
@@ -228,15 +280,34 @@ export function useCanvasContextMenu({
|
|
|
228
280
|
},
|
|
229
281
|
];
|
|
230
282
|
|
|
231
|
-
// ──
|
|
283
|
+
// ── 组装:分组标题 + 分割线 ──
|
|
232
284
|
const result: MenuProps['items'] = [];
|
|
233
285
|
if (specificActions && specificActions.length > 0) {
|
|
234
|
-
result.push(
|
|
286
|
+
result.push({
|
|
287
|
+
key: 'g-component',
|
|
288
|
+
type: 'group',
|
|
289
|
+
label: t('canvas.menuGroups.component', {
|
|
290
|
+
defaultValue: '组件设置',
|
|
291
|
+
}),
|
|
292
|
+
children: specificActions as any,
|
|
293
|
+
});
|
|
235
294
|
result.push({ type: 'divider' as const });
|
|
236
295
|
}
|
|
237
|
-
result.push(
|
|
296
|
+
result.push({
|
|
297
|
+
key: 'g-data',
|
|
298
|
+
type: 'group',
|
|
299
|
+
label: t('canvas.menuGroups.data', { defaultValue: '数据与样式' }),
|
|
300
|
+
children: commonActions as any,
|
|
301
|
+
});
|
|
302
|
+
result.push({ type: 'divider' as const });
|
|
303
|
+
result.push({
|
|
304
|
+
key: 'g-advanced',
|
|
305
|
+
type: 'group',
|
|
306
|
+
label: t('canvas.menuGroups.advanced', { defaultValue: '高级' }),
|
|
307
|
+
children: advancedActions as any,
|
|
308
|
+
});
|
|
238
309
|
result.push({ type: 'divider' as const });
|
|
239
|
-
result.push(...
|
|
310
|
+
result.push(...opActions);
|
|
240
311
|
|
|
241
312
|
return result;
|
|
242
313
|
})()
|