@gadmin2n/schematics 0.0.82 → 0.0.84
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/ITActivityDay.ts +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/package.json +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/lib/page-helpers.ts +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/{syncDataMngtPages.ts → sync-data-mngt-pages.ts} +25 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/App.tsx +1 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/inspectorActions.ts +68 -22
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/header.tsx +2 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/sider.tsx +14 -6
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +8 -6
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/DevShell.tsx +34 -20
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useDynamicResources.tsx +11 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/index.tsx +9 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/list.tsx +3 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/list.tsx +13 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/list.tsx +13 -3
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/list.tsx +13 -3
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/index.tsx +12 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/index.tsx +2 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/list.tsx +3 -1
- package/package.json +1 -1
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"migrate:status": "dotenv -e .env.local -e .env -- prisma migrate status",
|
|
27
27
|
"generate": "dotenv -e .env.local -e .env -- npx prisma generate",
|
|
28
28
|
"generate:dev": "npm run migrate:dev && dotenv -e .env.local -e .env -- npx prisma generate",
|
|
29
|
-
"postgenerate:dev": "dotenv -e .env.local -e .env -- ts-node scripts/
|
|
29
|
+
"postgenerate:dev": "dotenv -e .env.local -e .env -- ts-node scripts/sync-data-mngt-pages.ts && dotenv -e .env.local -e .env -- ts-node scripts/sync-resources.ts",
|
|
30
30
|
"generate:web": "dotenv -e .env.local -e .env -- npx prisma generate --generator react",
|
|
31
31
|
"generate:server": "dotenv -e .env.local -e .env -- npx prisma generate --generator client --generator nestjs",
|
|
32
32
|
"push:db": "dotenv -e .env.local -e .env -- prisma db push --skip-generate",
|
package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/lib/page-helpers.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* page-helpers.ts — 页面与权限管理的共享 DB 操作原语
|
|
3
3
|
*
|
|
4
4
|
* 接受 PrismaClient 作为参数,可被 CLI 脚本(page-manage.ts / permission-manage.ts)
|
|
5
|
-
* 和
|
|
5
|
+
* 和 ../sync-data-mngt-pages.ts / seed/permissions.ts)共同调用。
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { PrismaClient } from '@prisma/client';
|
|
@@ -7,6 +7,22 @@ import {
|
|
|
7
7
|
} from './lib/page-helpers';
|
|
8
8
|
import { readPrismaModels } from './prismaModels';
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Models whose Page record should be marked `isVirtual = true`,
|
|
12
|
+
* i.e. routes / resources / role grants are still seeded so that the page
|
|
13
|
+
* remains reachable by URL and protected by RBAC, but the page is hidden
|
|
14
|
+
* from the auto-generated 「系统管理 / 数据管理」 menu.
|
|
15
|
+
*
|
|
16
|
+
* Use this when a model's CRUD page is exposed elsewhere (e.g. embedded
|
|
17
|
+
* inside another custom admin page) instead of as its own menu entry.
|
|
18
|
+
*/
|
|
19
|
+
const HIDDEN_FROM_DATA_MNGT_MENU = new Set<string>([
|
|
20
|
+
// Surfaced via a button in /admin/agenda-jobs (Cron Jobs page).
|
|
21
|
+
'agendaJob',
|
|
22
|
+
// Surfaced via a button in /admin/workflow (Workflow list page).
|
|
23
|
+
'workflowEventOutbox',
|
|
24
|
+
]);
|
|
25
|
+
|
|
10
26
|
// ─── Main Seed Function ───────────────────────────────────────────────────────
|
|
11
27
|
|
|
12
28
|
/**
|
|
@@ -64,6 +80,7 @@ export async function seedDataMngtPages(prisma: PrismaClient): Promise<void> {
|
|
|
64
80
|
console.log(`[seedDataMngtPages] ── ${model.name} ──`);
|
|
65
81
|
|
|
66
82
|
const pagePath = `/admin/data-mngt/${model.slug}`;
|
|
83
|
+
const hideFromMenu = HIDDEN_FROM_DATA_MNGT_MENU.has(model.code);
|
|
67
84
|
|
|
68
85
|
// 1 + 2 + 3: Upsert page, resource, and PageResource link
|
|
69
86
|
const page = await upsertPage(
|
|
@@ -74,11 +91,17 @@ export async function seedDataMngtPages(prisma: PrismaClient): Promise<void> {
|
|
|
74
91
|
sortOrder: 2000 + index * 10,
|
|
75
92
|
parentId: dataMngtPage.id,
|
|
76
93
|
path: pagePath,
|
|
94
|
+
isVirtual: hideFromMenu,
|
|
77
95
|
},
|
|
78
|
-
|
|
96
|
+
// keep path in sync with model name on update;
|
|
97
|
+
// also force isVirtual when in the hide-from-menu list so existing
|
|
98
|
+
// rows get reconciled (otherwise the default upsertPage update is {}).
|
|
99
|
+
{ path: pagePath, ...(hideFromMenu && { isVirtual: true }) },
|
|
79
100
|
);
|
|
80
101
|
console.log(
|
|
81
|
-
`[seedDataMngtPages] Page upserted: ${page.code} → ${pagePath} (id=${
|
|
102
|
+
`[seedDataMngtPages] Page upserted: ${page.code} → ${pagePath} (id=${
|
|
103
|
+
page.id
|
|
104
|
+
})${hideFromMenu ? ' [hidden from menu]' : ''}`,
|
|
82
105
|
);
|
|
83
106
|
|
|
84
107
|
const resource = await bindResourceToPage(
|
|
@@ -236,6 +236,7 @@ export function getInspectorActions(
|
|
|
236
236
|
label: '修改字段值展示样式',
|
|
237
237
|
skill: 'list-column-render',
|
|
238
238
|
promptTemplate: `自定义 ${col(r, f)} 的渲染样式`,
|
|
239
|
+
promptPrefix: '具体要求:',
|
|
239
240
|
requiresInput: true,
|
|
240
241
|
inputPlaceholder:
|
|
241
242
|
'请描述样式要求,例如:用颜色区分状态,ACTIVE 显示绿色,INACTIVE 显示红色',
|
|
@@ -247,6 +248,7 @@ export function getInspectorActions(
|
|
|
247
248
|
skill: 'page-i18n',
|
|
248
249
|
promptTemplate: `修改 ${col(r, f)} 的显示名称(通过 i18n 翻译文件)`,
|
|
249
250
|
requiresInput: true,
|
|
251
|
+
promptPrefix: '修改为:',
|
|
250
252
|
inputPlaceholder:
|
|
251
253
|
'请分别提供中文和英文名称,例如:\n中文:审核状态\n英文:Review Status\n(翻译 key:resources.{resourceName}.fields.{fieldName})',
|
|
252
254
|
promptSuffix:
|
|
@@ -255,7 +257,8 @@ export function getInspectorActions(
|
|
|
255
257
|
{
|
|
256
258
|
label: '固定列',
|
|
257
259
|
skill: 'list-column-fixed',
|
|
258
|
-
promptTemplate: `将 ${col(r, f)}
|
|
260
|
+
promptTemplate: `将 ${col(r, f)} `,
|
|
261
|
+
promptPrefix: '固定到:',
|
|
259
262
|
requiresInput: true,
|
|
260
263
|
inputPlaceholder: '请指定固定方向:左 / 右',
|
|
261
264
|
promptSuffix:
|
|
@@ -309,12 +312,13 @@ export function getInspectorActions(
|
|
|
309
312
|
fieldSubMenu: 'add-before',
|
|
310
313
|
},
|
|
311
314
|
{
|
|
312
|
-
label: '
|
|
315
|
+
label: '在列中添加关联表的字段',
|
|
313
316
|
skill: 'list-extend-prisma-select',
|
|
314
|
-
promptTemplate: `为 ${col(r, f)}
|
|
317
|
+
promptTemplate: `为 ${col(r, f)} 添加关联表的字段展示`,
|
|
315
318
|
requiresInput: true,
|
|
319
|
+
promptPrefix: '要添加的字段:',
|
|
316
320
|
inputPlaceholder:
|
|
317
|
-
'
|
|
321
|
+
'请描述要添加的关联字段,例如:author.name 作者姓名',
|
|
318
322
|
promptSuffix:
|
|
319
323
|
'\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
|
|
320
324
|
},
|
|
@@ -323,7 +327,7 @@ export function getInspectorActions(
|
|
|
323
327
|
skill: null,
|
|
324
328
|
requiresInput: true,
|
|
325
329
|
promptTemplate: `对 ${r} 列表中的 "${f}" 列进行修改`,
|
|
326
|
-
promptPrefix: '
|
|
330
|
+
promptPrefix: '具体要求:',
|
|
327
331
|
inputPlaceholder: '请描述你希望 AI 执行的自定义操作',
|
|
328
332
|
promptSuffix:
|
|
329
333
|
'\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
|
|
@@ -351,6 +355,7 @@ export function getInspectorActions(
|
|
|
351
355
|
skill: 'page-i18n',
|
|
352
356
|
promptTemplate: `修改 ${formF(r, f)} 的显示名称(通过 i18n 翻译文件)`,
|
|
353
357
|
requiresInput: true,
|
|
358
|
+
promptPrefix: '修改为:',
|
|
354
359
|
inputPlaceholder:
|
|
355
360
|
'请分别提供中文和英文名称,例如:\n中文:游戏名称\n英文:Game Name\n(翻译 key:resources.{resourceName}.fields.{fieldName})',
|
|
356
361
|
promptSuffix:
|
|
@@ -360,6 +365,7 @@ export function getInspectorActions(
|
|
|
360
365
|
label: '字段旁添加帮助提示(含链接)',
|
|
361
366
|
skill: 'form-field-tooltip',
|
|
362
367
|
promptTemplate: `为 ${formF(r, f)} 添加 Tooltip 帮助提示(可包含链接)`,
|
|
368
|
+
promptPrefix: '要添加的提示内容:',
|
|
363
369
|
requiresInput: true,
|
|
364
370
|
inputPlaceholder:
|
|
365
371
|
'请描述提示内容,例如:\n提示文字"详见配置文档",链接 https://docs.example.com\n或纯文字:此字段用于关联上游系统的唯一标识',
|
|
@@ -370,6 +376,7 @@ export function getInspectorActions(
|
|
|
370
376
|
label: '字段联动(显/隐)',
|
|
371
377
|
skill: 'form-field-dependencies',
|
|
372
378
|
promptTemplate: `为 ${formF(r, f)} 添加联动依赖(显/隐依赖其他字段)`,
|
|
379
|
+
promptPrefix: '要添加的联动条件:',
|
|
373
380
|
requiresInput: true,
|
|
374
381
|
inputPlaceholder:
|
|
375
382
|
'请描述联动条件,例如:当"类型"字段值为"高级"时才显示此字段',
|
|
@@ -380,6 +387,7 @@ export function getInspectorActions(
|
|
|
380
387
|
label: '自定义校验逻辑',
|
|
381
388
|
skill: 'form-custom-validator',
|
|
382
389
|
promptTemplate: `为 ${formF(r, f)} 添加自定义校验规则`,
|
|
390
|
+
promptPrefix: '要添加的校验规则:',
|
|
383
391
|
requiresInput: true,
|
|
384
392
|
inputPlaceholder: '请描述校验规则,例如:必须是正整数且不超过 100',
|
|
385
393
|
promptSuffix:
|
|
@@ -389,6 +397,7 @@ export function getInspectorActions(
|
|
|
389
397
|
label: '改为级联选择器',
|
|
390
398
|
skill: 'form-cascader-component',
|
|
391
399
|
promptTemplate: `将 ${formF(r, f)} 替换为级联选择器`,
|
|
400
|
+
promptPrefix: '级联层级关系和数据来源:',
|
|
392
401
|
requiresInput: true,
|
|
393
402
|
inputPlaceholder:
|
|
394
403
|
'请描述级联层级和数据来源,例如:省 → 市 → 区,数据来自 /api/regions',
|
|
@@ -406,6 +415,7 @@ export function getInspectorActions(
|
|
|
406
415
|
label: '修改字段类型',
|
|
407
416
|
skill: 'prisma-schema-update',
|
|
408
417
|
promptTemplate: `修改 ${formF(r, f)} 的表单控件类型(@FormItem 注解)`,
|
|
418
|
+
promptPrefix: '修改为:',
|
|
409
419
|
requiresInput: true,
|
|
410
420
|
inputPlaceholder:
|
|
411
421
|
'请说明要改为什么控件类型,例如:改为下拉选择(Select DRAFT|PUBLISHED)、改为开关(Boolean)、改为多行文本(Text)、改为数字输入框(Number)',
|
|
@@ -428,6 +438,7 @@ export function getInspectorActions(
|
|
|
428
438
|
label: '字段选项从关联接口动态加载',
|
|
429
439
|
skill: 'form-load-related-data',
|
|
430
440
|
promptTemplate: `为 ${formF(r, f)} 的选项从关联接口动态加载`,
|
|
441
|
+
promptPrefix: '数据来源(接口):',
|
|
431
442
|
requiresInput: true,
|
|
432
443
|
inputPlaceholder:
|
|
433
444
|
'请描述数据来源接口,例如:从 /api/games 加载游戏列表作为下拉选项',
|
|
@@ -435,9 +446,10 @@ export function getInspectorActions(
|
|
|
435
446
|
'\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
|
|
436
447
|
},
|
|
437
448
|
{
|
|
438
|
-
label: '
|
|
449
|
+
label: '表单提交前转换字段数据',
|
|
439
450
|
skill: 'form-data-transform',
|
|
440
|
-
promptTemplate: `为 ${formF(r, f)}
|
|
451
|
+
promptTemplate: `为 ${formF(r, f)} 添加数据转换逻辑(表单提交前)`,
|
|
452
|
+
promptPrefix: '具体转换规则:',
|
|
441
453
|
requiresInput: true,
|
|
442
454
|
inputPlaceholder:
|
|
443
455
|
'请描述转换规则,例如:提交前将数组转为逗号分隔字符串,回填时再拆回数组',
|
|
@@ -449,7 +461,7 @@ export function getInspectorActions(
|
|
|
449
461
|
skill: null,
|
|
450
462
|
requiresInput: true,
|
|
451
463
|
promptTemplate: `对 ${r} 表单中的 "${f}" 字段进行修改`,
|
|
452
|
-
promptPrefix: '
|
|
464
|
+
promptPrefix: '具体要求:',
|
|
453
465
|
inputPlaceholder: '请描述你希望 AI 执行的自定义操作',
|
|
454
466
|
promptSuffix:
|
|
455
467
|
'\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
|
|
@@ -469,6 +481,7 @@ export function getInspectorActions(
|
|
|
469
481
|
label: '修改字段值展示样式',
|
|
470
482
|
skill: 'show-field-render',
|
|
471
483
|
promptTemplate: `自定义 ${showF(r, f)} 的显示方式`,
|
|
484
|
+
promptPrefix: '具体要求:',
|
|
472
485
|
requiresInput: true,
|
|
473
486
|
inputPlaceholder:
|
|
474
487
|
'请描述样式要求,例如:将 JSON 格式化展示,或用颜色标签渲染状态',
|
|
@@ -479,6 +492,7 @@ export function getInspectorActions(
|
|
|
479
492
|
label: '修改描述(label)',
|
|
480
493
|
skill: 'page-i18n',
|
|
481
494
|
promptTemplate: `修改 ${showF(r, f)} 的标签名称(通过 i18n 翻译文件)`,
|
|
495
|
+
promptPrefix: '修改为:',
|
|
482
496
|
requiresInput: true,
|
|
483
497
|
inputPlaceholder:
|
|
484
498
|
'请分别提供中文和英文名称,例如:\n中文:审核状态\n英文:Review Status\n(翻译 key:resources.{resourceName}.fields.{fieldName})',
|
|
@@ -502,7 +516,7 @@ export function getInspectorActions(
|
|
|
502
516
|
skill: null,
|
|
503
517
|
requiresInput: true,
|
|
504
518
|
promptTemplate: `对 ${r} 详情页的 "${f}" 字段进行修改`,
|
|
505
|
-
promptPrefix: '
|
|
519
|
+
promptPrefix: '具体要求:',
|
|
506
520
|
inputPlaceholder: '请描述你希望 AI 执行的自定义操作',
|
|
507
521
|
promptSuffix:
|
|
508
522
|
'\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
|
|
@@ -515,6 +529,7 @@ export function getInspectorActions(
|
|
|
515
529
|
label: '增加 模糊匹配 过滤',
|
|
516
530
|
skill: 'list-search-filter',
|
|
517
531
|
promptTemplate: `为 ${r} 搜索栏添加模糊匹配过滤(通过修改ui配置)`,
|
|
532
|
+
promptPrefix: '要添加的字段:',
|
|
518
533
|
requiresInput: true,
|
|
519
534
|
inputPlaceholder: '请填写要添加模糊搜索的字段名,例如:name、title',
|
|
520
535
|
promptSuffix:
|
|
@@ -524,9 +539,10 @@ export function getInspectorActions(
|
|
|
524
539
|
label: '增加 下拉 过滤',
|
|
525
540
|
skill: 'list-search-filter',
|
|
526
541
|
promptTemplate: `为 ${r} 搜索栏添加 Select 下拉过滤`,
|
|
542
|
+
promptPrefix: '要添加的字段:',
|
|
527
543
|
requiresInput: true,
|
|
528
544
|
inputPlaceholder:
|
|
529
|
-
'
|
|
545
|
+
'请填写字段名,例如:字段 status;或字段 gameId,选项来自关联表 game 的 name 字段',
|
|
530
546
|
promptSuffix:
|
|
531
547
|
'\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
|
|
532
548
|
},
|
|
@@ -534,9 +550,9 @@ export function getInspectorActions(
|
|
|
534
550
|
label: '增加 checkbox 过滤',
|
|
535
551
|
skill: 'list-search-filter',
|
|
536
552
|
promptTemplate: `为 ${r} 搜索栏添加 Checkbox 多选过滤`,
|
|
553
|
+
promptPrefix: '要添加的字段:',
|
|
537
554
|
requiresInput: true,
|
|
538
|
-
inputPlaceholder:
|
|
539
|
-
'请填写字段名及选项,例如:字段 category,选项:技术|产品|运营',
|
|
555
|
+
inputPlaceholder: '请填写字段名及选项,例如:字段 category',
|
|
540
556
|
promptSuffix:
|
|
541
557
|
'\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
|
|
542
558
|
},
|
|
@@ -544,6 +560,7 @@ export function getInspectorActions(
|
|
|
544
560
|
label: '增加 radio 过滤',
|
|
545
561
|
skill: 'list-search-filter',
|
|
546
562
|
promptTemplate: `为 ${r} 搜索栏添加 Radio 单选过滤`,
|
|
563
|
+
promptPrefix: '要添加的字段:',
|
|
547
564
|
requiresInput: true,
|
|
548
565
|
inputPlaceholder:
|
|
549
566
|
'请填写字段名及选项,例如:字段 type,选项:全部|在线|离线',
|
|
@@ -554,6 +571,7 @@ export function getInspectorActions(
|
|
|
554
571
|
label: '添加固定过滤(不可清除)',
|
|
555
572
|
skill: 'list-search-filter',
|
|
556
573
|
promptTemplate: `为 ${r} 列表页添加不可被用户清除的固定过滤条件(permanentFilter)`,
|
|
574
|
+
promptPrefix: '要添加的固定过滤条件:',
|
|
557
575
|
requiresInput: true,
|
|
558
576
|
inputPlaceholder:
|
|
559
577
|
'请描述固定过滤条件,例如:始终只显示 status=ACTIVE 的数据,或按当前用户 ID 过滤',
|
|
@@ -564,6 +582,7 @@ export function getInspectorActions(
|
|
|
564
582
|
label: '移除 过滤字段',
|
|
565
583
|
skill: 'list-search-filter',
|
|
566
584
|
promptTemplate: `从 ${r} 搜索栏删除过滤字段`,
|
|
585
|
+
promptPrefix: '要删除的过滤字段:',
|
|
567
586
|
requiresInput: true,
|
|
568
587
|
inputPlaceholder: '请填写要删除的过滤字段名',
|
|
569
588
|
promptSuffix:
|
|
@@ -573,6 +592,7 @@ export function getInspectorActions(
|
|
|
573
592
|
label: '修改描述(label)',
|
|
574
593
|
skill: 'page-i18n',
|
|
575
594
|
promptTemplate: `修改 ${r} 搜索栏某个过滤字段的显示名称(通过 i18n 翻译文件)`,
|
|
595
|
+
promptPrefix: '修改为:',
|
|
576
596
|
requiresInput: true,
|
|
577
597
|
inputPlaceholder:
|
|
578
598
|
'请填写字段名,并分别提供中文和英文名称,例如:\n字段:status\n中文:审核状态\n英文:Review Status\n(翻译 key:resources.{resourceName}.fields.{fieldName})',
|
|
@@ -584,7 +604,7 @@ export function getInspectorActions(
|
|
|
584
604
|
skill: null,
|
|
585
605
|
requiresInput: true,
|
|
586
606
|
promptTemplate: `对 ${r} 列表页的搜索栏进行修改`,
|
|
587
|
-
promptPrefix: '
|
|
607
|
+
promptPrefix: '具体要求:',
|
|
588
608
|
inputPlaceholder: '请描述你希望 AI 执行的自定义操作',
|
|
589
609
|
promptSuffix:
|
|
590
610
|
'\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
|
|
@@ -601,6 +621,7 @@ export function getInspectorActions(
|
|
|
601
621
|
label: '按条件显示',
|
|
602
622
|
skill: 'list-createbtn-customization',
|
|
603
623
|
promptTemplate: `为 ${r} 列表页工具栏新建按钮添加条件显示逻辑`,
|
|
624
|
+
promptPrefix: '显示条件:',
|
|
604
625
|
requiresInput: true,
|
|
605
626
|
inputPlaceholder:
|
|
606
627
|
'请描述显示条件,例如:仅角色为 GPU_ADMIN 时才显示新建按钮',
|
|
@@ -611,6 +632,7 @@ export function getInspectorActions(
|
|
|
611
632
|
label: '修改描述(label)',
|
|
612
633
|
skill: 'page-i18n',
|
|
613
634
|
promptTemplate: `修改 ${r} 列表页工具栏新建按钮的显示名称(通过 i18n 翻译文件)`,
|
|
635
|
+
promptPrefix: '修改为:',
|
|
614
636
|
requiresInput: true,
|
|
615
637
|
inputPlaceholder:
|
|
616
638
|
'请分别提供中文和英文,例如:\n中文:新建游戏\n英文:Create Game',
|
|
@@ -634,6 +656,7 @@ export function getInspectorActions(
|
|
|
634
656
|
label: '按条件显示',
|
|
635
657
|
skill: 'list-import-customization',
|
|
636
658
|
promptTemplate: `为 ${r} 列表页工具栏添加按条件显示的 导入按钮`,
|
|
659
|
+
promptPrefix: '显示条件:',
|
|
637
660
|
requiresInput: true,
|
|
638
661
|
inputPlaceholder: '请描述显示条件',
|
|
639
662
|
promptSuffix:
|
|
@@ -643,6 +666,7 @@ export function getInspectorActions(
|
|
|
643
666
|
label: '修改描述(label)',
|
|
644
667
|
skill: 'page-i18n',
|
|
645
668
|
promptTemplate: `修改 ${r} 列表页工具栏导入按钮的显示名称(通过 i18n 翻译文件)`,
|
|
669
|
+
promptPrefix: '修改为:',
|
|
646
670
|
requiresInput: true,
|
|
647
671
|
inputPlaceholder: '请分别提供中文和英文',
|
|
648
672
|
promptSuffix:
|
|
@@ -671,6 +695,7 @@ export function getInspectorActions(
|
|
|
671
695
|
label: '按条件显示',
|
|
672
696
|
skill: 'list-export-customization',
|
|
673
697
|
promptTemplate: `为 ${r} 列表页工具栏添加按条件显示的 导出按钮`,
|
|
698
|
+
promptPrefix: '显示条件:',
|
|
674
699
|
requiresInput: true,
|
|
675
700
|
inputPlaceholder: '请描述显示条件',
|
|
676
701
|
promptSuffix:
|
|
@@ -680,6 +705,7 @@ export function getInspectorActions(
|
|
|
680
705
|
label: '修改描述(label)',
|
|
681
706
|
skill: 'page-i18n',
|
|
682
707
|
promptTemplate: `修改 ${r} 列表页工具栏导出按钮的显示名称(通过 i18n 翻译文件)`,
|
|
708
|
+
promptPrefix: '修改为:',
|
|
683
709
|
requiresInput: true,
|
|
684
710
|
inputPlaceholder: '请分别提供中文和英文',
|
|
685
711
|
promptSuffix:
|
|
@@ -715,6 +741,7 @@ export function getInspectorActions(
|
|
|
715
741
|
label: '修改描述(label)',
|
|
716
742
|
skill: 'page-i18n',
|
|
717
743
|
promptTemplate: `修改 ${r} 列表页工具栏刷新按钮的显示名称(通过 i18n 翻译文件)`,
|
|
744
|
+
promptPrefix: '修改为:',
|
|
718
745
|
requiresInput: true,
|
|
719
746
|
inputPlaceholder: '请分别提供中文和英文',
|
|
720
747
|
promptSuffix:
|
|
@@ -748,7 +775,7 @@ export function getInspectorActions(
|
|
|
748
775
|
skill: null,
|
|
749
776
|
requiresInput: true,
|
|
750
777
|
promptTemplate: `对 ${r} 列表页的工具栏区域(ListPageHeader 组件)进行修改`,
|
|
751
|
-
promptPrefix: '
|
|
778
|
+
promptPrefix: '具体要求:',
|
|
752
779
|
promptSuffix: `注意:ListPageHeader 是公共组件,不可直接修改其源码。\n请优先通过调整列表页中 ListPageHeader 的 render props 来实现;\n如果 render props 无法满足需求,再在列表页内创建局部组件来替代。\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动`,
|
|
753
780
|
inputPlaceholder: '请描述你希望 AI 执行的自定义操作',
|
|
754
781
|
},
|
|
@@ -760,6 +787,7 @@ export function getInspectorActions(
|
|
|
760
787
|
label: '添加操作按钮',
|
|
761
788
|
skill: 'list-custom-row-actions',
|
|
762
789
|
promptTemplate: `为 ${r} 列表页行操作添加自定义按钮(通过CHANGE_STATUS配置 或者 自定义行操作)`,
|
|
790
|
+
promptPrefix: '具体要求:',
|
|
763
791
|
requiresInput: true,
|
|
764
792
|
inputPlaceholder:
|
|
765
793
|
'请描述按钮的名称、修改的状态字段和变更目标的值,例如:添加"发布"按钮,将 status 字段从 PENDING 改为 APPROVED' +
|
|
@@ -772,6 +800,7 @@ export function getInspectorActions(
|
|
|
772
800
|
label: '添加 跳转至外部链接 按钮',
|
|
773
801
|
skill: 'list-row-action-external',
|
|
774
802
|
promptTemplate: `为 ${r} 列表页行操作添加跳转链接按钮`,
|
|
803
|
+
promptPrefix: '具体要求:',
|
|
775
804
|
requiresInput: true,
|
|
776
805
|
inputPlaceholder:
|
|
777
806
|
'请描述按钮名称和跳转目标,例如:添加"查看报表"按钮,跳转到 /reports/:id',
|
|
@@ -782,6 +811,7 @@ export function getInspectorActions(
|
|
|
782
811
|
label: '添加 跳转至站内页面 按钮',
|
|
783
812
|
skill: 'list-row-action-link',
|
|
784
813
|
promptTemplate: `为 ${r} 列表页行操作添加站内页面跳转按钮`,
|
|
814
|
+
promptPrefix: '具体要求:',
|
|
785
815
|
requiresInput: true,
|
|
786
816
|
inputPlaceholder:
|
|
787
817
|
'请描述按钮名称和目标页面,例如:添加"查看详情"按钮,跳转到 /orders/:id/detail',
|
|
@@ -792,9 +822,10 @@ export function getInspectorActions(
|
|
|
792
822
|
label: '按条件显示 编辑 按钮 ',
|
|
793
823
|
skill: 'ui-config-update',
|
|
794
824
|
promptTemplate: `为 ${r} 列表页的 编辑 按钮添加条件显示逻辑(EDIT)`,
|
|
825
|
+
promptPrefix: '显示条件:',
|
|
795
826
|
requiresInput: true,
|
|
796
827
|
inputPlaceholder:
|
|
797
|
-
'
|
|
828
|
+
'请描述显示条件,例如:当 status 为 PENDING 时显示 编辑 按钮',
|
|
798
829
|
promptSuffix:
|
|
799
830
|
'\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
|
|
800
831
|
},
|
|
@@ -803,7 +834,7 @@ export function getInspectorActions(
|
|
|
803
834
|
skill: null,
|
|
804
835
|
requiresInput: true,
|
|
805
836
|
promptTemplate: `对 ${r} 列表页的行操作区域(RowActions 组件)进行修改`,
|
|
806
|
-
promptPrefix: '
|
|
837
|
+
promptPrefix: '具体要求:',
|
|
807
838
|
promptSuffix: `注意:RowActions 是公共组件,不可直接修改其源码。\n请优先通过调整列表页中 RowActions 的 render props 来实现;\n如果 render props 无法满足需求,再在列表页内创建局部组件来替代。\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动`,
|
|
808
839
|
inputPlaceholder: '请描述你希望 AI 执行的自定义操作',
|
|
809
840
|
},
|
|
@@ -839,6 +870,7 @@ export function getInspectorActions(
|
|
|
839
870
|
label: '添加(固定值,如状态)',
|
|
840
871
|
skill: 'list-bulk-actions-batch-modify-modal',
|
|
841
872
|
promptTemplate: `为 ${r} 列表页添加批量编辑弹窗(固定值)`,
|
|
873
|
+
promptPrefix: '具体要求:',
|
|
842
874
|
requiresInput: true,
|
|
843
875
|
inputPlaceholder:
|
|
844
876
|
'请描述要批量修改的字段和固定值,例如:将 status 批量设为 PUBLISHED',
|
|
@@ -849,6 +881,7 @@ export function getInspectorActions(
|
|
|
849
881
|
label: '添加(用户输入)',
|
|
850
882
|
skill: 'list-bulk-actions-batch-modify-modal',
|
|
851
883
|
promptTemplate: `为 ${r} 列表页添加批量编辑弹窗(用户输入)`,
|
|
884
|
+
promptPrefix: '具体要求:',
|
|
852
885
|
requiresInput: true,
|
|
853
886
|
inputPlaceholder:
|
|
854
887
|
'请描述要批量编辑的字段,例如:让用户输入 remark 后批量更新',
|
|
@@ -889,7 +922,7 @@ export function getInspectorActions(
|
|
|
889
922
|
skill: null,
|
|
890
923
|
requiresInput: true,
|
|
891
924
|
promptTemplate: `对 ${r} 列表页的批量操作区域(BulkActions 组件)进行修改`,
|
|
892
|
-
promptPrefix: '
|
|
925
|
+
promptPrefix: '具体要求:',
|
|
893
926
|
promptSuffix: `注意:BulkActions 是公共组件,不可直接修改其源码。\n请优先通过调整列表页中 BulkActions 的 render props(如 renderDeleteButton、extraActions 等)来实现;\n如果 render props 无法满足需求,再在列表页内创建局部组件来替代。\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动`,
|
|
894
927
|
inputPlaceholder: '请描述你希望 AI 执行的自定义操作',
|
|
895
928
|
},
|
|
@@ -902,6 +935,7 @@ export function getInspectorActions(
|
|
|
902
935
|
skill: 'header-customization',
|
|
903
936
|
promptTemplate: `修改网站标题文字`,
|
|
904
937
|
requiresInput: true,
|
|
938
|
+
promptPrefix: '修改为:',
|
|
905
939
|
inputPlaceholder:
|
|
906
940
|
'请描述修改内容,例如:\n- 改为"xxx 管理后台"\n- 隐藏标题只保留 Logo',
|
|
907
941
|
promptSuffix:
|
|
@@ -912,6 +946,7 @@ export function getInspectorActions(
|
|
|
912
946
|
skill: 'header-customization',
|
|
913
947
|
promptTemplate: `修改网站 Logo`,
|
|
914
948
|
requiresInput: true,
|
|
949
|
+
promptPrefix: '具体要求:',
|
|
915
950
|
inputPlaceholder:
|
|
916
951
|
'请描述修改内容,例如:\n- 替换为图片 Logo(提供图片路径或 URL)\n- 修改 Logo 颜色\n- 隐藏 Logo',
|
|
917
952
|
promptSuffix:
|
|
@@ -922,7 +957,7 @@ export function getInspectorActions(
|
|
|
922
957
|
skill: null,
|
|
923
958
|
requiresInput: true,
|
|
924
959
|
promptTemplate: `对页面标题和 Logo 区域进行修改`,
|
|
925
|
-
promptPrefix: '
|
|
960
|
+
promptPrefix: '具体要求:',
|
|
926
961
|
inputPlaceholder: '请描述你希望 AI 执行的自定义操作',
|
|
927
962
|
promptSuffix:
|
|
928
963
|
'\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
|
|
@@ -936,6 +971,7 @@ export function getInspectorActions(
|
|
|
936
971
|
skill: 'header-customization',
|
|
937
972
|
promptTemplate: `修改顶部导航的业务(游戏)选择器`,
|
|
938
973
|
requiresInput: true,
|
|
974
|
+
promptPrefix: '具体要求:',
|
|
939
975
|
inputPlaceholder:
|
|
940
976
|
'请描述修改内容,例如:\n- 隐藏选择器\n- 修改宽度为 200px\n- 默认选中第一项',
|
|
941
977
|
promptSuffix:
|
|
@@ -945,6 +981,7 @@ export function getInspectorActions(
|
|
|
945
981
|
label: '修改语言切换',
|
|
946
982
|
skill: 'header-customization',
|
|
947
983
|
promptTemplate: `修改顶部导航的语言切换`,
|
|
984
|
+
promptPrefix: '具体要求:',
|
|
948
985
|
requiresInput: true,
|
|
949
986
|
inputPlaceholder:
|
|
950
987
|
'请描述修改内容,例如:\n- 隐藏语言切换\n- 只保留中文,移除多语言切换',
|
|
@@ -956,6 +993,7 @@ export function getInspectorActions(
|
|
|
956
993
|
skill: 'header-customization',
|
|
957
994
|
promptTemplate: `修改顶部导航的用户信息区`,
|
|
958
995
|
requiresInput: true,
|
|
996
|
+
promptPrefix: '具体要求:',
|
|
959
997
|
inputPlaceholder:
|
|
960
998
|
'请描述修改内容,例如:\n- 隐藏用户名,只显示头像\n- 隐藏头像和用户名\n- 点击用户名跳转到个人主页',
|
|
961
999
|
promptSuffix:
|
|
@@ -966,6 +1004,7 @@ export function getInspectorActions(
|
|
|
966
1004
|
skill: 'header-customization',
|
|
967
1005
|
promptTemplate: `修改顶部导航的整体样式`,
|
|
968
1006
|
requiresInput: true,
|
|
1007
|
+
promptPrefix: '具体要求:',
|
|
969
1008
|
inputPlaceholder:
|
|
970
1009
|
'请描述修改内容,例如:\n- 背景色改为深色 #001529\n- 高度改为 48px\n- 左侧添加系统标题文字',
|
|
971
1010
|
promptSuffix:
|
|
@@ -976,7 +1015,7 @@ export function getInspectorActions(
|
|
|
976
1015
|
skill: null,
|
|
977
1016
|
requiresInput: true,
|
|
978
1017
|
promptTemplate: `对顶部导航栏(App Header 组件)进行修改`,
|
|
979
|
-
promptPrefix: '
|
|
1018
|
+
promptPrefix: '具体要求:',
|
|
980
1019
|
inputPlaceholder: '请描述你希望 AI 执行的自定义操作',
|
|
981
1020
|
promptSuffix:
|
|
982
1021
|
'\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
|
|
@@ -994,6 +1033,7 @@ export function getInspectorActions(
|
|
|
994
1033
|
skill: 'show-readonly-header',
|
|
995
1034
|
promptTemplate: `为 ${r} 详情页编辑按钮添加条件显示逻辑`,
|
|
996
1035
|
requiresInput: true,
|
|
1036
|
+
promptPrefix: '显示条件:',
|
|
997
1037
|
inputPlaceholder:
|
|
998
1038
|
'请描述显示条件,例如:仅角色为 ADMIN 时才显示编辑按钮',
|
|
999
1039
|
promptSuffix:
|
|
@@ -1003,6 +1043,7 @@ export function getInspectorActions(
|
|
|
1003
1043
|
label: '修改描述(label)',
|
|
1004
1044
|
skill: 'page-i18n',
|
|
1005
1045
|
promptTemplate: `修改 ${r} 详情页编辑按钮的显示名称(通过 i18n 翻译文件)`,
|
|
1046
|
+
promptPrefix: '修改为:',
|
|
1006
1047
|
requiresInput: true,
|
|
1007
1048
|
inputPlaceholder:
|
|
1008
1049
|
'请分别提供中文和英文,例如:\n中文:修改\n英文:Edit',
|
|
@@ -1033,6 +1074,7 @@ export function getInspectorActions(
|
|
|
1033
1074
|
label: '显示(按条件)',
|
|
1034
1075
|
skill: 'show-readonly-header',
|
|
1035
1076
|
promptTemplate: `为 ${r} 详情页复制按钮添加条件显示逻辑`,
|
|
1077
|
+
promptPrefix: '显示条件:',
|
|
1036
1078
|
requiresInput: true,
|
|
1037
1079
|
inputPlaceholder: '请描述显示条件',
|
|
1038
1080
|
promptSuffix:
|
|
@@ -1042,6 +1084,7 @@ export function getInspectorActions(
|
|
|
1042
1084
|
label: '修改描述(label)',
|
|
1043
1085
|
skill: 'page-i18n',
|
|
1044
1086
|
promptTemplate: `修改 ${r} 详情页复制按钮的显示名称(通过 i18n 翻译文件)`,
|
|
1087
|
+
promptPrefix: '修改为:',
|
|
1045
1088
|
requiresInput: true,
|
|
1046
1089
|
inputPlaceholder:
|
|
1047
1090
|
'请分别提供中文和英文,例如:\n中文:复制\n英文:Clone',
|
|
@@ -1064,7 +1107,8 @@ export function getInspectorActions(
|
|
|
1064
1107
|
{
|
|
1065
1108
|
label: '显示(按条件)',
|
|
1066
1109
|
skill: 'show-readonly-header',
|
|
1067
|
-
promptTemplate: `为 ${r}
|
|
1110
|
+
promptTemplate: `为 ${r} 详情页删除按钮添加条件显示的逻辑`,
|
|
1111
|
+
promptPrefix: '具体逻辑为:',
|
|
1068
1112
|
requiresInput: true,
|
|
1069
1113
|
inputPlaceholder:
|
|
1070
1114
|
'请描述显示条件,例如:当 status 为 PUBLISHED 时隐藏删除按钮',
|
|
@@ -1075,6 +1119,7 @@ export function getInspectorActions(
|
|
|
1075
1119
|
label: '修改描述(label)',
|
|
1076
1120
|
skill: 'page-i18n',
|
|
1077
1121
|
promptTemplate: `修改 ${r} 详情页删除按钮的显示名称(通过 i18n 翻译文件)`,
|
|
1122
|
+
promptPrefix: '修改为:',
|
|
1078
1123
|
requiresInput: true,
|
|
1079
1124
|
inputPlaceholder:
|
|
1080
1125
|
'请分别提供中文和英文,例如:\n中文:删除\n英文:Delete',
|
|
@@ -1105,6 +1150,7 @@ export function getInspectorActions(
|
|
|
1105
1150
|
label: '修改描述(label)',
|
|
1106
1151
|
skill: 'page-i18n',
|
|
1107
1152
|
promptTemplate: `修改 ${r} 详情页刷新按钮的显示名称(通过 i18n 翻译文件)`,
|
|
1153
|
+
promptPrefix: '修改为:',
|
|
1108
1154
|
requiresInput: true,
|
|
1109
1155
|
inputPlaceholder:
|
|
1110
1156
|
'请分别提供中文和英文,例如:\n中文:刷新\n英文:Refresh',
|
|
@@ -1124,7 +1170,7 @@ export function getInspectorActions(
|
|
|
1124
1170
|
label: '添加 自定义操作按钮(可调接口)',
|
|
1125
1171
|
skill: 'show-readonly-header',
|
|
1126
1172
|
promptTemplate: `为 ${r} 详情页工具栏添加自定义操作按钮`,
|
|
1127
|
-
promptPrefix: '
|
|
1173
|
+
promptPrefix: '具体要求:',
|
|
1128
1174
|
requiresInput: true,
|
|
1129
1175
|
inputPlaceholder:
|
|
1130
1176
|
'请描述按钮名称和要调用的接口,例如:添加"审核通过"按钮,点击后调用 POST /api/approve/:id',
|
|
@@ -1143,7 +1189,7 @@ export function getInspectorActions(
|
|
|
1143
1189
|
skill: null,
|
|
1144
1190
|
requiresInput: true,
|
|
1145
1191
|
promptTemplate: `对 ${r} 详情页的操作工具栏(show header 区域)进行修改`,
|
|
1146
|
-
promptPrefix: '
|
|
1192
|
+
promptPrefix: '具体要求:',
|
|
1147
1193
|
inputPlaceholder: '请描述你希望 AI 执行的自定义操作',
|
|
1148
1194
|
promptSuffix:
|
|
1149
1195
|
'\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
|
package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/header.tsx
CHANGED
|
@@ -63,7 +63,7 @@ export const Header: React.FC = () => {
|
|
|
63
63
|
|
|
64
64
|
return (
|
|
65
65
|
<Layout.Header style={headerStyles} {...agentAttrs({ type: 'app-header' })}>
|
|
66
|
-
<Select
|
|
66
|
+
{/* <Select
|
|
67
67
|
showSearch
|
|
68
68
|
defaultValue={business.gameId}
|
|
69
69
|
style={{ width: 160 }}
|
|
@@ -87,7 +87,7 @@ export const Header: React.FC = () => {
|
|
|
87
87
|
setBusiness(gameInfo);
|
|
88
88
|
window.location.reload();
|
|
89
89
|
}}
|
|
90
|
-
/>
|
|
90
|
+
/> */}
|
|
91
91
|
<Dropdown menu={langMenu}>
|
|
92
92
|
<Button type="link">
|
|
93
93
|
<Space>
|
package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/sider.tsx
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
useGo,
|
|
17
17
|
} from '@refinedev/core';
|
|
18
18
|
import { useTranslation } from 'react-i18next';
|
|
19
|
+
import { useLocation } from 'react-router-dom';
|
|
19
20
|
|
|
20
21
|
import {
|
|
21
22
|
BarsOutlined,
|
|
@@ -87,6 +88,7 @@ const getMenuLabel = (
|
|
|
87
88
|
export const Sider: React.FC = () => {
|
|
88
89
|
const { token } = useToken();
|
|
89
90
|
const { menuItems, selectedKey, defaultOpenKeys } = useMenu();
|
|
91
|
+
const { pathname: currentPathname } = useLocation();
|
|
90
92
|
const { t, i18n } = useTranslation();
|
|
91
93
|
const currentLocale = i18n.language;
|
|
92
94
|
|
|
@@ -205,12 +207,18 @@ export const Sider: React.FC = () => {
|
|
|
205
207
|
}
|
|
206
208
|
|
|
207
209
|
// Skip auto-redirect for CRUD detail pages (edit/show/create)
|
|
208
|
-
// These pages are not in the menu but are valid navigation targets
|
|
210
|
+
// These pages are not in the menu but are valid navigation targets.
|
|
211
|
+
// Also skip auto-generated /admin/data-mngt/* CRUD list pages —
|
|
212
|
+
// some of them are intentionally hidden from the sidebar via
|
|
213
|
+
// meta.hide but remain reachable through buttons on other pages.
|
|
214
|
+
// Use the live router pathname (not Refine's selectedKey, which
|
|
215
|
+
// collapses to an ancestor when the resource is hidden).
|
|
209
216
|
if (
|
|
210
|
-
|
|
211
|
-
(
|
|
212
|
-
|
|
213
|
-
|
|
217
|
+
currentPathname &&
|
|
218
|
+
(currentPathname.includes('/edit/') ||
|
|
219
|
+
currentPathname.includes('/show/') ||
|
|
220
|
+
currentPathname.endsWith('/create') ||
|
|
221
|
+
currentPathname.includes('/data-mngt/'))
|
|
214
222
|
) {
|
|
215
223
|
return;
|
|
216
224
|
}
|
|
@@ -248,7 +256,7 @@ export const Sider: React.FC = () => {
|
|
|
248
256
|
}, 300);
|
|
249
257
|
|
|
250
258
|
return () => clearTimeout(timer);
|
|
251
|
-
}, [items, selectedKey, go]);
|
|
259
|
+
}, [items, selectedKey, currentPathname, go]);
|
|
252
260
|
|
|
253
261
|
const handleOpenChange = useCallback(
|
|
254
262
|
(keys: string[]) => {
|
|
@@ -162,10 +162,12 @@ const S = ({ children }: { children: React.ReactNode }) => (
|
|
|
162
162
|
// ─── Route Registry ──────────────────────────────────────────────────────────
|
|
163
163
|
//
|
|
164
164
|
// 路由路径命名规则:
|
|
165
|
-
// Sider 组件会对不在菜单中的路径执行 auto-redirect
|
|
166
|
-
//
|
|
167
|
-
//
|
|
168
|
-
//
|
|
165
|
+
// Sider 组件会对不在菜单中的路径执行 auto-redirect。豁免规则(见
|
|
166
|
+
// components/layout/sider.tsx 中的 useEffect):
|
|
167
|
+
// ✅ 路径含 `/edit/` 或 `/show/`,或以 `/create` 结尾(CRUD 详情页)
|
|
168
|
+
// ✅ 路径含 `/data-mngt/`(数据管理 CRUD 列表,部分通过 meta.hide 隐藏)
|
|
169
|
+
// ❌ 其它不在菜单的列表路径会被自动重定向到第一个菜单项
|
|
170
|
+
// 因此,新加的不在侧边栏的子页面,路径必须命中上述某条豁免规则,例如:
|
|
169
171
|
// ✅ instance/show/:id
|
|
170
172
|
// ✅ node-instances/edit/:id
|
|
171
173
|
// ❌ instance/:id ← 会被 auto-redirect 导致 404
|
|
@@ -256,7 +258,7 @@ export const routeRegistry: Record<string, RouteEntry> = {
|
|
|
256
258
|
path: 'p/:slug',
|
|
257
259
|
component: lazy(() => import('routes/canvas-page')),
|
|
258
260
|
},
|
|
259
|
-
game: {
|
|
261
|
+
/*game: {
|
|
260
262
|
path: 'game-list',
|
|
261
263
|
children: {
|
|
262
264
|
list: {
|
|
@@ -285,7 +287,7 @@ export const routeRegistry: Record<string, RouteEntry> = {
|
|
|
285
287
|
),
|
|
286
288
|
},
|
|
287
289
|
},
|
|
288
|
-
}
|
|
290
|
+
},*/
|
|
289
291
|
// Agenda Jobs — sortOrder 1080, code: admin.agenda
|
|
290
292
|
agenda: {
|
|
291
293
|
path: 'agenda-jobs',
|
|
@@ -97,19 +97,36 @@ export default function DevShell() {
|
|
|
97
97
|
});
|
|
98
98
|
}, []);
|
|
99
99
|
|
|
100
|
+
// ── new-conversation + send prompt helper ───────────────────────────────
|
|
101
|
+
// Always start a fresh conversation before sending a prompt. Mirrors the
|
|
102
|
+
// SDK's own "新会话" button: `addConversation('新会话', true)` → emit
|
|
103
|
+
// NEW_CONVERSATION → sendUserPrompt. The second arg `true` forces creation
|
|
104
|
+
// even if the current conversation is empty (no id), so callers always get
|
|
105
|
+
// a fresh slate.
|
|
106
|
+
const startNewConversationAndSend = useCallback(
|
|
107
|
+
async (sdk: any, prompt: string) => {
|
|
108
|
+
await sdk.addConversation('新会话', true);
|
|
109
|
+
// const NEW_CONV = window.ChatSDK?.ChatEventKey?.NEW_CONVERSATION;
|
|
110
|
+
// if (NEW_CONV) sdk.emit(NEW_CONV, {});
|
|
111
|
+
return sdk.sendUserPrompt(prompt);
|
|
112
|
+
},
|
|
113
|
+
[],
|
|
114
|
+
);
|
|
115
|
+
|
|
100
116
|
// ── send prompt helper ───────────────────────────────────────────────────
|
|
101
|
-
const sendPromptToAgent = useCallback(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
.catch((err: any) =>
|
|
117
|
+
const sendPromptToAgent = useCallback(
|
|
118
|
+
(prompt: string) => {
|
|
119
|
+
setAgentVisible(true);
|
|
120
|
+
const sdk = sdkRef.current;
|
|
121
|
+
if (!sdk) return;
|
|
122
|
+
setTimeout(() => {
|
|
123
|
+
startNewConversationAndSend(sdk, prompt).catch((err: any) =>
|
|
109
124
|
console.error('[DevShell] sendUserPrompt failed:', err),
|
|
110
125
|
);
|
|
111
|
-
|
|
112
|
-
|
|
126
|
+
}, 300);
|
|
127
|
+
},
|
|
128
|
+
[startNewConversationAndSend],
|
|
129
|
+
);
|
|
113
130
|
|
|
114
131
|
// ── persist agent visibility ─────────────────────────────────────────────
|
|
115
132
|
useEffect(() => {
|
|
@@ -124,7 +141,7 @@ export default function DevShell() {
|
|
|
124
141
|
header: { logo: '', title: 'Coding Agent' },
|
|
125
142
|
empty: '',
|
|
126
143
|
streamingTimeout: 1800,
|
|
127
|
-
initialConversation:
|
|
144
|
+
initialConversation: false,
|
|
128
145
|
service: {
|
|
129
146
|
agentId: import.meta.env.VITE_AGENT_ID,
|
|
130
147
|
baseURL: import.meta.env.VITE_AGENT_BASE_URL,
|
|
@@ -189,8 +206,7 @@ export default function DevShell() {
|
|
|
189
206
|
.catch(() => {})
|
|
190
207
|
.finally(() => {
|
|
191
208
|
setTimeout(() => {
|
|
192
|
-
sdk
|
|
193
|
-
.sendUserPrompt(data.payload)
|
|
209
|
+
startNewConversationAndSend(sdk, data.payload)
|
|
194
210
|
.catch((err: any) =>
|
|
195
211
|
console.error('[DevShell] sendUserPrompt failed:', err),
|
|
196
212
|
)
|
|
@@ -203,11 +219,9 @@ export default function DevShell() {
|
|
|
203
219
|
});
|
|
204
220
|
} else {
|
|
205
221
|
setTimeout(() => {
|
|
206
|
-
sdk
|
|
207
|
-
.sendUserPrompt
|
|
208
|
-
|
|
209
|
-
console.error('[DevShell] sendUserPrompt failed:', err),
|
|
210
|
-
);
|
|
222
|
+
startNewConversationAndSend(sdk, data.payload).catch((err: any) =>
|
|
223
|
+
console.error('[DevShell] sendUserPrompt failed:', err),
|
|
224
|
+
);
|
|
211
225
|
}, 300);
|
|
212
226
|
}
|
|
213
227
|
break;
|
|
@@ -290,7 +304,7 @@ export default function DevShell() {
|
|
|
290
304
|
sdk.on(keys.STREAMING_STOP, handleStreamStop);
|
|
291
305
|
}
|
|
292
306
|
|
|
293
|
-
sdk
|
|
307
|
+
startNewConversationAndSend(sdk, data.prompt).catch((err: any) => {
|
|
294
308
|
cleanup();
|
|
295
309
|
iframeRef.current?.contentWindow?.postMessage(
|
|
296
310
|
{
|
|
@@ -308,7 +322,7 @@ export default function DevShell() {
|
|
|
308
322
|
}
|
|
309
323
|
window.addEventListener('message', handleMessage);
|
|
310
324
|
return () => window.removeEventListener('message', handleMessage);
|
|
311
|
-
}, [applyPageContext]);
|
|
325
|
+
}, [applyPageContext, startNewConversationAndSend]);
|
|
312
326
|
|
|
313
327
|
// ── Escape key stops inspect ─────────────────────────────────────────────
|
|
314
328
|
useEffect(() => {
|
package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useDynamicResources.tsx
CHANGED
|
@@ -130,8 +130,12 @@ export const useDynamicResources = (): IResourceItem[] => {
|
|
|
130
130
|
sortedAccessiblePages.forEach((page) => {
|
|
131
131
|
if (!page) return;
|
|
132
132
|
|
|
133
|
-
//
|
|
134
|
-
|
|
133
|
+
// NOTE: isVirtual pages are NOT skipped here — keeping them in the
|
|
134
|
+
// resources array lets Refine hooks (useResource, useNavigation, etc.)
|
|
135
|
+
// resolve the page's metadata, and React Router routes for these
|
|
136
|
+
// pages are registered independently via routeRegistry. The menu
|
|
137
|
+
// entry is hidden below by setting `meta.hide = true`, which
|
|
138
|
+
// Refine's useMenu honours.
|
|
135
139
|
|
|
136
140
|
// Skip children of pages that use tabs
|
|
137
141
|
if (page.parentId) {
|
|
@@ -191,6 +195,11 @@ export const useDynamicResources = (): IResourceItem[] => {
|
|
|
191
195
|
parentPageCode: page.parentId
|
|
192
196
|
? pageMap.get(page.parentId)?.code
|
|
193
197
|
: undefined,
|
|
198
|
+
// Refine's useMenu skips items whose meta.hide === true.
|
|
199
|
+
// This lets us hide a CRUD page from the auto-generated
|
|
200
|
+
// 「数据管理」menu (e.g. AgendaJob is surfaced from the Cron
|
|
201
|
+
// Jobs custom page instead) while keeping the route reachable.
|
|
202
|
+
...(page.isVirtual && { hide: true }),
|
|
194
203
|
},
|
|
195
204
|
};
|
|
196
205
|
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
message,
|
|
20
20
|
} from 'antd';
|
|
21
21
|
import {
|
|
22
|
+
DatabaseOutlined,
|
|
22
23
|
DeleteOutlined,
|
|
23
24
|
PlayCircleOutlined,
|
|
24
25
|
PlusOutlined,
|
|
@@ -445,6 +446,14 @@ export default function AgendaJobsPage() {
|
|
|
445
446
|
Cron Jobs
|
|
446
447
|
</Title>
|
|
447
448
|
<Space>
|
|
449
|
+
<Tooltip title="查看 AgendaJob 表原始数据">
|
|
450
|
+
<Button
|
|
451
|
+
icon={<DatabaseOutlined />}
|
|
452
|
+
onClick={() => navigate('/admin/data-mngt/agenda-job')}
|
|
453
|
+
>
|
|
454
|
+
AgendaJob 表
|
|
455
|
+
</Button>
|
|
456
|
+
</Tooltip>
|
|
448
457
|
<Button
|
|
449
458
|
type="primary"
|
|
450
459
|
icon={<PlusOutlined />}
|
package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/list.tsx
CHANGED
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
useTranslate,
|
|
23
23
|
useApiUrl,
|
|
24
24
|
} from '@refinedev/core';
|
|
25
|
-
import { useLocation } from 'react-router-dom';
|
|
25
|
+
import { useLocation, useNavigate } from 'react-router-dom';
|
|
26
26
|
import {
|
|
27
27
|
getColumns,
|
|
28
28
|
ModelType,
|
|
@@ -61,6 +61,7 @@ export const AgendaJobList: React.FC<IResourceComponentsProps> = () => {
|
|
|
61
61
|
const resourceName = 'agendaJob';
|
|
62
62
|
const t = useTranslate();
|
|
63
63
|
const apiUrl = useApiUrl();
|
|
64
|
+
const navigate = useNavigate();
|
|
64
65
|
const { search } = useLocation();
|
|
65
66
|
const { parsedSorter, parsedFilters } = parseTableParams(search);
|
|
66
67
|
|
|
@@ -163,6 +164,7 @@ export const AgendaJobList: React.FC<IResourceComponentsProps> = () => {
|
|
|
163
164
|
return (
|
|
164
165
|
<List
|
|
165
166
|
headerProps={{
|
|
167
|
+
onBack: () => navigate('/admin/agenda-jobs'),
|
|
166
168
|
subTitle: (
|
|
167
169
|
<BulkActions
|
|
168
170
|
selectedRowKeys={batchOps.selectedRowKeys}
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
Modal,
|
|
18
18
|
message,
|
|
19
19
|
Tabs,
|
|
20
|
+
Typography,
|
|
20
21
|
} from 'antd';
|
|
21
22
|
import {
|
|
22
23
|
SaveOutlined,
|
|
@@ -1280,7 +1281,17 @@ export const PageManagementListPage: React.FC = () => {
|
|
|
1280
1281
|
|
|
1281
1282
|
return (
|
|
1282
1283
|
<div>
|
|
1283
|
-
<
|
|
1284
|
+
<div
|
|
1285
|
+
style={{
|
|
1286
|
+
display: 'flex',
|
|
1287
|
+
justifyContent: 'space-between',
|
|
1288
|
+
alignItems: 'center',
|
|
1289
|
+
marginBottom: 16,
|
|
1290
|
+
}}
|
|
1291
|
+
>
|
|
1292
|
+
<Typography.Title level={4} style={{ margin: 0 }}>
|
|
1293
|
+
Page mgnts
|
|
1294
|
+
</Typography.Title>
|
|
1284
1295
|
<Button
|
|
1285
1296
|
type="primary"
|
|
1286
1297
|
onClick={() =>
|
|
@@ -1292,7 +1303,7 @@ export const PageManagementListPage: React.FC = () => {
|
|
|
1292
1303
|
>
|
|
1293
1304
|
Create Page
|
|
1294
1305
|
</Button>
|
|
1295
|
-
</
|
|
1306
|
+
</div>
|
|
1296
1307
|
|
|
1297
1308
|
<Tabs
|
|
1298
1309
|
activeKey={activeTab}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useState, useMemo } from 'react';
|
|
2
2
|
import { useTable, FilterDropdown } from '@refinedev/antd';
|
|
3
|
-
import { Table, Button, Space, Tooltip, Input } from 'antd';
|
|
3
|
+
import { Table, Button, Space, Tooltip, Input, Typography } from 'antd';
|
|
4
4
|
import {
|
|
5
5
|
EditOutlined,
|
|
6
6
|
EyeOutlined,
|
|
@@ -117,7 +117,17 @@ export const ResourceManagementListPage: React.FC = () => {
|
|
|
117
117
|
|
|
118
118
|
return (
|
|
119
119
|
<div>
|
|
120
|
-
<
|
|
120
|
+
<div
|
|
121
|
+
style={{
|
|
122
|
+
display: 'flex',
|
|
123
|
+
justifyContent: 'space-between',
|
|
124
|
+
alignItems: 'center',
|
|
125
|
+
marginBottom: 16,
|
|
126
|
+
}}
|
|
127
|
+
>
|
|
128
|
+
<Typography.Title level={4} style={{ margin: 0 }}>
|
|
129
|
+
Resource mgnts
|
|
130
|
+
</Typography.Title>
|
|
121
131
|
<Button
|
|
122
132
|
type="primary"
|
|
123
133
|
onClick={() =>
|
|
@@ -129,7 +139,7 @@ export const ResourceManagementListPage: React.FC = () => {
|
|
|
129
139
|
>
|
|
130
140
|
Create Resource
|
|
131
141
|
</Button>
|
|
132
|
-
</
|
|
142
|
+
</div>
|
|
133
143
|
<Table {...tableProps} rowKey="id">
|
|
134
144
|
<Table.Column
|
|
135
145
|
dataIndex="code"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useCallback, useMemo, useState } from 'react';
|
|
2
2
|
import { useTable } from '@refinedev/antd';
|
|
3
3
|
import { useGetLocale, useGetIdentity } from '@refinedev/core';
|
|
4
|
-
import { Table, Button, Space, Tooltip, message } from 'antd';
|
|
4
|
+
import { Table, Button, Space, Tooltip, message, Typography } from 'antd';
|
|
5
5
|
|
|
6
6
|
import { EditModal } from './Components/EditModal';
|
|
7
7
|
import { CreateModal } from './Components/CreateModal';
|
|
@@ -321,7 +321,17 @@ export const RoleManagementListPage: React.FC = () => {
|
|
|
321
321
|
|
|
322
322
|
return (
|
|
323
323
|
<div>
|
|
324
|
-
<
|
|
324
|
+
<div
|
|
325
|
+
style={{
|
|
326
|
+
display: 'flex',
|
|
327
|
+
justifyContent: 'space-between',
|
|
328
|
+
alignItems: 'center',
|
|
329
|
+
marginBottom: 16,
|
|
330
|
+
}}
|
|
331
|
+
>
|
|
332
|
+
<Typography.Title level={4} style={{ margin: 0 }}>
|
|
333
|
+
Role mgnts
|
|
334
|
+
</Typography.Title>
|
|
325
335
|
<Button
|
|
326
336
|
type="primary"
|
|
327
337
|
onClick={() =>
|
|
@@ -333,7 +343,7 @@ export const RoleManagementListPage: React.FC = () => {
|
|
|
333
343
|
>
|
|
334
344
|
Create Role
|
|
335
345
|
</Button>
|
|
336
|
-
</
|
|
346
|
+
</div>
|
|
337
347
|
<Table {...tableProps} rowKey="id">
|
|
338
348
|
<Table.Column dataIndex="name" title="Name" />
|
|
339
349
|
<Table.Column dataIndex="description" title="Description" />
|
package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/index.tsx
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
message,
|
|
16
16
|
} from 'antd';
|
|
17
17
|
import {
|
|
18
|
+
DatabaseOutlined,
|
|
18
19
|
DeleteOutlined,
|
|
19
20
|
EditOutlined,
|
|
20
21
|
ExportOutlined,
|
|
@@ -412,7 +413,16 @@ export default function WorkflowListPage() {
|
|
|
412
413
|
Workflows
|
|
413
414
|
</Title>
|
|
414
415
|
<Space>
|
|
415
|
-
<
|
|
416
|
+
<Tooltip title="查看 WorkflowEventOutbox 表原始数据">
|
|
417
|
+
<Button
|
|
418
|
+
icon={<DatabaseOutlined />}
|
|
419
|
+
onClick={() =>
|
|
420
|
+
navigate('/admin/data-mngt/workflow-event-outbox')
|
|
421
|
+
}
|
|
422
|
+
>
|
|
423
|
+
EventOutbox 表
|
|
424
|
+
</Button>
|
|
425
|
+
</Tooltip>
|
|
416
426
|
<Button
|
|
417
427
|
icon={<ImportOutlined />}
|
|
418
428
|
onClick={() => setImportModalOpen(true)}
|
|
@@ -426,6 +436,7 @@ export default function WorkflowListPage() {
|
|
|
426
436
|
>
|
|
427
437
|
New Workflow
|
|
428
438
|
</Button>
|
|
439
|
+
<Button icon={<ReloadOutlined />} onClick={fetchData} />
|
|
429
440
|
</Space>
|
|
430
441
|
</div>
|
|
431
442
|
</Card>
|
|
@@ -236,10 +236,9 @@ export default function NodeInstanceListPage() {
|
|
|
236
236
|
}}
|
|
237
237
|
>
|
|
238
238
|
<Title level={4} style={{ margin: 0 }}>
|
|
239
|
-
Node
|
|
239
|
+
Node instance mgnts
|
|
240
240
|
</Title>
|
|
241
241
|
<Space>
|
|
242
|
-
<Button icon={<ReloadOutlined />} onClick={fetchData} />
|
|
243
242
|
<Button
|
|
244
243
|
type="primary"
|
|
245
244
|
icon={<PlusOutlined />}
|
|
@@ -247,6 +246,7 @@ export default function NodeInstanceListPage() {
|
|
|
247
246
|
>
|
|
248
247
|
New Instance
|
|
249
248
|
</Button>
|
|
249
|
+
<Button icon={<ReloadOutlined />} onClick={fetchData} />
|
|
250
250
|
</Space>
|
|
251
251
|
</div>
|
|
252
252
|
</Card>
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
useTranslate,
|
|
23
23
|
useApiUrl,
|
|
24
24
|
} from '@refinedev/core';
|
|
25
|
-
import { useLocation } from 'react-router-dom';
|
|
25
|
+
import { useLocation, useNavigate } from 'react-router-dom';
|
|
26
26
|
import {
|
|
27
27
|
getColumns,
|
|
28
28
|
ModelType,
|
|
@@ -66,6 +66,7 @@ export const WorkflowEventOutboxList: React.FC<
|
|
|
66
66
|
const resourceName = 'workflowEventOutbox';
|
|
67
67
|
const t = useTranslate();
|
|
68
68
|
const apiUrl = useApiUrl();
|
|
69
|
+
const navigate = useNavigate();
|
|
69
70
|
const { search } = useLocation();
|
|
70
71
|
const { parsedSorter, parsedFilters } = parseTableParams(search);
|
|
71
72
|
|
|
@@ -172,6 +173,7 @@ export const WorkflowEventOutboxList: React.FC<
|
|
|
172
173
|
return (
|
|
173
174
|
<List
|
|
174
175
|
headerProps={{
|
|
176
|
+
onBack: () => navigate('/admin/workflow'),
|
|
175
177
|
subTitle: (
|
|
176
178
|
<BulkActions
|
|
177
179
|
selectedRowKeys={batchOps.selectedRowKeys}
|