@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.
Files changed (20) hide show
  1. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/ITActivityDay.ts +1 -1
  2. package/dist/lib/application/files/gadmin2-game-angle-demo/server/package.json +1 -1
  3. package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/lib/page-helpers.ts +1 -1
  4. package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/{syncDataMngtPages.ts → sync-data-mngt-pages.ts} +25 -2
  5. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/App.tsx +1 -0
  6. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/inspectorActions.ts +68 -22
  7. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/header.tsx +2 -2
  8. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/sider.tsx +14 -6
  9. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +8 -6
  10. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/DevShell.tsx +34 -20
  11. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useDynamicResources.tsx +11 -2
  12. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/index.tsx +9 -0
  13. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/list.tsx +3 -1
  14. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/list.tsx +13 -2
  15. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/list.tsx +13 -3
  16. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/list.tsx +13 -3
  17. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/index.tsx +12 -1
  18. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/index.tsx +2 -2
  19. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/list.tsx +3 -1
  20. package/package.json +1 -1
@@ -28,7 +28,7 @@ export const ITActivityDay: ModelConfig =
28
28
  filter: [],
29
29
  sorter: ["id"],
30
30
  },
31
- fields: ["*","!created_at"],
31
+ fields: ["*","!createdAt","!updatedAt","!dateKey"],
32
32
  rowSelection: {
33
33
  actions: [
34
34
  {action: 'INSERT', desc: 'Insert'},
@@ -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/syncDataMngtPages.ts && dotenv -e .env.local -e .env -- ts-node scripts/sync-resources.ts",
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",
@@ -2,7 +2,7 @@
2
2
  * page-helpers.ts — 页面与权限管理的共享 DB 操作原语
3
3
  *
4
4
  * 接受 PrismaClient 作为参数,可被 CLI 脚本(page-manage.ts / permission-manage.ts)
5
- * 和 seed 函数(syncDataMngtPages.ts / seed/permissions.ts)共同调用。
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
- { path: pagePath }, // keep path in sync with model name on update
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=${page.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(
@@ -76,6 +76,7 @@ function App() {
76
76
  options={{
77
77
  syncWithLocation: true,
78
78
  warnWhenUnsavedChanges: true,
79
+ breadcrumb: null,
79
80
  }}
80
81
  >
81
82
  {resources.length === 0 ? (
@@ -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
- '请描述要添加的关联字段,例如:添加 author.name 作者姓名',
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: '要求:\n',
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: '要求:\n',
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: '要求:\n',
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
- '请填写字段名及选项来源,例如:字段 status,选项 ACTIVE|INACTIVE;或字段 gameId,选项来自关联表 game 的 name 字段',
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: '要求:\n',
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: '要求:\n',
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
- '请描述隐藏条件,例如:当 status 为 PUBLISHED 时隐藏 编辑 按钮',
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: '要求:\n',
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: '要求:\n',
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: '要求:\n',
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: '要求:\n',
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: '要求:\n',
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: '要求:\n',
1192
+ promptPrefix: '具体要求:',
1147
1193
  inputPlaceholder: '请描述你希望 AI 执行的自定义操作',
1148
1194
  promptSuffix:
1149
1195
  '\n你先理解下这个需求,然后找我澄清需求(非技术方案),我确认后再行动',
@@ -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>
@@ -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
- selectedKey &&
211
- (selectedKey.includes('/edit/') ||
212
- selectedKey.includes('/show/') ||
213
- selectedKey.endsWith('/create'))
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
- // `/edit/`、`/show/` 或以 `/create` 结尾的页面才会被豁免。
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((prompt: string) => {
102
- setAgentVisible(true);
103
- const sdk = sdkRef.current;
104
- if (!sdk) return;
105
- setTimeout(() => {
106
- sdk
107
- .sendUserPrompt(prompt)
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
- }, 300);
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: true,
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(data.payload)
208
- .catch((err: any) =>
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.sendUserPrompt(data.prompt).catch((err: any) => {
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(() => {
@@ -130,8 +130,12 @@ export const useDynamicResources = (): IResourceItem[] => {
130
130
  sortedAccessiblePages.forEach((page) => {
131
131
  if (!page) return;
132
132
 
133
- // Skip virtual pages
134
- if (page.isVirtual) return;
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 />}
@@ -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
- <Space style={{ marginBottom: 16 }}>
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
- </Space>
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
- <Space style={{ marginBottom: 16 }}>
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
- </Space>
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
- <Space style={{ marginBottom: 16 }}>
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
- </Space>
346
+ </div>
337
347
  <Table {...tableProps} rowKey="id">
338
348
  <Table.Column dataIndex="name" title="Name" />
339
349
  <Table.Column dataIndex="description" title="Description" />
@@ -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
- <Button icon={<ReloadOutlined />} onClick={fetchData} />
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 Instance Mgnt
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}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gadmin2n/schematics",
3
- "version": "0.0.82",
3
+ "version": "0.0.84",
4
4
  "description": "Gadmin - modern, fast, powerful node.js web framework (@schematics)",
5
5
  "main": "dist/index.js",
6
6
  "files": [