@lovrabet/cli 1.1.21 → 1.1.22

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 (65) hide show
  1. package/lib/add-page/input-page-router.js +1 -1
  2. package/lib/add-page/main.js +1 -1
  3. package/lib/add-page/select-page-template.js +1 -1
  4. package/lib/api/api-doc-ui.js +1 -1
  5. package/lib/api/api-doc.js +1 -1
  6. package/lib/api/api-pull-ui.js +1 -1
  7. package/lib/api/fetch-model-list.js +1 -1
  8. package/lib/api/generate-api-file.js +1 -1
  9. package/lib/api/main.js +1 -1
  10. package/lib/api/pull-silent.js +1 -1
  11. package/lib/app-menu/app-menu-sync-ui.js +1 -1
  12. package/lib/app-menu/create-menu.js +1 -1
  13. package/lib/app-menu/get-local-pages.js +1 -1
  14. package/lib/app-menu/get-online-menu-list.js +1 -1
  15. package/lib/app-menu/valid-url.js +1 -1
  16. package/lib/auth/auth-server-ui.js +1 -1
  17. package/lib/auth/auth-server.js +1 -1
  18. package/lib/auth/constant.js +1 -1
  19. package/lib/auth/get-cookie.js +1 -1
  20. package/lib/auth/is-session-valid.js +1 -1
  21. package/lib/auth/logout.js +1 -1
  22. package/lib/cli.js +1 -1
  23. package/lib/cmd/build-watch.js +1 -1
  24. package/lib/cmd/build.js +1 -1
  25. package/lib/cmd/logs.js +1 -1
  26. package/lib/cmd/preview.js +1 -1
  27. package/lib/cmd/start.js +1 -1
  28. package/lib/config/config-help.js +1 -1
  29. package/lib/config/main.js +1 -1
  30. package/lib/constant/domain.js +1 -1
  31. package/lib/constant/env.js +1 -1
  32. package/lib/create-app/enhanced-guided-create.js +1 -1
  33. package/lib/create-app/format-elapsed.js +1 -1
  34. package/lib/create-app/main.js +1 -1
  35. package/lib/create-app/task-finished.js +1 -1
  36. package/lib/create-app/task-loading.js +1 -1
  37. package/lib/create-app/task-running.js +1 -1
  38. package/lib/create-app/task-time.js +1 -1
  39. package/lib/create-app/use-copy-project-template.js +1 -1
  40. package/lib/create-app/use-format-code.js +1 -1
  41. package/lib/create-app/use-install-dependencies.js +1 -1
  42. package/lib/help.js +1 -1
  43. package/lib/init/main.js +1 -1
  44. package/lib/mcp/cursor.js +1 -1
  45. package/lib/mcp/main.js +1 -1
  46. package/lib/utils/config.js +1 -1
  47. package/lib/utils/copy-directory.js +1 -1
  48. package/lib/utils/http-client.js +1 -1
  49. package/lib/utils/logger.js +1 -1
  50. package/lib/utils/router-updater.js +1 -1
  51. package/lib/utils/sleep.js +1 -1
  52. package/lib/utils/template-replacer.js +1 -1
  53. package/package.json +1 -1
  54. package/templates/projects/sub-app-react-demo/CHANGELOG.md +16 -0
  55. package/templates/projects/sub-app-react-demo/README.md +163 -54
  56. package/templates/projects/sub-app-react-demo/package-lock.json +1347 -149
  57. package/templates/projects/sub-app-react-demo/package.json +2 -2
  58. package/templates/projects/sub-app-react-demo/src/layouts/MainLayout.tsx +286 -55
  59. package/templates/projects/sub-app-react-demo/src/pages/data-screen/index.tsx +526 -0
  60. package/templates/projects/sub-app-react-demo/src/pages/index.tsx +942 -87
  61. package/templates/projects/sub-app-react-demo/src/pages/intro/index.tsx +560 -0
  62. package/templates/projects/sub-app-react-demo/src/pages/sdk-demo/index.tsx +113 -118
  63. package/templates/projects/sub-app-react-demo/src/pages/workbench/index.tsx +469 -0
  64. package/templates/projects/sub-app-react-demo/src/style.css +39 -0
  65. package/templates/projects/sub-app-react-demo/bun.lock +0 -600
@@ -0,0 +1,469 @@
1
+ import React, { useState } from "react";
2
+ import { useNavigate } from "react-router-dom";
3
+ import {
4
+ Card,
5
+ Row,
6
+ Col,
7
+ Statistic,
8
+ Typography,
9
+ Space,
10
+ Button,
11
+ List,
12
+ Avatar,
13
+ Tag,
14
+ Progress,
15
+ Timeline,
16
+ Empty,
17
+ } from "antd";
18
+ import {
19
+ RocketOutlined,
20
+ DashboardOutlined,
21
+ ApiOutlined,
22
+ BarChartOutlined,
23
+ FileTextOutlined,
24
+ SettingOutlined,
25
+ UserOutlined,
26
+ ShoppingOutlined,
27
+ DollarOutlined,
28
+ TrophyOutlined,
29
+ ClockCircleOutlined,
30
+ CheckCircleOutlined,
31
+ ExclamationCircleOutlined,
32
+ ArrowRightOutlined,
33
+ } from "@ant-design/icons";
34
+
35
+ const { Title, Text, Paragraph } = Typography;
36
+
37
+ // Mock 数据
38
+ const mockData = {
39
+ // 统计数据
40
+ statistics: [
41
+ {
42
+ title: "今日访问",
43
+ value: 1256,
44
+ prefix: <UserOutlined />,
45
+ color: "#1890ff",
46
+ trend: "+12.5%",
47
+ },
48
+ {
49
+ title: "待处理订单",
50
+ value: 89,
51
+ prefix: <ShoppingOutlined />,
52
+ color: "#52c41a",
53
+ trend: "+8.3%",
54
+ },
55
+ {
56
+ title: "本月收入",
57
+ value: 896523,
58
+ prefix: <DollarOutlined />,
59
+ color: "#fa8c16",
60
+ suffix: "元",
61
+ trend: "+15.6%",
62
+ },
63
+ {
64
+ title: "完成率",
65
+ value: 89.5,
66
+ prefix: <TrophyOutlined />,
67
+ color: "#eb2f96",
68
+ suffix: "%",
69
+ trend: "+3.2%",
70
+ },
71
+ ],
72
+
73
+ // 快捷操作
74
+ quickActions: [
75
+ {
76
+ key: "/sdk-demo",
77
+ title: "SDK 演示",
78
+ icon: <ApiOutlined />,
79
+ description: "查看 SDK 使用示例",
80
+ color: "#1890ff",
81
+ },
82
+ {
83
+ key: "/dashboard",
84
+ title: "数据看板",
85
+ icon: <DashboardOutlined />,
86
+ description: "查看业务数据统计",
87
+ color: "#52c41a",
88
+ },
89
+ {
90
+ key: "/data-screen",
91
+ title: "数据大屏",
92
+ icon: <BarChartOutlined />,
93
+ description: "可视化数据展示",
94
+ color: "#fa8c16",
95
+ },
96
+ {
97
+ key: "https://open.lovrabet.com",
98
+ title: "查看文档",
99
+ icon: <FileTextOutlined />,
100
+ description: "访问完整文档",
101
+ color: "#722ed1",
102
+ external: true,
103
+ },
104
+ ],
105
+
106
+ // 最近访问
107
+ recentAccess: [
108
+ { name: "SDK 演示", path: "/sdk-demo", time: "2 小时前" },
109
+ { name: "数据看板", path: "/dashboard", time: "5 小时前" },
110
+ { name: "数据大屏", path: "/data-screen", time: "1 天前" },
111
+ ],
112
+
113
+ // 待办事项
114
+ todos: [
115
+ {
116
+ id: 1,
117
+ title: "完成 SDK 集成文档",
118
+ priority: "high",
119
+ status: "pending",
120
+ dueDate: "2025-01-15",
121
+ },
122
+ {
123
+ id: 2,
124
+ title: "优化数据大屏性能",
125
+ priority: "medium",
126
+ status: "in-progress",
127
+ dueDate: "2025-01-20",
128
+ },
129
+ {
130
+ id: 3,
131
+ title: "更新 API 文档",
132
+ priority: "low",
133
+ status: "pending",
134
+ dueDate: "2025-01-25",
135
+ },
136
+ ],
137
+
138
+ // 系统公告
139
+ announcements: [
140
+ {
141
+ id: 1,
142
+ title: "SDK v1.1.22 版本发布",
143
+ content: "新增 filter 接口支持,支持复杂条件查询",
144
+ time: "2025-01-10",
145
+ type: "update",
146
+ },
147
+ {
148
+ id: 2,
149
+ title: "CLI v1.1.15 版本更新",
150
+ content: "优化菜单同步功能,支持中文菜单名",
151
+ time: "2025-01-08",
152
+ type: "feature",
153
+ },
154
+ {
155
+ id: 3,
156
+ title: "文档中心更新",
157
+ content: "新增 API 使用指南和最佳实践",
158
+ time: "2025-01-05",
159
+ type: "info",
160
+ },
161
+ ],
162
+ };
163
+
164
+ const Workbench: React.FC = () => {
165
+ const navigate = useNavigate();
166
+ const [todos] = useState(mockData.todos);
167
+
168
+ const handleQuickAction = (action: any) => {
169
+ if (action.external) {
170
+ window.open(action.key, "_blank");
171
+ } else {
172
+ navigate(action.key);
173
+ }
174
+ };
175
+
176
+ const getPriorityColor = (priority: string) => {
177
+ const colors: Record<string, string> = {
178
+ high: "red",
179
+ medium: "orange",
180
+ low: "blue",
181
+ };
182
+ return colors[priority] || "default";
183
+ };
184
+
185
+ const getStatusIcon = (status: string) => {
186
+ if (status === "completed") {
187
+ return <CheckCircleOutlined style={{ color: "#52c41a" }} />;
188
+ }
189
+ if (status === "in-progress") {
190
+ return <ClockCircleOutlined style={{ color: "#1890ff" }} />;
191
+ }
192
+ return <ExclamationCircleOutlined style={{ color: "#fa8c16" }} />;
193
+ };
194
+
195
+ const getAnnouncementIcon = (type: string) => {
196
+ const icons: Record<string, any> = {
197
+ update: <RocketOutlined style={{ color: "#1890ff" }} />,
198
+ feature: <TrophyOutlined style={{ color: "#52c41a" }} />,
199
+ info: <FileTextOutlined style={{ color: "#fa8c16" }} />,
200
+ };
201
+ return icons[type] || <FileTextOutlined />;
202
+ };
203
+
204
+ return (
205
+ <div>
206
+ {/* 欢迎区域 */}
207
+ <Card
208
+ style={{
209
+ background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
210
+ border: "none",
211
+ marginBottom: 24,
212
+ }}
213
+ >
214
+ <Row align="middle" gutter={24}>
215
+ <Col xs={24} md={16}>
216
+ <Title level={2} style={{ color: "#fff", margin: 0 }}>
217
+ <RocketOutlined /> 工作台
218
+ </Title>
219
+ <Paragraph style={{ color: "#fff", fontSize: 16, marginTop: 8, marginBottom: 0 }}>
220
+ 欢迎回来!这里是您的开发工作台,可以快速访问常用功能和查看系统状态。
221
+ </Paragraph>
222
+ </Col>
223
+ <Col xs={24} md={8} style={{ textAlign: "right" }}>
224
+ <Space>
225
+ <Button
226
+ type="primary"
227
+ size="large"
228
+ icon={<FileTextOutlined />}
229
+ href="https://open.lovrabet.com"
230
+ target="_blank"
231
+ style={{
232
+ background: "#fff",
233
+ color: "#667eea",
234
+ border: "none",
235
+ }}
236
+ >
237
+ 查看文档
238
+ </Button>
239
+ </Space>
240
+ </Col>
241
+ </Row>
242
+ </Card>
243
+
244
+ {/* 统计数据 */}
245
+ <Row gutter={[16, 16]} style={{ marginBottom: 24 }}>
246
+ {mockData.statistics.map((stat, index) => (
247
+ <Col xs={24} sm={12} lg={6} key={index}>
248
+ <Card>
249
+ <Statistic
250
+ title={stat.title}
251
+ value={stat.value}
252
+ prefix={
253
+ <span style={{ color: stat.color, marginRight: 8 }}>
254
+ {stat.prefix}
255
+ </span>
256
+ }
257
+ suffix={stat.suffix}
258
+ valueStyle={{ color: stat.color, fontSize: 24, fontWeight: "bold" }}
259
+ />
260
+ <div style={{ marginTop: 8, fontSize: 12, color: "#52c41a" }}>
261
+ {stat.trend} 较昨日
262
+ </div>
263
+ </Card>
264
+ </Col>
265
+ ))}
266
+ </Row>
267
+
268
+ <Row gutter={[16, 16]}>
269
+ {/* 快捷操作 */}
270
+ <Col xs={24} lg={12}>
271
+ <Card
272
+ title={
273
+ <Space>
274
+ <RocketOutlined style={{ color: "#1890ff" }} />
275
+ <span>快捷操作</span>
276
+ </Space>
277
+ }
278
+ style={{ height: "100%" }}
279
+ >
280
+ <Row gutter={[12, 12]}>
281
+ {mockData.quickActions.map((action) => (
282
+ <Col xs={12} sm={12} key={action.key}>
283
+ <Card
284
+ hoverable
285
+ onClick={() => handleQuickAction(action)}
286
+ style={{
287
+ textAlign: "center",
288
+ cursor: "pointer",
289
+ border: `1px solid ${action.color}20`,
290
+ }}
291
+ bodyStyle={{ padding: 16 }}
292
+ >
293
+ <div
294
+ style={{
295
+ fontSize: 32,
296
+ color: action.color,
297
+ marginBottom: 8,
298
+ }}
299
+ >
300
+ {action.icon}
301
+ </div>
302
+ <div style={{ fontWeight: "bold", marginBottom: 4 }}>
303
+ {action.title}
304
+ </div>
305
+ <div style={{ fontSize: 12, color: "#666" }}>
306
+ {action.description}
307
+ </div>
308
+ </Card>
309
+ </Col>
310
+ ))}
311
+ </Row>
312
+ </Card>
313
+ </Col>
314
+
315
+ {/* 最近访问 */}
316
+ <Col xs={24} lg={12}>
317
+ <Card
318
+ title={
319
+ <Space>
320
+ <ClockCircleOutlined style={{ color: "#1890ff" }} />
321
+ <span>最近访问</span>
322
+ </Space>
323
+ }
324
+ style={{ height: "100%" }}
325
+ >
326
+ {mockData.recentAccess.length > 0 ? (
327
+ <List
328
+ dataSource={mockData.recentAccess}
329
+ renderItem={(item) => (
330
+ <List.Item
331
+ style={{ cursor: "pointer", padding: "12px 0" }}
332
+ onClick={() => navigate(item.path)}
333
+ actions={[
334
+ <Button
335
+ type="link"
336
+ icon={<ArrowRightOutlined />}
337
+ onClick={(e) => {
338
+ e.stopPropagation();
339
+ navigate(item.path);
340
+ }}
341
+ />,
342
+ ]}
343
+ >
344
+ <List.Item.Meta
345
+ avatar={
346
+ <Avatar
347
+ style={{
348
+ background: "#1890ff",
349
+ }}
350
+ icon={<FileTextOutlined />}
351
+ />
352
+ }
353
+ title={item.name}
354
+ description={
355
+ <Text type="secondary" style={{ fontSize: 12 }}>
356
+ {item.time}
357
+ </Text>
358
+ }
359
+ />
360
+ </List.Item>
361
+ )}
362
+ />
363
+ ) : (
364
+ <Empty description="暂无访问记录" />
365
+ )}
366
+ </Card>
367
+ </Col>
368
+
369
+ {/* 待办事项 */}
370
+ <Col xs={24} lg={12}>
371
+ <Card
372
+ title={
373
+ <Space>
374
+ <ExclamationCircleOutlined style={{ color: "#fa8c16" }} />
375
+ <span>待办事项</span>
376
+ <Tag color="red">{todos.filter((t) => t.status === "pending").length}</Tag>
377
+ </Space>
378
+ }
379
+ style={{ height: "100%" }}
380
+ >
381
+ {todos.length > 0 ? (
382
+ <List
383
+ dataSource={todos}
384
+ renderItem={(item) => (
385
+ <List.Item>
386
+ <List.Item.Meta
387
+ avatar={getStatusIcon(item.status)}
388
+ title={
389
+ <Space>
390
+ <span>{item.title}</span>
391
+ <Tag color={getPriorityColor(item.priority)}>
392
+ {item.priority === "high"
393
+ ? "高"
394
+ : item.priority === "medium"
395
+ ? "中"
396
+ : "低"}
397
+ </Tag>
398
+ </Space>
399
+ }
400
+ description={
401
+ <div>
402
+ <Text type="secondary" style={{ fontSize: 12 }}>
403
+ 截止日期:{item.dueDate}
404
+ </Text>
405
+ <div style={{ marginTop: 8 }}>
406
+ <Progress
407
+ percent={
408
+ item.status === "completed"
409
+ ? 100
410
+ : item.status === "in-progress"
411
+ ? 50
412
+ : 0
413
+ }
414
+ size="small"
415
+ status={
416
+ item.status === "completed" ? "success" : "active"
417
+ }
418
+ />
419
+ </div>
420
+ </div>
421
+ }
422
+ />
423
+ </List.Item>
424
+ )}
425
+ />
426
+ ) : (
427
+ <Empty description="暂无待办事项" />
428
+ )}
429
+ </Card>
430
+ </Col>
431
+
432
+ {/* 系统公告 */}
433
+ <Col xs={24} lg={12}>
434
+ <Card
435
+ title={
436
+ <Space>
437
+ <FileTextOutlined style={{ color: "#1890ff" }} />
438
+ <span>系统公告</span>
439
+ </Space>
440
+ }
441
+ style={{ height: "100%" }}
442
+ >
443
+ <Timeline
444
+ items={mockData.announcements.map((announcement) => ({
445
+ dot: getAnnouncementIcon(announcement.type),
446
+ children: (
447
+ <div>
448
+ <div style={{ fontWeight: "bold", marginBottom: 4 }}>
449
+ {announcement.title}
450
+ </div>
451
+ <div style={{ color: "#666", fontSize: 13, marginBottom: 4 }}>
452
+ {announcement.content}
453
+ </div>
454
+ <Text type="secondary" style={{ fontSize: 12 }}>
455
+ {announcement.time}
456
+ </Text>
457
+ </div>
458
+ ),
459
+ }))}
460
+ />
461
+ </Card>
462
+ </Col>
463
+ </Row>
464
+ </div>
465
+ );
466
+ };
467
+
468
+ export default Workbench;
469
+
@@ -37,6 +37,45 @@ body {
37
37
  background: #a8a8a8;
38
38
  }
39
39
 
40
+ /* 自定义菜单样式 - B端专业风格 */
41
+ .custom-menu.ant-menu {
42
+ background: #fafafa !important;
43
+ }
44
+
45
+ .custom-menu .ant-menu-item {
46
+ margin: 4px 8px !important;
47
+ border-radius: 4px !important;
48
+ height: 40px !important;
49
+ line-height: 40px !important;
50
+ color: #262626 !important;
51
+ }
52
+
53
+ .custom-menu .ant-menu-item-icon {
54
+ color: #595959 !important;
55
+ }
56
+
57
+ .custom-menu .ant-menu-item:hover {
58
+ background: #e6f7ff !important;
59
+ color: #1890ff !important;
60
+ }
61
+
62
+ .custom-menu .ant-menu-item:hover .ant-menu-item-icon {
63
+ color: #1890ff !important;
64
+ }
65
+
66
+ .custom-menu .ant-menu-item-selected {
67
+ background: #1890ff !important;
68
+ color: #fff !important;
69
+ }
70
+
71
+ .custom-menu .ant-menu-item-selected .ant-menu-item-icon {
72
+ color: #fff !important;
73
+ }
74
+
75
+ .custom-menu .ant-menu-item-selected::after {
76
+ display: none !important;
77
+ }
78
+
40
79
  /* 响应式设计 */
41
80
  @media (max-width: 768px) {
42
81
  .ant-layout-sider {