@lovrabet/rabetbase-cli 2.0.2-beta.1

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 (163) hide show
  1. package/LICENSE +45 -0
  2. package/README.md +605 -0
  3. package/lib/ai-setup/config.js +1 -0
  4. package/lib/api/api-doc-ui.js +1 -0
  5. package/lib/api/api-doc.js +1 -0
  6. package/lib/api/api-pull-ui.js +1 -0
  7. package/lib/api/fetch-model-list.js +1 -0
  8. package/lib/api/generate-api-file.js +1 -0
  9. package/lib/api/main.js +1 -0
  10. package/lib/api/pull-silent.js +1 -0
  11. package/lib/app-menu/app-menu-sync-ui.js +1 -0
  12. package/lib/app-menu/create-menu.js +1 -0
  13. package/lib/app-menu/get-local-pages.js +1 -0
  14. package/lib/app-menu/get-online-menu-list.js +1 -0
  15. package/lib/app-menu/types.js +1 -0
  16. package/lib/app-menu/use-get-online-menu-list.js +1 -0
  17. package/lib/app-menu/utils.js +1 -0
  18. package/lib/app-menu/valid-url.js +1 -0
  19. package/lib/app-menu-update-cdn/current-content.js +1 -0
  20. package/lib/app-menu-update-cdn/input-cdn-asset.js +1 -0
  21. package/lib/app-menu-update-cdn/main.js +1 -0
  22. package/lib/app-menu-update-cdn/types.js +1 -0
  23. package/lib/app-menu-update-cdn/update-menu-cdn-url.js +1 -0
  24. package/lib/auth/auth-server-ui.js +1 -0
  25. package/lib/auth/auth-server.js +1 -0
  26. package/lib/auth/constant.js +1 -0
  27. package/lib/auth/get-cookie.js +1 -0
  28. package/lib/auth/is-session-valid.js +1 -0
  29. package/lib/auth/logout.js +1 -0
  30. package/lib/cli-flags.js +1 -0
  31. package/lib/cli.js +2 -0
  32. package/lib/commands/api.js +1 -0
  33. package/lib/commands/app.js +1 -0
  34. package/lib/commands/auth.js +1 -0
  35. package/lib/commands/bff/delete.js +1 -0
  36. package/lib/commands/bff/detail.js +1 -0
  37. package/lib/commands/bff/index.js +1 -0
  38. package/lib/commands/bff/list.js +1 -0
  39. package/lib/commands/bff/new.js +1 -0
  40. package/lib/commands/bff/pull.js +1 -0
  41. package/lib/commands/bff/push.js +1 -0
  42. package/lib/commands/bff/status.js +1 -0
  43. package/lib/commands/build.js +1 -0
  44. package/lib/commands/codegen/index.js +1 -0
  45. package/lib/commands/codegen/sdk.js +1 -0
  46. package/lib/commands/codegen/sql.js +1 -0
  47. package/lib/commands/config.js +1 -0
  48. package/lib/commands/create.js +1 -0
  49. package/lib/commands/dataset/detail.js +1 -0
  50. package/lib/commands/dataset/index.js +1 -0
  51. package/lib/commands/dataset/links.js +1 -0
  52. package/lib/commands/dataset/list.js +1 -0
  53. package/lib/commands/dataset/operations.js +1 -0
  54. package/lib/commands/init.js +1 -0
  55. package/lib/commands/logout.js +1 -0
  56. package/lib/commands/logs.js +1 -0
  57. package/lib/commands/mcp.js +1 -0
  58. package/lib/commands/menu.js +1 -0
  59. package/lib/commands/preview.js +1 -0
  60. package/lib/commands/registry.js +1 -0
  61. package/lib/commands/run.js +1 -0
  62. package/lib/commands/skill.js +1 -0
  63. package/lib/commands/sql/detail.js +1 -0
  64. package/lib/commands/sql/exec.js +1 -0
  65. package/lib/commands/sql/index.js +1 -0
  66. package/lib/commands/sql/list.js +1 -0
  67. package/lib/commands/sql/save.js +1 -0
  68. package/lib/commands/sql/validate.js +1 -0
  69. package/lib/commands/start.js +1 -0
  70. package/lib/config/config-help.js +1 -0
  71. package/lib/config/main.js +1 -0
  72. package/lib/constant/cli.js +1 -0
  73. package/lib/constant/domain.js +1 -0
  74. package/lib/constant/env.js +1 -0
  75. package/lib/context.js +1 -0
  76. package/lib/core/alias-resolver.js +1 -0
  77. package/lib/core/api-client.js +1 -0
  78. package/lib/core/bff/config.js +1 -0
  79. package/lib/core/bff/file-system.js +1 -0
  80. package/lib/core/bff/hash.js +1 -0
  81. package/lib/core/bff/lock.js +1 -0
  82. package/lib/core/bff/types.js +1 -0
  83. package/lib/core/bff/utils.js +1 -0
  84. package/lib/core/db-resolver.js +1 -0
  85. package/lib/core/sql-validator.js +1 -0
  86. package/lib/create-app/enhanced-guided-create.js +1 -0
  87. package/lib/create-app/format-elapsed.js +1 -0
  88. package/lib/create-app/main.js +1 -0
  89. package/lib/create-app/non-interactive.js +1 -0
  90. package/lib/create-app/task-finished.js +1 -0
  91. package/lib/create-app/task-loading.js +1 -0
  92. package/lib/create-app/task-running.js +1 -0
  93. package/lib/create-app/task-time.js +1 -0
  94. package/lib/create-app/use-copy-project-template.js +1 -0
  95. package/lib/create-app/use-format-code.js +1 -0
  96. package/lib/create-app/use-install-dependencies.js +1 -0
  97. package/lib/errors.js +1 -0
  98. package/lib/framework/flags.js +1 -0
  99. package/lib/framework/help.js +1 -0
  100. package/lib/framework/index.js +1 -0
  101. package/lib/framework/output.js +1 -0
  102. package/lib/framework/response.js +1 -0
  103. package/lib/framework/runner.js +1 -0
  104. package/lib/framework/types.js +1 -0
  105. package/lib/generated/build-info.js +1 -0
  106. package/lib/help.js +1 -0
  107. package/lib/init/main.js +1 -0
  108. package/lib/mcp/McpInstallUI.js +1 -0
  109. package/lib/mcp/claude.js +1 -0
  110. package/lib/mcp/cursor.js +1 -0
  111. package/lib/mcp/main.js +1 -0
  112. package/lib/mcp/mcp-install-non-interactive.js +1 -0
  113. package/lib/mcp/mcp-installer.js +1 -0
  114. package/lib/skills/main.js +1 -0
  115. package/lib/skills/npx-skills-add.js +1 -0
  116. package/lib/types/index.js +1 -0
  117. package/lib/ui/IDESelector.js +1 -0
  118. package/lib/ui/useIDESelection.js +1 -0
  119. package/lib/utils/ai_config.js +1 -0
  120. package/lib/utils/cdn-config.js +1 -0
  121. package/lib/utils/check-sdk-version.js +1 -0
  122. package/lib/utils/cli-version-check.js +1 -0
  123. package/lib/utils/config.js +1 -0
  124. package/lib/utils/copy-directory.js +1 -0
  125. package/lib/utils/file-utils.js +1 -0
  126. package/lib/utils/guides-cdn.js +1 -0
  127. package/lib/utils/http-client.js +1 -0
  128. package/lib/utils/logger.js +1 -0
  129. package/lib/utils/rules-cdn.js +1 -0
  130. package/lib/utils/sleep.js +1 -0
  131. package/lib/utils/template-replacer.js +1 -0
  132. package/package.json +77 -0
  133. package/sidecar/flags.json +10 -0
  134. package/templates/README.md +97 -0
  135. package/templates/generate-api/api.ts.tpl +47 -0
  136. package/templates/generate-api/client.ts.tpl +64 -0
  137. package/templates/projects/sub-app-react-demo/.prettierrc +1 -0
  138. package/templates/projects/sub-app-react-demo/CHANGELOG.md +53 -0
  139. package/templates/projects/sub-app-react-demo/README.md +318 -0
  140. package/templates/projects/sub-app-react-demo/docs/API_RULE_CHANGE.md +212 -0
  141. package/templates/projects/sub-app-react-demo/docs/quick-start.md +526 -0
  142. package/templates/projects/sub-app-react-demo/index.html +27 -0
  143. package/templates/projects/sub-app-react-demo/package.json +34 -0
  144. package/templates/projects/sub-app-react-demo/public/logo.svg +1 -0
  145. package/templates/projects/sub-app-react-demo/public/vite.svg +1 -0
  146. package/templates/projects/sub-app-react-demo/src/api/api.ts +83 -0
  147. package/templates/projects/sub-app-react-demo/src/api/client.ts +64 -0
  148. package/templates/projects/sub-app-react-demo/src/layouts/MainLayout.tsx +311 -0
  149. package/templates/projects/sub-app-react-demo/src/main.tsx +48 -0
  150. package/templates/projects/sub-app-react-demo/src/pages/dashboard/index.tsx +572 -0
  151. package/templates/projects/sub-app-react-demo/src/pages/data-screen/index.tsx +526 -0
  152. package/templates/projects/sub-app-react-demo/src/pages/index.tsx +467 -0
  153. package/templates/projects/sub-app-react-demo/src/pages/sdk-demo/index.tsx +453 -0
  154. package/templates/projects/sub-app-react-demo/src/pages/workbench/index.module.css +293 -0
  155. package/templates/projects/sub-app-react-demo/src/pages/workbench/index.tsx +155 -0
  156. package/templates/projects/sub-app-react-demo/src/router/index.tsx +30 -0
  157. package/templates/projects/sub-app-react-demo/src/style.css +92 -0
  158. package/templates/projects/sub-app-react-demo/src/utils/api.ts +12 -0
  159. package/templates/projects/sub-app-react-demo/src/vite-env.d.ts +2 -0
  160. package/templates/projects/sub-app-react-demo/tsconfig.json +26 -0
  161. package/templates/projects/sub-app-react-demo/vite.config.ts +111 -0
  162. package/templates/rules/lovrabet_rules.mdc.tpl +891 -0
  163. package/templates/skill/SKILL.md.tpl +120 -0
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Generated by Lovrabet CLI
3
+ * Created: 2026-01-16T10:07:17.932Z
4
+ *
5
+ * 这个文件包含了项目的模型配置,并自动注册到 SDK 中
6
+ * CLI 工具会自动维护这个文件,通常不需要手动修改
7
+ */
8
+
9
+ import { registerModels, CONFIG_NAMES, type ModelsConfig } from "@lovrabet/sdk";
10
+
11
+ export const RABETBASE_APP_CODE = "app-c4c89304";
12
+
13
+ /**
14
+ * 项目的模型配置
15
+ * 使用数组格式,每个模型包含 datasetCode、tableName、name 和可选的 alias
16
+ *
17
+ * 访问方式:
18
+ * - 标准访问:client.models.dataset_[datasetCode]
19
+ * - 别名访问:client.models.[alias](如果配置了 alias)
20
+ */
21
+ export const RABETBASE_MODELS_CONFIG: ModelsConfig = {
22
+ appCode: RABETBASE_APP_CODE,
23
+ models: [
24
+ {
25
+ datasetCode: "3ff202af07164d0a9c5df7ddd8f83c23",
26
+ tableName: "dataset_f83c23",
27
+ name: "客户访谈记录",
28
+ alias: "datasetF83c23",
29
+ },
30
+ {
31
+ datasetCode: "a60f11c17c5344e7a26d5144212cf366",
32
+ tableName: "iterations",
33
+ name: "迭代信息",
34
+ alias: "iterations",
35
+ },
36
+ {
37
+ datasetCode: "d26ed512e878461ca97d287a47606fd3",
38
+ tableName: "requirements",
39
+ name: "需求",
40
+ alias: "requirements",
41
+ },
42
+ {
43
+ datasetCode: "f17f1ee941c1468e87e6a0ca655ce00e",
44
+ tableName: "requirement_types",
45
+ name: "需求类型",
46
+ alias: "requirementTypes",
47
+ },
48
+ {
49
+ datasetCode: "c6e55d6720b84ffcb21698b0a04ccd23",
50
+ tableName: "projects",
51
+ name: "项目",
52
+ alias: "projects",
53
+ },
54
+ {
55
+ datasetCode: "71494bcba13f4ec7858abe90794183ad",
56
+ tableName: "project_members",
57
+ name: "项目成员",
58
+ alias: "projectMembers",
59
+ },
60
+ ],
61
+ } as const;
62
+
63
+ /**
64
+ * 自动注册配置
65
+ * 配置名称: CONFIG_NAMES.DEFAULT
66
+ */
67
+ registerModels(RABETBASE_MODELS_CONFIG, CONFIG_NAMES.DEFAULT);
68
+
69
+ /**
70
+ * 如果需要支持多项目或多环境,可以注册额外的配置:
71
+ *
72
+ * // 开发环境配置
73
+ * registerModels({
74
+ * appCode: 'app-dev-123',
75
+ * models: [...]
76
+ * }, 'dev');
77
+ *
78
+ * // 其他项目配置
79
+ * registerModels({
80
+ * appCode: 'other-project',
81
+ * models: [...]
82
+ * }, 'project-b');
83
+ */
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Lovrabet SDK 客户端实例
3
+ * Generated by Lovrabet CLI
4
+ * Created: 2026-01-16T10:07:17.967Z
5
+ *
6
+ * 这个文件负责创建和导出统一的客户端实例,供整个应用使用
7
+ * 通过导入 './api' 文件来自动执行配置注册
8
+ */
9
+
10
+ import { createClient, CONFIG_NAMES } from "@lovrabet/sdk";
11
+ import "./api"; // 导入配置文件,执行 registerModels() 注册
12
+
13
+ /**
14
+ * 主要的客户端实例
15
+ * 使用配置名称 'CONFIG_NAMES.DEFAULT' 创建客户端
16
+ */
17
+ export const lovrabetClient = createClient();
18
+
19
+ /**
20
+ * 使用示例:
21
+ *
22
+ * // 在组件中使用
23
+ * import { lovrabetClient } from '@/api/client';
24
+ *
25
+ * // 获取数据列表
26
+ * const data = await lovrabetClient.models.datasetF83c23.getList({
27
+ * currentPage: 1,
28
+ * pageSize: 20
29
+ * });
30
+ *
31
+ * // 获取单条记录
32
+ * const record = await lovrabetClient.models.datasetF83c23.getOne('123');
33
+ *
34
+ * // 创建新记录
35
+ * const newRecord = await lovrabetClient.models.datasetF83c23.create({
36
+ * // 记录数据
37
+ * });
38
+ */
39
+
40
+ /**
41
+ * 其他创建客户端的方式(根据需要选择):
42
+ *
43
+ * 1. 使用默认配置(无参数调用):
44
+ * export const lovrabetClient = createClient();
45
+ *
46
+ * 2. 使用其他已注册的配置:
47
+ * export const devClient = createClient('dev');
48
+ * export const prodClient = createClient('prod');
49
+ *
50
+ * 3. 直接传入配置对象:
51
+ * import { RABETBASE_MODELS_CONFIG } from './api';
52
+ * export const lovrabetClient = createClient(RABETBASE_MODELS_CONFIG);
53
+ *
54
+ * 4. 通过 ClientConfig 指定配置名和其他选项:
55
+ * export const lovrabetClient = createClient({
56
+ * apiConfigName: 'default',
57
+ * token: 'custom-token',
58
+ * env: 'daily'
59
+ * });
60
+ *
61
+ * 5. 多项目支持示例:
62
+ * export const projectAClient = createClient('project-a');
63
+ * export const projectBClient = createClient('project-b');
64
+ */
@@ -0,0 +1,311 @@
1
+ import React, { useState } from "react";
2
+ import { isInIcestark } from "@ice/stark-app";
3
+ import { Outlet, useNavigate, useLocation } from "react-router-dom";
4
+ import {
5
+ Layout,
6
+ Menu,
7
+ Button,
8
+ Breadcrumb,
9
+ Avatar,
10
+ Space,
11
+ Dropdown,
12
+ } from "antd";
13
+ import type { MenuProps } from "antd";
14
+ import {
15
+ HomeOutlined,
16
+ DashboardOutlined,
17
+ ApiOutlined,
18
+ MenuFoldOutlined,
19
+ MenuUnfoldOutlined,
20
+ UserOutlined,
21
+ BarChartOutlined,
22
+ FileTextOutlined,
23
+ AuditOutlined,
24
+ } from "@ant-design/icons";
25
+
26
+ const { Header, Sider, Content } = Layout;
27
+
28
+ // 路由配置,用于生成面包屑
29
+ const routeConfig = [
30
+ { path: "/", title: "首页" },
31
+ { path: "/workbench", title: "工作台" },
32
+ { path: "/dashboard", title: "数据看板" },
33
+ { path: "/sdk-demo", title: "SDK 演示" },
34
+ { path: "/data-screen", title: "数据大屏" },
35
+ { path: "/ceo-audit", title: "CEO 审计" },
36
+ ];
37
+
38
+ const MainLayout: React.FC = () => {
39
+ const navigate = useNavigate();
40
+ const location = useLocation();
41
+
42
+ // 菜单收起/展开状态
43
+ const [collapsed, setCollapsed] = useState(false);
44
+ // 菜单是否完全隐藏
45
+ const [menuHidden, setMenuHidden] = useState(false);
46
+
47
+ const menuItems: MenuProps["items"] = [
48
+ {
49
+ key: "/",
50
+ icon: <HomeOutlined />,
51
+ label: "首页",
52
+ },
53
+ {
54
+ key: "/sdk-demo",
55
+ icon: <ApiOutlined />,
56
+ label: "SDK 演示",
57
+ },
58
+ {
59
+ key: "page-examples",
60
+ icon: <FileTextOutlined />,
61
+ label: "页面案例",
62
+ children: [
63
+ {
64
+ key: "/workbench",
65
+ icon: <DashboardOutlined />,
66
+ label: "工作台",
67
+ },
68
+ {
69
+ key: "/dashboard",
70
+ icon: <DashboardOutlined />,
71
+ label: "数据看板",
72
+ },
73
+ {
74
+ key: "/data-screen",
75
+ icon: <BarChartOutlined />,
76
+ label: "数据大屏",
77
+ },
78
+ ],
79
+ },
80
+ ];
81
+
82
+ const handleMenuClick = ({ key }: { key: string }) => {
83
+ // 如果是外部链接(以 http:// 或 https:// 开头),在新标签页打开
84
+ if (key.startsWith("http://") || key.startsWith("https://")) {
85
+ window.open(key, "_blank", "noopener,noreferrer");
86
+ } else {
87
+ navigate(key);
88
+ }
89
+ };
90
+
91
+ const toggleCollapsed = () => {
92
+ setCollapsed(!collapsed);
93
+ };
94
+
95
+ const toggleMenuHidden = () => {
96
+ setMenuHidden(!menuHidden);
97
+ // 如果隐藏菜单,同时收起菜单
98
+ if (!menuHidden) {
99
+ setCollapsed(true);
100
+ }
101
+ };
102
+
103
+ // 生成面包屑
104
+ const getBreadcrumbItems = () => {
105
+ const items: any[] = [{ title: "首页" }];
106
+ const currentRoute = routeConfig.find((r) => r.path === location.pathname);
107
+ if (currentRoute && currentRoute.path !== "/") {
108
+ items.push({ title: currentRoute.title });
109
+ }
110
+ return items;
111
+ };
112
+
113
+ // 用户菜单
114
+ const userMenuItems: MenuProps["items"] = [
115
+ {
116
+ key: "profile",
117
+ label: "个人中心",
118
+ icon: <UserOutlined />,
119
+ },
120
+ {
121
+ key: "settings",
122
+ label: "系统设置",
123
+ },
124
+ {
125
+ type: "divider",
126
+ },
127
+ {
128
+ key: "logout",
129
+ label: "退出登录",
130
+ danger: true,
131
+ },
132
+ ];
133
+
134
+ // 可选:根据isInIcestark()判断当前运行环境,被嵌入时,不渲染layout布局
135
+ if (isInIcestark()) {
136
+ return <Outlet />;
137
+ }
138
+
139
+ return (
140
+ <Layout style={{ minHeight: "100vh" }}>
141
+ {!menuHidden && (
142
+ <Sider
143
+ trigger={null}
144
+ collapsible
145
+ collapsed={collapsed}
146
+ width={220}
147
+ style={{ background: "#fff" }}
148
+ >
149
+ {/* 系统标题 */}
150
+ <div
151
+ style={{
152
+ height: 64,
153
+ padding: collapsed ? "16px 8px" : "16px 20px",
154
+ display: "flex",
155
+ alignItems: "center",
156
+ justifyContent: collapsed ? "center" : "flex-start",
157
+ background: "#fff",
158
+ borderBottom: "1px solid #f0f0f0",
159
+ }}
160
+ >
161
+ {!collapsed ? (
162
+ <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
163
+ <img
164
+ src="/logo.svg"
165
+ alt="Logo"
166
+ style={{ height: 28, width: 28 }}
167
+ />
168
+ <span
169
+ style={{
170
+ fontSize: 16,
171
+ fontWeight: 600,
172
+ }}
173
+ >
174
+ Lovrabet System
175
+ </span>
176
+ </div>
177
+ ) : (
178
+ <img
179
+ src="/logo.svg"
180
+ alt="Logo"
181
+ style={{ height: 28, width: 28 }}
182
+ />
183
+ )}
184
+ </div>
185
+ <Menu
186
+ mode="inline"
187
+ selectedKeys={[location.pathname]}
188
+ items={menuItems}
189
+ onClick={handleMenuClick}
190
+ style={{
191
+ height: "calc(100vh - 64px)",
192
+ borderRight: 0,
193
+ }}
194
+ className="custom-menu"
195
+ />
196
+ </Sider>
197
+ )}
198
+ <Layout>
199
+ <Header
200
+ style={{
201
+ padding: "0 24px",
202
+ display: "flex",
203
+ alignItems: "center",
204
+ justifyContent: "space-between",
205
+ boxShadow: "0 2px 8px 0 rgba(29,35,41,.05)",
206
+ height: 64,
207
+ background: "#fff",
208
+ borderBottom: "1px solid #f0f0f0",
209
+ }}
210
+ >
211
+ <div style={{ display: "flex", alignItems: "center", gap: 16 }}>
212
+ <Button
213
+ type="text"
214
+ icon={
215
+ menuHidden ? (
216
+ <MenuUnfoldOutlined />
217
+ ) : collapsed ? (
218
+ <MenuUnfoldOutlined />
219
+ ) : (
220
+ <MenuFoldOutlined />
221
+ )
222
+ }
223
+ onClick={menuHidden ? toggleMenuHidden : toggleCollapsed}
224
+ style={{
225
+ fontSize: 16,
226
+ width: 40,
227
+ height: 40,
228
+ display: "flex",
229
+ alignItems: "center",
230
+ justifyContent: "center",
231
+ }}
232
+ />
233
+ {menuHidden && (
234
+ <Button
235
+ type="text"
236
+ icon={<MenuUnfoldOutlined />}
237
+ onClick={toggleMenuHidden}
238
+ style={{
239
+ fontSize: 14,
240
+ height: 32,
241
+ }}
242
+ >
243
+ 显示菜单
244
+ </Button>
245
+ )}
246
+ {/* 面包屑导航 */}
247
+ <Breadcrumb
248
+ items={getBreadcrumbItems()}
249
+ style={{
250
+ marginLeft: menuHidden ? 0 : 16,
251
+ fontSize: 14,
252
+ }}
253
+ itemRender={(route, params, routes, paths) => {
254
+ const isLast = routes.indexOf(route) === routes.length - 1;
255
+ return (
256
+ <span
257
+ style={{
258
+ color: isLast ? "#262626" : "#595959",
259
+ fontWeight: isLast ? 500 : 400,
260
+ }}
261
+ >
262
+ {route.title}
263
+ </span>
264
+ );
265
+ }}
266
+ />
267
+ </div>
268
+ <div style={{ display: "flex", alignItems: "center", gap: 16 }}>
269
+ {/* 用户信息 */}
270
+ <Dropdown menu={{ items: userMenuItems }} placement="bottomRight">
271
+ <Space
272
+ style={{
273
+ cursor: "pointer",
274
+ padding: "4px 8px",
275
+ borderRadius: 4,
276
+ transition: "background 0.3s",
277
+ }}
278
+ onMouseEnter={(e) => {
279
+ e.currentTarget.style.background = "rgba(0,0,0,0.06)";
280
+ }}
281
+ onMouseLeave={(e) => {
282
+ e.currentTarget.style.background = "transparent";
283
+ }}
284
+ >
285
+ <Avatar
286
+ size="small"
287
+ icon={<UserOutlined />}
288
+ style={{ background: "#1890ff" }}
289
+ />
290
+ <span style={{ fontSize: 14 }}>管理员</span>
291
+ </Space>
292
+ </Dropdown>
293
+ </div>
294
+ </Header>
295
+ <Content
296
+ style={{
297
+ margin: "16px",
298
+ padding: 24,
299
+ minHeight: 280,
300
+ background: "#fff",
301
+ borderRadius: 8,
302
+ }}
303
+ >
304
+ <Outlet />
305
+ </Content>
306
+ </Layout>
307
+ </Layout>
308
+ );
309
+ };
310
+
311
+ export default MainLayout;
@@ -0,0 +1,48 @@
1
+ import React from "react";
2
+ import { createRoot } from "react-dom/client";
3
+ import { isInIcestark } from "@ice/stark-app";
4
+ import { ConfigProvider } from "antd";
5
+ import zhCN from "antd/locale/zh_CN";
6
+ import App from "./router";
7
+ import "./style.css";
8
+
9
+ // 可选:根据 isInIcestark() 判断当前的运行环境,可同时兼容独立使用和嵌入使用
10
+ if (!isInIcestark()) {
11
+ const container = document.getElementById("root");
12
+ if (container) {
13
+ const root = createRoot(container);
14
+ root.render(
15
+ <ConfigProvider locale={zhCN}>
16
+ <App />
17
+ </ConfigProvider>,
18
+ );
19
+ }
20
+ }
21
+
22
+ // 关键:暴露 mount 供主应用加载时调用
23
+ export function mount({
24
+ container,
25
+ customProps,
26
+ }: {
27
+ container: HTMLElement;
28
+ customProps: object;
29
+ }) {
30
+ const root = createRoot(container);
31
+ root.render(
32
+ <React.StrictMode>
33
+ <ConfigProvider locale={zhCN}>
34
+ <App {...customProps} />
35
+ </ConfigProvider>
36
+ </React.StrictMode>,
37
+ );
38
+ return root;
39
+ }
40
+
41
+ // 关键:暴露 unmount 供主应用卸载时调用
42
+ export function unmount({ container }: { container: HTMLElement }) {
43
+ // React 18 中不再需要手动卸载,但为了兼容性保留
44
+ const root = (container as any)._reactRoot;
45
+ if (root) {
46
+ root.unmount();
47
+ }
48
+ }