@gadmin2n/schematics 0.0.68 → 0.0.70

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 (223) hide show
  1. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/canvas.prisma +45 -0
  2. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/example.prisma +24 -23
  3. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/system.prisma +93 -90
  4. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Audit.ts +70 -0
  5. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Event.ts +3 -3
  6. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Page.ts +70 -0
  7. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/PageResource.ts +70 -0
  8. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Resource.ts +70 -0
  9. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/RolePages.ts +70 -0
  10. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/RoleResource.ts +70 -0
  11. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/SavedQuery.ts +70 -0
  12. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/User.ts +70 -0
  13. package/dist/lib/application/files/gadmin2-game-angle-demo/readme.md +95 -2
  14. package/dist/lib/application/files/gadmin2-game-angle-demo/server/.eslintrc.js +4 -2
  15. package/dist/lib/application/files/gadmin2-game-angle-demo/server/.prettierignore +7 -1
  16. package/dist/lib/application/files/gadmin2-game-angle-demo/server/config/index.ts +1 -3
  17. package/dist/lib/application/files/gadmin2-game-angle-demo/server/gadmin-cli.json +2 -2
  18. package/dist/lib/application/files/gadmin2-game-angle-demo/server/package.json +6 -5
  19. package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/lib/page-helpers.ts +157 -0
  20. package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/page-manage.ts +290 -0
  21. package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/permission-manage.ts +184 -0
  22. package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/prismaModels.ts +143 -0
  23. package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/sync-resources.ts +100 -0
  24. package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/syncDataMngtPages.ts +119 -0
  25. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/index.ts +1 -3
  26. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/permissions.ts +109 -143
  27. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/main.ts +5 -2
  28. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas.controller.spec.ts +20 -0
  29. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas.controller.ts +81 -0
  30. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas.dto.ts +49 -0
  31. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas.module.ts +11 -0
  32. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas.service.spec.ts +334 -0
  33. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas.service.ts +249 -0
  34. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/index.ts +2 -1
  35. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.service.ts +2 -2
  36. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.service.ts +17 -4
  37. package/dist/lib/application/files/gadmin2-game-angle-demo/server/yarn.lock +7737 -0
  38. package/dist/lib/application/files/gadmin2-game-angle-demo/web/.env +1 -0
  39. package/dist/lib/application/files/gadmin2-game-angle-demo/web/.eslintrc.json +38 -0
  40. package/dist/lib/application/files/gadmin2-game-angle-demo/web/.prettierignore +2 -0
  41. package/dist/lib/application/files/gadmin2-game-angle-demo/web/dev-shell-entry.html +49 -0
  42. package/dist/lib/application/files/gadmin2-game-angle-demo/web/package.json +13 -2
  43. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/App.tsx +137 -111
  44. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/auditLogProvider.ts +46 -44
  45. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/authProvider.ts +32 -12
  46. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/BulkActions.tsx +74 -23
  47. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/ListPageHeader.tsx +9 -9
  48. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/RowActions.tsx +57 -31
  49. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/SearchBar.tsx +53 -24
  50. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/SqlModal.tsx +148 -72
  51. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/AgentContext.tsx +190 -16
  52. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/ElementInspector.tsx +914 -63
  53. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/agentAttributes.ts +17 -8
  54. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/index.ts +0 -10
  55. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/inspectorActions.ts +969 -46
  56. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/pagePathUtils.ts +66 -0
  57. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/promptGenerator.ts +85 -25
  58. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/propPatcher.ts +84 -0
  59. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/auditLog/components/eventList/index.tsx +16 -20
  60. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/auditLog/components/index.ts +4 -4
  61. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/auditLog/components/logButton/index.tsx +13 -13
  62. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/auditLog/components/logList/index.tsx +15 -16
  63. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/auditLog/components/modalDiffViewer/index.tsx +15 -15
  64. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/auditLog/index.tsx +2 -2
  65. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/BarChart/index.tsx +896 -0
  66. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/ChartSwitcher/index.tsx +219 -0
  67. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/ChartViewer/index.tsx +159 -0
  68. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Filter/index.tsx +192 -0
  69. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/LineChart/index.tsx +1034 -0
  70. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumCard/NumCard.module.css +8 -0
  71. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumCard/index.tsx +509 -0
  72. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumLineCard/index.tsx +66 -0
  73. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/PieChart/index.tsx +552 -0
  74. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/RadarChart/index.tsx +263 -0
  75. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Section/index.tsx +35 -0
  76. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Table/index.tsx +207 -0
  77. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/TreemapChart/index.tsx +382 -0
  78. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/WorldMap/index.tsx +135 -0
  79. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/chart-constants.ts +53 -0
  80. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/icon/InfoIcon.tsx +8 -0
  81. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/icon/index.ts +1 -0
  82. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/config.ts +31 -0
  83. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/nameMap.json +9 -0
  84. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/world.geo.json +39349 -0
  85. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/metric-info-tooltip/index.tsx +19 -0
  86. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/contexts/business/index.tsx +12 -12
  87. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/contexts/color-mode/index.tsx +22 -26
  88. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/custom-avatar.tsx +13 -9
  89. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/index.ts +4 -4
  90. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/header.tsx +22 -37
  91. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/index.ts +4 -4
  92. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/layout.tsx +10 -10
  93. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/logo.tsx +1 -1
  94. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/sider.tsx +113 -65
  95. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/title.tsx +14 -14
  96. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/offLayoutArea/index.tsx +1 -1
  97. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/pagination-total.tsx +2 -2
  98. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/tags/index.ts +1 -1
  99. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/tags/role-tag.tsx +21 -21
  100. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/text.tsx +17 -13
  101. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/http.ts +26 -5
  102. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +221 -51
  103. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/constants/layout.ts +3 -3
  104. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/AddDataModal.tsx +199 -0
  105. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/AddPageModal.tsx +335 -0
  106. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/DeleteDataConfirm.tsx +56 -0
  107. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/DevShell.tsx +401 -0
  108. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/EditDataModal.tsx +129 -0
  109. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/SkillMenu.tsx +202 -0
  110. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/UndoConfirm.tsx +36 -0
  111. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/index.tsx +8 -0
  112. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/style.css +835 -0
  113. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/enums/audit-log.enum.ts +8 -8
  114. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/enums/index.ts +1 -1
  115. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/form.tsx +120 -70
  116. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/get-name-initials.ts +3 -3
  117. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/get-random-color.ts +11 -11
  118. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/http.ts +16 -19
  119. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/index.tsx +1 -1
  120. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/list.tsx +99 -73
  121. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/login.ts +22 -27
  122. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/page-tree.ts +74 -0
  123. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/show.tsx +95 -51
  124. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/utils.tsx +7 -3
  125. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/types.ts +15 -15
  126. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useBatchDelete.ts +10 -10
  127. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useBatchOperations.ts +8 -7
  128. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useBatchOperationsCore.ts +10 -10
  129. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useBatchUpdate.ts +10 -10
  130. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useDynamicResources.tsx +36 -27
  131. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useECharts.tsx +144 -0
  132. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useFetchData.ts +4 -4
  133. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useListPageState.ts +34 -34
  134. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useRoles.ts +8 -4
  135. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useRowSelection.ts +1 -1
  136. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useUserPageAccess.ts +55 -41
  137. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/i18n.ts +8 -8
  138. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/index.tsx +9 -2
  139. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/common.json +193 -0
  140. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/common.json +194 -0
  141. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/plugins/devShellPlugin.ts +81 -0
  142. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/components/action-cell.tsx +37 -37
  143. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/create.tsx +23 -31
  144. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/edit.tsx +34 -35
  145. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/index.ts +1 -1
  146. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/index.tsx +4 -6
  147. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/list.tsx +41 -34
  148. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/show.tsx +33 -20
  149. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasCell.tsx +87 -0
  150. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasEditPage.tsx +192 -0
  151. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasListPage.tsx +409 -0
  152. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasPage.tsx +1372 -0
  153. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasToolbar.tsx +384 -0
  154. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CodeFloatWindow.tsx +476 -0
  155. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/ComponentThumbnail.tsx +135 -0
  156. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/IsolatedLivePreview.tsx +101 -0
  157. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/LivePreview.tsx +236 -0
  158. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/PublishModal.tsx +200 -0
  159. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasApi.ts +92 -0
  160. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasConfigRegistry.tsx +25 -0
  161. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasContextMenuRegistry.tsx +875 -0
  162. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasDefaults.ts +126 -0
  163. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasI18n.ts +11 -0
  164. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/BarChartDataSourceModal.tsx +115 -0
  165. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/ChartViewerConfigModal.tsx +217 -0
  166. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/LineChartDataSourceModal.tsx +153 -0
  167. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/NumCardDataSourceModal.tsx +211 -0
  168. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/PromptModal.tsx +90 -0
  169. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/RadarChartDataSourceModal.tsx +87 -0
  170. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/TableDataSourceModal.tsx +204 -0
  171. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/demos.ts +1153 -0
  172. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/index.tsx +2 -0
  173. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/sectionCompactor.ts +45 -0
  174. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/types.ts +45 -0
  175. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas-page/index.tsx +108 -0
  176. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/game/create.tsx +105 -0
  177. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/game/edit.tsx +121 -0
  178. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/game/index.tsx +4 -0
  179. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/game/list.tsx +237 -0
  180. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/game/show.tsx +74 -0
  181. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/AssignRolesModal.tsx +29 -20
  182. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/CreatePageModal.tsx +3 -3
  183. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/EditPageModal.tsx +7 -3
  184. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/PageDetailDrawer.tsx +58 -23
  185. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/PageFormModal.tsx +206 -122
  186. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/hooks/usePageManagement.ts +8 -4
  187. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/index.ts +1 -1
  188. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/list.tsx +345 -190
  189. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/types.ts +1 -1
  190. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/permissionReadme/index.tsx +341 -340
  191. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/Components/CreateModal.tsx +2 -2
  192. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/Components/EditModal.tsx +2 -2
  193. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/Components/ResourceDetailDrawer.tsx +41 -24
  194. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/Components/modal.tsx +64 -36
  195. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/index.ts +2 -2
  196. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/list.tsx +78 -40
  197. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/Components/CreateModal.tsx +3 -3
  198. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/Components/EditModal.tsx +4 -4
  199. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/Components/RoleDetailDrawer.tsx +19 -9
  200. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/Components/modal.tsx +45 -47
  201. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/hooks/useRolePage.ts +4 -4
  202. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/index.ts +1 -1
  203. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/list.tsx +121 -147
  204. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/types.ts +1 -1
  205. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/create-modal.tsx +2 -2
  206. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/edit-modal.tsx +2 -2
  207. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/form-modal.tsx +25 -19
  208. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/index.ts +5 -5
  209. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/role-tag.tsx +10 -10
  210. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/show-drawer.tsx +31 -26
  211. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/index.ts +1 -1
  212. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/list.tsx +76 -71
  213. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/setupTests.ts +1 -1
  214. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/types/audit-log.ts +1 -1
  215. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/types/index.ts +3 -3
  216. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/types/role.ts +1 -1
  217. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/types/user.ts +1 -1
  218. package/dist/lib/application/files/gadmin2-game-angle-demo/web/vite.config.ts +42 -25
  219. package/dist/lib/application/files/gadmin2-game-angle-demo/web/yarn.lock +1193 -32
  220. package/package.json +1 -1
  221. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/seedDataMngtPages.ts +0 -258
  222. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/AgentPanel.tsx +0 -497
  223. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/skills.ts +0 -464
@@ -1,7 +1,7 @@
1
- import React, { lazy, Suspense } from "react";
2
- import { Outlet, Route } from "react-router-dom";
3
- import { Spin } from "antd";
4
- import generatedResources from "generated/resources";
1
+ import React, { lazy, Suspense } from 'react';
2
+ import { Outlet, Route } from 'react-router-dom';
3
+ import { Spin } from 'antd';
4
+ import generatedResources from 'generated/resources';
5
5
 
6
6
  // ─── Types ───────────────────────────────────────────────────────────────────
7
7
 
@@ -15,6 +15,13 @@ interface RouteEntry {
15
15
  wrapper?: LazyComp | AnyComp;
16
16
  index?: boolean;
17
17
  children?: Record<string, RouteEntry>;
18
+ /**
19
+ * Programmatic-only — never hand-written.
20
+ * Set automatically by buildDataMngtChildren (res.name) or derived via
21
+ * extractSourceDir() from the component's import string at index-build time.
22
+ * Identifies the routes/ subdirectory that owns this route group.
23
+ */
24
+ _sourceDir?: string;
18
25
  }
19
26
 
20
27
  // ─── Data-Mngt dynamic route helpers ─────────────────────────────────────────
@@ -24,12 +31,19 @@ interface RouteEntry {
24
31
  * These must NOT be auto-registered again under dataMngt.
25
32
  */
26
33
  const SYSTEM_RESOURCE_NAMES = new Set([
27
- "user", "role", "page", "resource", "audit",
28
- "game", "roleResource", "pageResource", "rolePages",
34
+ 'user',
35
+ 'role',
36
+ 'page',
37
+ 'resource',
38
+ 'audit',
39
+ 'game',
40
+ 'roleResource',
41
+ 'pageResource',
42
+ 'rolePages',
29
43
  ]);
30
44
 
31
45
  /** camelCase → PascalCase (reverses toCamelCase in seedDataMngtPages) */
32
- function toPascalCase(str: string): string {
46
+ export function toPascalCase(str: string): string {
33
47
  return str.charAt(0).toUpperCase() + str.slice(1);
34
48
  }
35
49
 
@@ -41,8 +55,8 @@ function toPascalCase(str: string): string {
41
55
  */
42
56
  function toKebabCase(str: string): string {
43
57
  return str
44
- .replace(/([a-z0-9])([A-Z])/g, "$1-$2")
45
- .replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2")
58
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
59
+ .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')
46
60
  .toLowerCase();
47
61
  }
48
62
 
@@ -65,8 +79,12 @@ function buildDataMngtChildren(): Record<string, RouteEntry> {
65
79
  if (SYSTEM_RESOURCE_NAMES.has(res.name)) continue;
66
80
 
67
81
  // generated/resources stores components in meta.components
68
- const { list: ListComp, show: ShowComp, edit: EditComp, create: CreateComp } =
69
- (res.meta as any).components ?? {};
82
+ const {
83
+ list: ListComp,
84
+ show: ShowComp,
85
+ edit: EditComp,
86
+ create: CreateComp,
87
+ } = (res.meta as any).components ?? {};
70
88
 
71
89
  if (!ListComp) continue;
72
90
 
@@ -76,13 +94,15 @@ function buildDataMngtChildren(): Record<string, RouteEntry> {
76
94
 
77
95
  children[res.name] = {
78
96
  path: slug,
97
+ _sourceDir: res.name, // directory name == resource name for dataMngt routes
79
98
  // No component on the parent — React Router renders <Outlet /> so that
80
99
  // the index / show / edit / create children can each occupy the full view.
81
100
  children: {
82
- list: { path: "", index: true, component: ListComp as AnyComp },
83
- show: { path: "show/:id", component: ShowComp as AnyComp },
84
- edit: { path: "edit/:id", component: EditComp as AnyComp },
85
- create: { path: "create", component: CreateComp as AnyComp },
101
+ list: { path: '', index: true, component: ListComp as AnyComp },
102
+ show: { path: 'show/:id', component: ShowComp as AnyComp },
103
+ edit: { path: 'edit/:id', component: EditComp as AnyComp },
104
+ create: { path: 'create', component: CreateComp as AnyComp },
105
+ clone: { path: 'clone/:id', component: CreateComp as AnyComp },
86
106
  },
87
107
  };
88
108
  }
@@ -90,7 +110,50 @@ function buildDataMngtChildren(): Record<string, RouteEntry> {
90
110
  return children;
91
111
  }
92
112
 
93
- // ─── Suspense wrapper ────────────────────────────────────────────────────────
113
+ /**
114
+ * Extract the routes/ subdirectory name from a lazy component's import string.
115
+ *
116
+ * Works by calling toString() on the factory function — in both dev (Vite
117
+ * module-graph) and build (Rollup) modes the original import specifier is
118
+ * preserved in the stringified source.
119
+ *
120
+ * Examples:
121
+ * import("routes/user") → "user"
122
+ * import("routes/iTActivityDay") → "iTActivityDay"
123
+ * import("routes/page/list") → "page" (strip trailing page-type segment)
124
+ *
125
+ * Returns null when the string cannot be parsed (safe fallback).
126
+ */
127
+ function extractSourceDir(
128
+ component: LazyComp | AnyComp | undefined,
129
+ ): string | null {
130
+ if (!component) return null;
131
+ try {
132
+ // React.lazy stores the factory in _payload._result before the promise
133
+ // resolves. Stringify it to find the original import() specifier.
134
+ const c = component as any;
135
+ const factory: unknown = c._payload?._result;
136
+ const src =
137
+ typeof factory === 'function'
138
+ ? (factory as () => unknown).toString()
139
+ : typeof component === 'function'
140
+ ? (component as () => unknown).toString()
141
+ : '';
142
+
143
+ const match = src.match(/import\(["'`]routes\/([^"'`]+)["'`]\)/);
144
+ if (!match) return null;
145
+
146
+ // Strip trailing page-type segments: list, create, edit, show, index
147
+ const parts = match[1].split('/');
148
+ const PAGE_TYPES = new Set(['list', 'create', 'edit', 'show', 'index']);
149
+ while (parts.length > 1 && PAGE_TYPES.has(parts[parts.length - 1])) {
150
+ parts.pop();
151
+ }
152
+ return parts.join('/') || null;
153
+ } catch {
154
+ return null;
155
+ }
156
+ }
94
157
 
95
158
  const S = ({ children }: { children: React.ReactNode }) => (
96
159
  <Suspense fallback={<Spin size="large" />}>{children}</Suspense>
@@ -101,50 +164,50 @@ const S = ({ children }: { children: React.ReactNode }) => (
101
164
  export const routeRegistry: Record<string, RouteEntry> = {
102
165
  // ── Administration ─────────────────────────────────────────────────────────
103
166
  admin: {
104
- path: "/admin",
167
+ path: '/admin',
105
168
  children: {
106
169
  permission: {
107
- path: "permission",
170
+ path: 'permission',
108
171
  children: {
109
172
  // 菜单指引 — sortOrder 1020, code: admin.permission.readme
110
173
  permission_readme: {
111
- path: "readme",
174
+ path: 'readme',
112
175
  component: lazy(() =>
113
- import("routes/permissionReadme").then((m) => ({
176
+ import('routes/permissionReadme').then((m) => ({
114
177
  default: m.PermissionReadmePage,
115
178
  })),
116
179
  ),
117
180
  },
118
181
  // 用户管理 — sortOrder 1030, code: admin.permission.user
119
182
  user: {
120
- path: "user",
183
+ path: 'user',
121
184
  component: lazy(() =>
122
- import("routes/user").then((m) => ({ default: m.UserListPage })),
185
+ import('routes/user').then((m) => ({ default: m.UserListPage })),
123
186
  ),
124
187
  },
125
188
  // 角色管理 — sortOrder 1040, code: admin.permission.role
126
189
  role: {
127
- path: "role-list",
190
+ path: 'role-list',
128
191
  component: lazy(() =>
129
- import("routes/role").then((m) => ({
192
+ import('routes/role').then((m) => ({
130
193
  default: m.RoleManagementListPage,
131
194
  })),
132
195
  ),
133
196
  },
134
197
  // 页面管理 — sortOrder 1050, code: admin.permission.page
135
198
  page: {
136
- path: "page-list",
199
+ path: 'page-list',
137
200
  component: lazy(() =>
138
- import("routes/page/list").then((m) => ({
201
+ import('routes/page/list').then((m) => ({
139
202
  default: m.PageManagementListPage,
140
203
  })),
141
204
  ),
142
205
  },
143
206
  // 资源管理 — sortOrder 1060, code: admin.permission.resource
144
207
  resource: {
145
- path: "resource-list",
208
+ path: 'resource-list',
146
209
  component: lazy(() =>
147
- import("routes/resource").then((m) => ({
210
+ import('routes/resource').then((m) => ({
148
211
  default: m.ResourceManagementListPage,
149
212
  })),
150
213
  ),
@@ -152,61 +215,168 @@ export const routeRegistry: Record<string, RouteEntry> = {
152
215
  },
153
216
  },
154
217
  dataMngt: {
155
- path: "data-mngt",
218
+ path: 'data-mngt',
156
219
  children: buildDataMngtChildren(),
157
220
  },
221
+ // Canvas
222
+ canvas: {
223
+ path: 'canvas',
224
+ children: {
225
+ list: {
226
+ path: '',
227
+ index: true,
228
+ component: lazy(() =>
229
+ import('routes/canvas').then((m) => ({
230
+ default: m.CanvasListPage,
231
+ })),
232
+ ),
233
+ },
234
+ edit: {
235
+ path: 'edit/:id',
236
+ component: lazy(() =>
237
+ import('routes/canvas').then((m) => ({
238
+ default: m.CanvasEditPage,
239
+ })),
240
+ ),
241
+ },
242
+ },
243
+ },
244
+ // Canvas published pages (dynamic, DB-driven)
245
+ 'canvas-page': {
246
+ path: 'p/:slug',
247
+ component: lazy(() => import('routes/canvas-page')),
248
+ },
158
249
  game: {
159
- path: "game-list",
250
+ path: 'game-list',
160
251
  children: {
161
- list: { path: "", index: true, component: lazy(() => import("routes/game").then((m) => ({ default: m.GameList }))) },
162
- show: { path: "show/:id", component: lazy(() => import("routes/game").then((m) => ({ default: m.GameShow }))) },
163
- edit: { path: "edit/:id", component: lazy(() => import("routes/game").then((m) => ({ default: m.GameEdit }))) },
164
- create: { path: "create", component: lazy(() => import("routes/game").then((m) => ({ default: m.GameCreate }))) },
252
+ list: {
253
+ path: '',
254
+ index: true,
255
+ component: lazy(() =>
256
+ import('routes/game').then((m) => ({ default: m.GameList })),
257
+ ),
258
+ },
259
+ show: {
260
+ path: 'show/:id',
261
+ component: lazy(() =>
262
+ import('routes/game').then((m) => ({ default: m.GameShow })),
263
+ ),
264
+ },
265
+ edit: {
266
+ path: 'edit/:id',
267
+ component: lazy(() =>
268
+ import('routes/game').then((m) => ({ default: m.GameEdit })),
269
+ ),
270
+ },
271
+ create: {
272
+ path: 'create',
273
+ component: lazy(() =>
274
+ import('routes/game').then((m) => ({ default: m.GameCreate })),
275
+ ),
276
+ },
165
277
  },
166
278
  },
167
279
  // 操作日志 — sortOrder 1070, code: admin.audit
168
280
  audits: {
169
- path: "audit-log-list",
281
+ path: 'audit-log-list',
170
282
  component: lazy(() =>
171
- import("routes/audit").then((m) => ({ default: m.AuditLogPage })),
283
+ import('routes/audit').then((m) => ({ default: m.AuditLogPage })),
172
284
  ),
173
285
  },
174
286
  },
175
287
  },
176
288
  };
177
289
 
178
- // ─── Path Index (getRoutePath) ────────────────────────────────────────────────
290
+ // ─── Path + SourceDir indices ─────────────────────────────────────────────────
179
291
 
180
- function buildPathIndex(
292
+ /**
293
+ * Walk the registry tree once and produce two flat maps:
294
+ *
295
+ * pathIndex : routeKey → absolute URL path (e.g. "user" → "/admin/permission/user")
296
+ * sourceDirIndex : URL pattern → routes/ dir (e.g. "/admin/permission/user" → "user")
297
+ *
298
+ * URL patterns in sourceDirIndex use ":id" for dynamic segments so they can
299
+ * be matched against live pathnames after replacing numeric/uuid segments.
300
+ */
301
+ function buildIndices(
181
302
  entries: Record<string, RouteEntry>,
182
- parentPath = "",
183
- ): Record<string, string> {
184
- const result: Record<string, string> = {};
303
+ parentPath = '',
304
+ inheritedSourceDir: string | null = null,
305
+ ): {
306
+ pathIndex: Record<string, string>;
307
+ sourceDirIndex: Record<string, string>;
308
+ } {
309
+ const pathIndex: Record<string, string> = {};
310
+ const sourceDirIndex: Record<string, string> = {};
311
+
185
312
  for (const [key, entry] of Object.entries(entries)) {
186
- const fullPath = entry.path.startsWith("/")
313
+ const fullPath = entry.path.startsWith('/')
187
314
  ? entry.path
188
- : entry.path === ""
315
+ : entry.path === ''
189
316
  ? parentPath
190
- : entry.path.startsWith("?")
317
+ : entry.path.startsWith('?')
191
318
  ? parentPath + entry.path
192
- : parentPath + "/" + entry.path;
193
- result[key] = fullPath;
319
+ : parentPath + '/' + entry.path;
320
+
321
+ pathIndex[key] = fullPath;
322
+
323
+ // Resolve sourceDir for this entry:
324
+ // Priority: explicit _sourceDir > extracted from component > inherited from parent
325
+ const resolved =
326
+ entry._sourceDir ??
327
+ extractSourceDir(entry.component) ??
328
+ inheritedSourceDir;
329
+
330
+ // Register in sourceDirIndex when we have both a real path and a sourceDir.
331
+ // Use the path without query-string, with dynamic segments normalised to ":id".
332
+ if (resolved) {
333
+ const pattern = fullPath.split('?')[0];
334
+ sourceDirIndex[pattern] = resolved;
335
+ }
336
+
194
337
  if (entry.children) {
195
- Object.assign(result, buildPathIndex(entry.children, fullPath.split("?")[0]));
338
+ const sub = buildIndices(
339
+ entry.children,
340
+ fullPath.split('?')[0],
341
+ resolved,
342
+ );
343
+ Object.assign(pathIndex, sub.pathIndex);
344
+ Object.assign(sourceDirIndex, sub.sourceDirIndex);
196
345
  }
197
346
  }
198
- return result;
347
+
348
+ return { pathIndex, sourceDirIndex };
199
349
  }
200
350
 
201
- const pathIndex = buildPathIndex(routeRegistry);
351
+ const { pathIndex, sourceDirIndex } = buildIndices(routeRegistry);
202
352
 
203
353
  export function getRoutePath(pageCode: string): string | null {
204
354
  return pathIndex[pageCode] ?? null;
205
355
  }
206
356
 
357
+ /**
358
+ * Given a live pathname (e.g. "/admin/permission/user" or "/admin/game-list/edit/123"),
359
+ * return the routes/ subdirectory that owns it (e.g. "user", "game").
360
+ *
361
+ * Matching strategy: replace trailing numeric / uuid-like segments with ":id"
362
+ * so the live URL aligns with the pattern stored during index build.
363
+ */
364
+ export function getRouteSourceDir(pathname: string): string | null {
365
+ // Normalise: strip trailing slash, replace numeric/uuid segments with :id
366
+ const normalised = pathname
367
+ .replace(/\/$/, '')
368
+ .replace(/\/[0-9a-f]{8}-[0-9a-f-]{27,35}/gi, '/:id') // uuid
369
+ .replace(/\/\d+/g, '/:id'); // numeric id
370
+
371
+ return sourceDirIndex[normalised] ?? null;
372
+ }
373
+
207
374
  // ─── renderRoutes() ──────────────────────────────────────────────────────────
208
375
 
209
- function renderEntry(key: string, entry: RouteEntry): React.ReactElement | null {
376
+ function renderEntry(
377
+ key: string,
378
+ entry: RouteEntry,
379
+ ): React.ReactElement | null {
210
380
  let element: React.ReactNode | undefined;
211
381
  if (entry.component) {
212
382
  const Comp = entry.component;
@@ -230,7 +400,7 @@ function renderEntry(key: string, entry: RouteEntry): React.ReactElement | null
230
400
  return <Route key={key} index element={element ?? null} />;
231
401
  }
232
402
 
233
- const routePath = entry.path.split("?")[0];
403
+ const routePath = entry.path.split('?')[0];
234
404
 
235
405
  const childRoutes = Object.entries(entry.children ?? {})
236
406
  .map(([k, e]) => renderEntry(k, e))
@@ -1,14 +1,14 @@
1
1
  /** List / Create 页面顶层组件的内容区样式 */
2
2
  export const LIST_CONTENT_PROPS = {
3
- style: { marginTop: "1rem" },
3
+ style: { marginTop: '1rem' },
4
4
  } as const;
5
5
 
6
6
  /** Show 页面顶层组件的内容区样式 */
7
7
  export const SHOW_CONTENT_PROPS = {
8
8
  style: {
9
- backgroundColor: "#f5f5f5",
9
+ backgroundColor: '#f5f5f5',
10
10
  padding: 0,
11
- marginTop: "1rem",
11
+ marginTop: '1rem',
12
12
  },
13
13
  bodyStyle: {
14
14
  padding: 0,
@@ -0,0 +1,199 @@
1
+ import React, { useState } from 'react';
2
+
3
+ interface Props {
4
+ onConfirm: (prompt: string) => void;
5
+ onCancel: () => void;
6
+ }
7
+
8
+ const GUIDED_QUESTIONS = [
9
+ {
10
+ key: 'purpose',
11
+ label: '1️⃣ 这个表是用来做什么的?',
12
+ placeholder: '比如:记录订单 / 管理客户 / 记录库存',
13
+ type: 'input',
14
+ optional: false,
15
+ },
16
+ {
17
+ key: 'fields',
18
+ label: '2️⃣ 你会往里面"填写"哪些信息?',
19
+ placeholder: '比如:姓名、电话、金额、时间…',
20
+ type: 'textarea',
21
+ optional: false,
22
+ },
23
+ {
24
+ key: 'statuses',
25
+ label: '3️⃣ 有没有"固定的几种状态"?',
26
+ placeholder: '比如:订单有 未支付 / 已支付 / 已取消',
27
+ type: 'input',
28
+ optional: true,
29
+ },
30
+ {
31
+ key: 'relations',
32
+ label: '4️⃣ 这个数据和谁有关?',
33
+ placeholder: '比如:订单属于某个用户?一个用户有多个订单?',
34
+ type: 'input',
35
+ optional: true,
36
+ },
37
+ {
38
+ key: 'queries',
39
+ label: '5️⃣ 你平时会怎么查这些数据?',
40
+ placeholder: '比如:按用户名查、按时间查、看最近的记录',
41
+ type: 'input',
42
+ optional: true,
43
+ },
44
+ {
45
+ key: 'scale',
46
+ label: '6️⃣ 大概会有多少数据?',
47
+ placeholder: '比如:每天几十条 / 每天几万条',
48
+ type: 'input',
49
+ optional: true,
50
+ },
51
+ {
52
+ key: 'special',
53
+ label: '7️⃣ 有没有特殊要求?',
54
+ placeholder: '比如:可以删除吗?要不要保留历史记录?',
55
+ type: 'textarea',
56
+ optional: true,
57
+ },
58
+ ];
59
+
60
+ export default function AddDataModal({ onConfirm, onCancel }: Props) {
61
+ const [activeTab, setActiveTab] = useState<'free' | 'guided'>('free');
62
+ const [freeText, setFreeText] = useState('');
63
+ const [answers, setAnswers] = useState<Record<string, string>>({});
64
+
65
+ function handleConfirm() {
66
+ if (activeTab === 'free') {
67
+ const text = freeText.trim();
68
+ if (!text) {
69
+ alert('请输入数据描述');
70
+ return;
71
+ }
72
+ onConfirm(
73
+ '请帮我使用 prisma-schema-update skill 添加一个新的prisma model。\n\n以下是关于这个业务数据的描述:\n' +
74
+ text,
75
+ );
76
+ } else {
77
+ if (!answers.purpose?.trim()) {
78
+ alert('请至少填写"这个表是用来做什么的"');
79
+ return;
80
+ }
81
+ const lines = [
82
+ '请帮我使用 prisma-schema-update skill 添加一个新的prisma model。\n\n以下是我对这个业务数据的描述:\n',
83
+ ];
84
+ GUIDED_QUESTIONS.forEach((q) => {
85
+ if (answers[q.key]?.trim()) {
86
+ lines.push(
87
+ q.label.replace(/(可选)/g, '').trim() +
88
+ '\n' +
89
+ answers[q.key].trim(),
90
+ );
91
+ }
92
+ });
93
+ onConfirm(lines.join('\n\n'));
94
+ }
95
+ }
96
+
97
+ return (
98
+ <div
99
+ id="add-data-modal-overlay"
100
+ onClick={(e) => {
101
+ if (e.target === e.currentTarget) onCancel();
102
+ }}
103
+ >
104
+ <div id="add-data-modal-card">
105
+ <div className="add-data-modal-header">
106
+ <h3>🗄️ 添加新的业务数据</h3>
107
+ <button className="add-data-modal-close" onClick={onCancel}>
108
+ ×
109
+ </button>
110
+ </div>
111
+
112
+ <div className="add-data-modal-tabs">
113
+ {(['free', 'guided'] as const).map((tab) => (
114
+ <button
115
+ key={tab}
116
+ className={
117
+ 'add-data-modal-tab' + (activeTab === tab ? ' active' : '')
118
+ }
119
+ onClick={() => setActiveTab(tab)}
120
+ >
121
+ {tab === 'free' ? '自由描述' : '引导式填写'}
122
+ </button>
123
+ ))}
124
+ </div>
125
+
126
+ <div className="add-data-modal-body">
127
+ {activeTab === 'free' && (
128
+ <div className="add-data-tab-panel active">
129
+ <p className="add-data-hint">
130
+ 用日常语言描述你想要的数据表,你也可以使用其他AI工具帮你生成更详细的需求,然后再输入到这边。
131
+ </p>
132
+ <textarea
133
+ className="add-data-free-textarea"
134
+ value={freeText}
135
+ onChange={(e) => setFreeText(e.target.value)}
136
+ placeholder={
137
+ '我要一个订单表:\n- 用户可以下多个订单\n- 支持支付状态\n- 要能查用户订单列表\n- 未来可能有退款'
138
+ }
139
+ />
140
+ </div>
141
+ )}
142
+ {activeTab === 'guided' && (
143
+ <div className="add-data-tab-panel active">
144
+ <p className="add-data-hint">
145
+ 我们来一起设计一个数据表 😊 用日常语言回答下面几个问题:
146
+ </p>
147
+ {GUIDED_QUESTIONS.map((q) => (
148
+ <div className="guided-question" key={q.key}>
149
+ <label className="guided-question-label">
150
+ {q.label}
151
+ {q.optional && (
152
+ <span className="guided-optional-tag">(可选)</span>
153
+ )}
154
+ </label>
155
+ {q.type === 'textarea' ? (
156
+ <textarea
157
+ className="guided-question-textarea"
158
+ placeholder={q.placeholder}
159
+ rows={2}
160
+ value={answers[q.key] || ''}
161
+ onChange={(e) =>
162
+ setAnswers((prev) => ({
163
+ ...prev,
164
+ [q.key]: e.target.value,
165
+ }))
166
+ }
167
+ />
168
+ ) : (
169
+ <input
170
+ className="guided-question-input"
171
+ type="text"
172
+ placeholder={q.placeholder}
173
+ value={answers[q.key] || ''}
174
+ onChange={(e) =>
175
+ setAnswers((prev) => ({
176
+ ...prev,
177
+ [q.key]: e.target.value,
178
+ }))
179
+ }
180
+ />
181
+ )}
182
+ </div>
183
+ ))}
184
+ </div>
185
+ )}
186
+ </div>
187
+
188
+ <div className="add-data-modal-footer">
189
+ <button className="add-data-btn-cancel" onClick={onCancel}>
190
+ 取消
191
+ </button>
192
+ <button className="add-data-btn-confirm" onClick={handleConfirm}>
193
+ 确认,开始生成
194
+ </button>
195
+ </div>
196
+ </div>
197
+ </div>
198
+ );
199
+ }