@chatbi-v/cli 1.0.7 → 1.0.9

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 (117) hide show
  1. package/dist/app/.env +8 -0
  2. package/dist/app/.env.hbs +8 -0
  3. package/dist/app/README.md.hbs +16 -0
  4. package/dist/app/chatbi.config.ts.hbs +60 -0
  5. package/{templates/default/apps/main → dist/app}/index.html.hbs +3 -4
  6. package/dist/app/package.json.hbs +34 -0
  7. package/dist/app/src/App.tsx.hbs +92 -0
  8. package/dist/app/src/components/GlobalErrorBoundary.tsx.hbs +69 -0
  9. package/dist/app/src/components/GlobalSettingsModal.tsx.hbs +35 -0
  10. package/dist/app/src/components/LayoutSkeletons.tsx.hbs +79 -0
  11. package/dist/app/src/components/index.ts.hbs +2 -0
  12. package/dist/app/src/custom-antd.less.hbs +7 -0
  13. package/dist/app/src/features/settings/ConfigRenderStrategy.tsx.hbs +119 -0
  14. package/dist/app/src/features/settings/ExtensionSettings.tsx.hbs +52 -0
  15. package/dist/app/src/features/settings/PluginList.tsx.hbs +115 -0
  16. package/dist/app/src/features/settings/PluginSettings.tsx.hbs +123 -0
  17. package/dist/app/src/features/settings/SchemaSettingsRenderer.tsx.hbs +56 -0
  18. package/dist/app/src/hooks/useAppRoutes.ts.hbs +39 -0
  19. package/dist/app/src/hooks/usePluginLoader.ts.hbs +22 -0
  20. package/dist/app/src/hooks/usePluginSettings.ts.hbs +29 -0
  21. package/dist/app/src/hooks/useThemeSync.ts.hbs +108 -0
  22. package/dist/app/src/index.css.hbs +45 -0
  23. package/dist/app/src/layouts/BackgroundEffects.tsx.hbs +10 -0
  24. package/dist/app/src/layouts/MainContent.tsx.hbs +58 -0
  25. package/dist/app/src/layouts/SidebarNav.tsx.hbs +182 -0
  26. package/dist/app/src/main.tsx.hbs +43 -0
  27. package/dist/app/src/providers/AppProviders.tsx.hbs +36 -0
  28. package/dist/app/src/services/api/index.ts.hbs +37 -0
  29. package/dist/app/src/services/api/modules/auth.ts.hbs +18 -0
  30. package/dist/app/src/services/config-service.ts.hbs +48 -0
  31. package/dist/app/src/stores/storage-adapter.ts.hbs +29 -0
  32. package/dist/app/src/stores/useSessionStore.ts.hbs +22 -0
  33. package/dist/app/src/stores/useUIStore.ts.hbs +64 -0
  34. package/dist/app/tailwind.config.cjs.hbs +14 -0
  35. package/dist/app/tsconfig.json.hbs +26 -0
  36. package/dist/app/vite.config.ts.hbs +89 -0
  37. package/dist/index.js +5662 -4194
  38. package/{templates/default → dist/monorepo}/package.json.hbs +5 -0
  39. package/dist/monorepo/pnpm-workspace.yaml.hbs +10 -0
  40. package/dist/{default → monorepo}/tsconfig.json.hbs +3 -1
  41. package/{templates/default/plugins/demo-plugin → dist/plugin}/package.json.hbs +9 -3
  42. package/dist/plugin/src/index.tsx.hbs +90 -0
  43. package/dist/plugin/tsconfig.json.hbs +14 -0
  44. package/package.json +18 -6
  45. package/templates/app/.env.hbs +8 -0
  46. package/templates/app/README.md.hbs +16 -0
  47. package/templates/app/chatbi.config.ts.hbs +60 -0
  48. package/{dist/default/apps/main → templates/app}/index.html.hbs +3 -4
  49. package/templates/app/package.json.hbs +34 -0
  50. package/templates/app/src/App.tsx.hbs +92 -0
  51. package/templates/app/src/components/GlobalErrorBoundary.tsx.hbs +69 -0
  52. package/templates/app/src/components/GlobalSettingsModal.tsx.hbs +35 -0
  53. package/templates/app/src/components/LayoutSkeletons.tsx.hbs +79 -0
  54. package/templates/app/src/components/index.ts.hbs +2 -0
  55. package/templates/app/src/custom-antd.less.hbs +7 -0
  56. package/templates/app/src/features/settings/ConfigRenderStrategy.tsx.hbs +119 -0
  57. package/templates/app/src/features/settings/ExtensionSettings.tsx.hbs +52 -0
  58. package/templates/app/src/features/settings/PluginList.tsx.hbs +115 -0
  59. package/templates/app/src/features/settings/PluginSettings.tsx.hbs +123 -0
  60. package/templates/app/src/features/settings/SchemaSettingsRenderer.tsx.hbs +56 -0
  61. package/templates/app/src/hooks/useAppRoutes.ts.hbs +39 -0
  62. package/templates/app/src/hooks/usePluginLoader.ts.hbs +22 -0
  63. package/templates/app/src/hooks/usePluginSettings.ts.hbs +29 -0
  64. package/templates/app/src/hooks/useThemeSync.ts.hbs +108 -0
  65. package/templates/app/src/index.css.hbs +45 -0
  66. package/templates/app/src/layouts/BackgroundEffects.tsx.hbs +10 -0
  67. package/templates/app/src/layouts/MainContent.tsx.hbs +58 -0
  68. package/templates/app/src/layouts/SidebarNav.tsx.hbs +182 -0
  69. package/templates/app/src/main.tsx.hbs +43 -0
  70. package/templates/app/src/providers/AppProviders.tsx.hbs +36 -0
  71. package/templates/app/src/services/api/index.ts.hbs +37 -0
  72. package/templates/app/src/services/api/modules/auth.ts.hbs +18 -0
  73. package/templates/app/src/services/config-service.ts.hbs +48 -0
  74. package/templates/app/src/stores/storage-adapter.ts.hbs +29 -0
  75. package/templates/app/src/stores/useSessionStore.ts.hbs +22 -0
  76. package/templates/app/src/stores/useUIStore.ts.hbs +64 -0
  77. package/templates/app/tailwind.config.cjs.hbs +14 -0
  78. package/templates/app/tsconfig.json.hbs +26 -0
  79. package/templates/app/vite.config.ts.hbs +89 -0
  80. package/templates/monorepo/.gitignore.hbs +3 -0
  81. package/{dist/default → templates/monorepo}/package.json.hbs +5 -0
  82. package/templates/monorepo/pnpm-workspace.yaml.hbs +10 -0
  83. package/templates/{default → monorepo}/tsconfig.json.hbs +3 -1
  84. package/{dist/default/plugins/demo-plugin → templates/plugin}/package.json.hbs +9 -3
  85. package/templates/plugin/src/index.tsx.hbs +90 -0
  86. package/templates/plugin/tsconfig.json.hbs +14 -0
  87. package/dist/default/apps/main/package.json.hbs +0 -20
  88. package/dist/default/apps/main/src/App.tsx.hbs +0 -162
  89. package/dist/default/apps/main/src/components/NavIcon.tsx.hbs +0 -41
  90. package/dist/default/apps/main/src/hooks/usePluginLoader.ts.hbs +0 -25
  91. package/dist/default/apps/main/src/index.css.hbs +0 -8
  92. package/dist/default/apps/main/src/main.tsx.hbs +0 -13
  93. package/dist/default/apps/main/src/pages/Guide.tsx.hbs +0 -133
  94. package/dist/default/apps/main/tailwind.config.cjs.hbs +0 -17
  95. package/dist/default/apps/main/tsconfig.json.hbs +0 -10
  96. package/dist/default/apps/main/vite.config.ts.hbs +0 -16
  97. package/dist/default/plugins/demo-plugin/src/index.tsx.hbs +0 -44
  98. package/dist/default/plugins/demo-plugin/tsconfig.json.hbs +0 -10
  99. package/dist/default/pnpm-workspace.yaml.hbs +0 -3
  100. package/templates/default/apps/main/package.json.hbs +0 -20
  101. package/templates/default/apps/main/src/App.tsx.hbs +0 -162
  102. package/templates/default/apps/main/src/components/NavIcon.tsx.hbs +0 -41
  103. package/templates/default/apps/main/src/hooks/usePluginLoader.ts.hbs +0 -25
  104. package/templates/default/apps/main/src/index.css.hbs +0 -8
  105. package/templates/default/apps/main/src/main.tsx.hbs +0 -13
  106. package/templates/default/apps/main/src/pages/Guide.tsx.hbs +0 -133
  107. package/templates/default/apps/main/tailwind.config.cjs.hbs +0 -17
  108. package/templates/default/apps/main/tsconfig.json.hbs +0 -10
  109. package/templates/default/apps/main/vite.config.ts.hbs +0 -16
  110. package/templates/default/plugins/demo-plugin/src/index.tsx.hbs +0 -44
  111. package/templates/default/plugins/demo-plugin/tsconfig.json.hbs +0 -10
  112. package/templates/default/pnpm-workspace.yaml.hbs +0 -3
  113. /package/dist/{default/apps/main → app}/postcss.config.cjs.hbs +0 -0
  114. /package/{templates/default → dist/monorepo}/.gitignore.hbs +0 -0
  115. /package/dist/{default → monorepo}/README.md.hbs +0 -0
  116. /package/templates/{default/apps/main → app}/postcss.config.cjs.hbs +0 -0
  117. /package/templates/{default → monorepo}/README.md.hbs +0 -0
@@ -2,6 +2,7 @@
2
2
  "name": "{{name}}",
3
3
  "private": true,
4
4
  "version": "1.0.0",
5
+ "description": "ChatBI-V {{#if isBusiness}}Business{{else}}System{{/if}} Plugin Project",
5
6
  "type": "module",
6
7
  "scripts": {
7
8
  "dev": "pnpm --filter @chatbi-v/main dev",
@@ -13,6 +14,8 @@
13
14
  "plugins/*"
14
15
  ],
15
16
  "dependencies": {
17
+ "react": "^18.3.1",
18
+ "react-dom": "^18.3.1",
16
19
  "antd": "^5.29.3",
17
20
  "axios": "^1.13.2",
18
21
  "clsx": "^2.1.1",
@@ -23,6 +26,8 @@
23
26
  "typescript": "^5.0.0",
24
27
  "@chatbi-v/cli": "link:./.chatbi/cli",
25
28
  "@ant-design/icons": "^5.6.1",
29
+ "@types/react": "^18.3.1",
30
+ "@types/react-dom": "^18.3.1",
26
31
  "vite": "^5.4.0",
27
32
  "@vitejs/plugin-react": "^4.3.1",
28
33
  "tailwindcss": "^3.4.0",
@@ -0,0 +1,10 @@
1
+ # ChatBI Monorepo Workspace Configuration
2
+ packages:
3
+ # 宿主应用目录
4
+ - 'apps/*'
5
+ # 插件目录
6
+ - 'plugins/*'
7
+
8
+ # 增量配置:如果添加了核心库或工具库,可在此处包含
9
+ # - 'packages/*'
10
+ # - 'libs/*'
@@ -1,4 +1,5 @@
1
1
  {
2
+ "extends": "./.chatbi/tsconfig.paths.json",
2
3
  "compilerOptions": {
3
4
  "target": "ESNext",
4
5
  "useDefineForClassFields": true,
@@ -17,7 +18,8 @@
17
18
  "jsx": "react-jsx",
18
19
  "baseUrl": ".",
19
20
  "paths": {
20
- "@chatbi-v/core": ["./.chatbi/core"]
21
+ "@chatbi-plugins/*": ["./plugins/*/src"],
22
+ "@chatbi-apps/*": ["./apps/*/src"]
21
23
  }
22
24
  },
23
25
  "include": ["apps/main/src", "plugins/*/src"]
@@ -1,8 +1,9 @@
1
1
  {
2
- "name": "@chatbi-v/plugin-demo-plugin",
2
+ "name": "{{name}}",
3
3
  "version": "1.0.0",
4
4
  "type": "module",
5
5
  "plugin": true,
6
+ "pluginType": "{{pluginType}}",
6
7
  "main": "src/index.tsx",
7
8
  "module": "src/index.tsx",
8
9
  "exports": {
@@ -11,7 +12,12 @@
11
12
  "scripts": {
12
13
  "build": "chatbi-cli build"
13
14
  },
14
- "dependencies": {
15
- "@chatbi-v/core": "link:../../.chatbi/core"
15
+ "devDependencies": {
16
+ },
17
+ "peerDependencies": {
18
+ "@chatbi-v/core": "*",
19
+ "react": ">=18.0.0",
20
+ "react-dom": ">=18.0.0",
21
+ "antd": ">=5.0.0"
16
22
  }
17
23
  }
@@ -0,0 +1,90 @@
1
+ import React from 'react'
2
+ import { Plugin, PluginContext, Slot } from '@chatbi-v/core'
3
+ import { MessageOutlined } from '@ant-design/icons'
4
+
5
+ /**
6
+ * 插件入口类
7
+ * 必须实现 Plugin 接口,并导出为 default
8
+ *
9
+ * 生命周期说明:
10
+ * - onLoad: 插件加载时调用,用于初始化状态、注册服务等
11
+ * - onUnload: 插件卸载时调用,用于清理资源
12
+ */
13
+ export class {{className}} implements Plugin {
14
+ // 插件唯一标识,必须与 metadata.id 保持一致
15
+ id = '{{pluginId}}'
16
+
17
+ // 插件元数据定义
18
+ metadata = {
19
+ id: '{{pluginId}}',
20
+ name: '{{pluginId}} Plugin',
21
+ version: '1.0.0',
22
+ type: '{{pluginType}}' as const, // business | system
23
+
24
+ /**
25
+ * 路由配置 (可选)
26
+ * 如果插件需要注册页面路由,在此处定义
27
+ */
28
+ routes: [
29
+ {
30
+ path: '/{{pluginId}}',
31
+ // 路由对应的组件
32
+ component: () => <div style=\{{ padding: '20px', background: '#f5f5f5', borderRadius: '8px' }}>
33
+ <h3>Hello from {{pluginId}} Plugin!</h3>
34
+ <p>This is a {{pluginType}} plugin generated by ChatBI CLI.</p>
35
+ </div>,
36
+ meta: {
37
+ title: '{{pluginId}}',
38
+ icon: 'MessageOutlined' // 对应 AntD Icon 名称
39
+ }
40
+ }
41
+ ],
42
+
43
+ /**
44
+ * 扩展插槽配置 (可选)
45
+ * 用于将组件注入到系统的各个位置 (如侧边栏、顶部栏等)
46
+ */
47
+ extensions: [
48
+ {
49
+ slot: Slot.Sidebar, // 注入到侧边栏
50
+ component: () => null, // 侧边栏通常不需要组件实体,只需要 meta 信息
51
+ order: 10, // 排序权重,越小越靠前
52
+ meta: {
53
+ title: '{{pluginId}}',
54
+ icon: <MessageOutlined />, // 直接传入 ReactNode
55
+ path: '/{{pluginId}}' // 点击跳转的路径
56
+ }
57
+ }
58
+ // 示例:注入到顶部栏
59
+ // {
60
+ // slot: Slot.TopBar,
61
+ // component: () => <MyTopBarComponent />,
62
+ // order: 5
63
+ // }
64
+ ]
65
+ }
66
+
67
+ /**
68
+ * 插件加载回调
69
+ * @param context 插件上下文,包含 logger, eventBus, serviceRegistry 等
70
+ */
71
+ onLoad(context: PluginContext) {
72
+ context.logger.info('{{className}} Loaded!')
73
+
74
+ // 示例:监听事件
75
+ // context.eventBus.on('some-event', () => { ... })
76
+
77
+ // 示例:注册服务
78
+ // context.serviceRegistry.register('myService', new MyService())
79
+ }
80
+
81
+ /**
82
+ * 插件卸载回调 (可选)
83
+ */
84
+ onUnload() {
85
+ // 清理资源
86
+ console.log('{{className}} Unloaded')
87
+ }
88
+ }
89
+
90
+ export default {{className}}
@@ -0,0 +1,14 @@
1
+ {
2
+ "extends": "{{tsconfigPath}}",
3
+ "compilerOptions": {
4
+ "baseUrl": ".",
5
+ "noEmit": false,
6
+ "declaration": true,
7
+ "emitDeclarationOnly": true,
8
+ "declarationDir": "./dist",
9
+ "paths": {
10
+ "@/*": ["./src/*"]
11
+ }
12
+ },
13
+ "include": ["src"]
14
+ }
package/package.json CHANGED
@@ -1,35 +1,47 @@
1
1
  {
2
2
  "name": "@chatbi-v/cli",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Standardized CLI tooling for ChatBI Monorepo",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
7
  "chatbi-cli": "./bin/chatbi-cli.js"
8
8
  },
9
9
  "files": [
10
- "templates",
11
10
  "dist",
12
- "bin"
11
+ "bin",
12
+ "templates"
13
13
  ],
14
14
  "publishConfig": {
15
15
  "access": "public"
16
16
  },
17
17
  "dependencies": {
18
+ "boxen": "^8.0.1",
18
19
  "cac": "^6.7.14",
19
20
  "execa": "^8.0.1",
21
+ "fast-glob": "^3.3.3",
22
+ "figlet": "^1.9.4",
20
23
  "fs-extra": "^11.2.0",
24
+ "gradient-string": "^3.0.0",
21
25
  "handlebars": "^4.7.8",
26
+ "jiti": "^2.6.1",
27
+ "ora": "^7.0.1",
22
28
  "picocolors": "^1.0.0",
29
+ "prompts": "^2.4.2",
23
30
  "tsup": "^8.5.1",
24
31
  "typescript": "^5.0.0",
32
+ "vite": "^5.4.21",
25
33
  "@chatbi-v/core": "1.0.3",
26
- "@chatbi-v/plugin-system-user": "1.0.1",
27
- "@chatbi-v/plugin-system-monitor": "1.0.1",
28
- "@chatbi-v/plugin-theme-manager": "1.0.2"
34
+ "@chatbi-v/plugin-theme-manager": "1.0.2",
35
+ "@chatbi-v/mocks": "1.0.1",
36
+ "@chatbi-v/plugin-system-monitor": "1.0.1"
29
37
  },
30
38
  "devDependencies": {
39
+ "@types/boxen": "^3.0.5",
40
+ "@types/figlet": "^1.7.0",
31
41
  "@types/fs-extra": "^11.0.0",
42
+ "@types/gradient-string": "^1.1.6",
32
43
  "@types/node": "^20.0.0",
44
+ "@types/prompts": "^2.4.9",
33
45
  "tsup": "^8.5.1",
34
46
  "vitest": "^1.0.0",
35
47
  "@chatbi-v/tsconfig": "1.0.2"
@@ -0,0 +1,8 @@
1
+ # API Base URL
2
+ VITE_API_BASE_URL=/bron-chat-bi
3
+
4
+ # 是否开启 Mock 模式 (能力开关,需配合 url mock=true 使用)
5
+ VITE_USE_MOCK=true
6
+
7
+ # API Timeout (ms)
8
+ VITE_API_TIMEOUT=10000
@@ -0,0 +1,16 @@
1
+ # @chatbi/main
2
+
3
+ ChatBI 主应用,基于 React 和 Vite 构建。
4
+
5
+ ## 功能
6
+
7
+ - **会话管理**: 支持会话列表、搜索、历史记录。
8
+ - **插件集成**: 集成 Chat 和 Scene 插件。
9
+ - **主题切换**: 支持深色/浅色模式。
10
+ - **布局管理**: 响应式布局,支持侧边栏折叠。
11
+
12
+ ## 启动
13
+
14
+ ```bash
15
+ pnpm dev
16
+ ```
@@ -0,0 +1,60 @@
1
+ /**
2
+ * ChatBI 应用配置文件
3
+ * @description 定义应用的全局配置和插件参数
4
+ */
5
+
6
+ import { DiscoveryRule } from '@chatbi-v/core';
7
+
8
+ interface ChatBIConfig {
9
+ /**
10
+ * 插件配置表
11
+ * Key: 插件 ID (通常是包名,如 @chatbi-v/plugin-chat)
12
+ * Value: 插件配置项
13
+ */
14
+ plugins: Record<string, any>;
15
+ system: {
16
+ title: string;
17
+ version: string;
18
+ language: string;
19
+ /** 插件发现规则 */
20
+ discoveryRules: DiscoveryRule[];
21
+ };
22
+ }
23
+
24
+ export const chatbiConfig: ChatBIConfig = {
25
+ /**
26
+ * 插件配置中心
27
+ * 这里只定义插件的"运行参数",插件的加载已由 AutoLoader 自动处理
28
+ */
29
+ plugins: {
30
+ '@chatbi-v/plugin-theme-manager': {
31
+ defaultTheme: '{{theme}}-light',
32
+ defaultLayout: 'standard',
33
+ },
34
+ '@chatbi-v/plugin-layout-transform': {},
35
+ '@chatbi-v/plugin-system-monitor': {},
36
+ },
37
+ /**
38
+ * 系统配置
39
+ */
40
+ system: {
41
+ title: '{{projectName}}',
42
+ version: '1.0.0',
43
+ language: 'zh-CN',
44
+ /** 插件发现规则 */
45
+ discoveryRules: [
46
+ {
47
+ pattern: '@chatbi-plugins/*/src/index.{ts,tsx}',
48
+ pathSegment: 'plugins',
49
+ idPrefix: '@chatbi-v/plugin',
50
+ alias: '@chatbi-plugins',
51
+ },
52
+ {
53
+ pattern: '@chatbi-apps/*/src/index.{ts,tsx}',
54
+ pathSegment: 'apps',
55
+ idPrefix: '@chatbi-v/app',
56
+ alias: '@chatbi-apps',
57
+ },
58
+ ],
59
+ },
60
+ };
@@ -1,10 +1,9 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
1
+ <!doctype html>
2
+ <html lang="zh-CN">
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
- <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
- <title>ChatBI Business Plugin Host</title>
6
+ <title>智能分析平台</title>
8
7
  </head>
9
8
  <body>
10
9
  <div id="root"></div>
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "{{name}}",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "vite",
7
+ "build": "tsc && vite build",
8
+ "preview": "vite preview",
9
+ "test": "vitest",
10
+ "sync": "chatbi-cli sync"
11
+ },
12
+ "dependencies": {
13
+ "@ant-design/icons": "^5.2.6",
14
+ "@ant-design/x": "^2.1.1",
15
+ "antd": "^5.29.3",
16
+ "react": "^18.3.1",
17
+ "react-dom": "^18.3.1",
18
+ "react-router-dom": "^7.10.1",
19
+ "zustand": "^5.0.9"
20
+ },
21
+ "devDependencies": {
22
+ "@types/node": "^20.0.0",
23
+ "@types/react": "^18.2.43",
24
+ "@types/react-dom": "^18.2.17",
25
+ "@vitejs/plugin-react": "^4.2.1",
26
+ "less": "^4.2.0",
27
+ "typescript": "^5.3.3",
28
+ "vite": "^5.0.8",
29
+ "vite-tsconfig-paths": "^4.3.1",
30
+ "tailwindcss": "^3.4.1",
31
+ "autoprefixer": "^10.4.17",
32
+ "postcss": "^8.4.35"
33
+ }
34
+ }
@@ -0,0 +1,92 @@
1
+ import React, { lazy, Suspense, useMemo } from 'react';
2
+ import { useLocation } from 'react-router-dom';
3
+
4
+ import { GlobalSettingsModal } from './components/GlobalSettingsModal';
5
+ import { ContentSkeleton, NavSkeleton } from './components/LayoutSkeletons';
6
+ import { usePluginLoader } from './hooks/usePluginLoader';
7
+ import { AppProviders } from './providers/AppProviders';
8
+ import { useSessionStore } from './stores/useSessionStore';
9
+ import { useUIStore } from './stores/useUIStore';
10
+
11
+ // Lazy load layouts
12
+ const BackgroundEffects = lazy(() => import('./layouts/BackgroundEffects').then(module => ({ default: module.BackgroundEffects })));
13
+ const MainContent = lazy(() => import('./layouts/MainContent').then(module => ({ default: module.MainContent })));
14
+ const SidebarNav = lazy(() => import('./layouts/SidebarNav').then(module => ({ default: module.SidebarNav })));
15
+
16
+ const App: React.FC = () => {
17
+ const location = useLocation();
18
+ const activeTab = location.pathname.replace(/^\//, '') || '';
19
+
20
+ // 1. 加载插件 (逻辑已封装)
21
+ const { pluginsLoaded } = usePluginLoader();
22
+
23
+ // 2. 获取 UI 状态
24
+ const { activeSession, setActiveSession } = useSessionStore();
25
+ const {
26
+ isRightPanelOpen, setIsRightPanelOpen,
27
+ isMaximized, setIsMaximized,
28
+ collapsed
29
+ } = useUIStore();
30
+
31
+ // 3. 构造共享 Props
32
+ const sharedProps = useMemo(() => ({
33
+ activeSession,
34
+ setActiveSession,
35
+ isRightPanelOpen,
36
+ setIsRightPanelOpen,
37
+ isMaximized,
38
+ setIsMaximized
39
+ }), [
40
+ activeSession,
41
+ setActiveSession,
42
+ isRightPanelOpen,
43
+ setIsRightPanelOpen,
44
+ isMaximized,
45
+ setIsMaximized
46
+ ]);
47
+
48
+ return (
49
+ <AppProviders>
50
+ <div className="flex h-screen w-screen bg-slate-50 dark:bg-slate-950 overflow-hidden text-slate-900 dark:text-slate-200 selection:bg-primary/30 font-sans transition-colors duration-300">
51
+
52
+ <Suspense fallback={null}>
53
+ <BackgroundEffects />
54
+ </Suspense>
55
+
56
+ {/* Sidebar */}
57
+ <Suspense fallback={
58
+ <div className={`relative z-20 flex flex-col items-center py-4 gap-[var(--layout-gap)] transition-all duration-500 ease-[cubic-bezier(0.2,0,0,1)]
59
+ border-r border-slate-200/60 dark:border-white/10 backdrop-blur-xl bg-white/80 dark:bg-slate-900/80
60
+ ${isMaximized ? 'w-0 overflow-hidden opacity-0 p-0 border-none' : (collapsed ? 'w-[72px]' : 'w-[var(--layout-sidebar-width)]')}
61
+ h-screen
62
+ `}>
63
+ <NavSkeleton />
64
+ </div>
65
+ }>
66
+ <SidebarNav
67
+ activeTab={activeTab}
68
+ pluginsLoaded={pluginsLoaded}
69
+ />
70
+ </Suspense>
71
+
72
+ {/* Main Content */}
73
+ <Suspense fallback={
74
+ <main className="flex-1 flex flex-col relative z-10 overflow-hidden bg-white/50 dark:bg-black/20 backdrop-blur-sm">
75
+ <ContentSkeleton />
76
+ </main>
77
+ }>
78
+ <MainContent
79
+ pluginsLoaded={pluginsLoaded}
80
+ sharedProps={sharedProps}
81
+ />
82
+ </Suspense>
83
+
84
+ {/* Global Settings */}
85
+ <GlobalSettingsModal />
86
+
87
+ </div>
88
+ </AppProviders>
89
+ );
90
+ };
91
+
92
+ export default App;
@@ -0,0 +1,69 @@
1
+ import { createLogger } from '@chatbi-v/core';
2
+ import { Button, Result, Typography } from 'antd';
3
+ import React, { Component, ErrorInfo, ReactNode } from 'react';
4
+
5
+ const { Paragraph, Text } = Typography;
6
+ const logger = createLogger('GlobalError');
7
+
8
+ interface Props {
9
+ children: ReactNode;
10
+ }
11
+
12
+ interface State {
13
+ hasError: boolean;
14
+ error: Error | null;
15
+ errorInfo: ErrorInfo | null;
16
+ }
17
+
18
+ export class GlobalErrorBoundary extends Component<Props, State> {
19
+ constructor(props: Props) {
20
+ super(props);
21
+ this.state = { hasError: false, error: null, errorInfo: null };
22
+ }
23
+
24
+ static getDerivedStateFromError(error: Error): State {
25
+ return { hasError: true, error, errorInfo: null };
26
+ }
27
+
28
+ componentDidCatch(error: Error, errorInfo: ErrorInfo) {
29
+ logger.error('Uncaught error:', error, errorInfo);
30
+ this.setState({ errorInfo });
31
+ // TODO: Report to logging service
32
+ }
33
+
34
+ handleReload = () => {
35
+ window.location.reload();
36
+ };
37
+
38
+ render() {
39
+ if (this.state.hasError) {
40
+ return (
41
+ <div className="flex items-center justify-center min-h-screen bg-gray-50 p-4">
42
+ <Result
43
+ status="500"
44
+ title="应用遇到了一些问题"
45
+ subTitle="抱歉,发生了未预期的错误,请尝试刷新页面。"
46
+ extra={[
47
+ <Button type="primary" key="reload" onClick={this.handleReload}>
48
+ 刷新页面
49
+ </Button>,
50
+ ]}
51
+ >
52
+ {import.meta.env.DEV && this.state.error && (
53
+ <div className="mt-8 text-left max-w-2xl bg-white p-4 rounded border border-gray-200 shadow-sm overflow-auto max-h-96">
54
+ <Paragraph>
55
+ <Text type="danger" strong>Error: {this.state.error.toString()}</Text>
56
+ </Paragraph>
57
+ <Paragraph className="mb-0">
58
+ <Text code className="text-xs">{this.state.errorInfo?.componentStack}</Text>
59
+ </Paragraph>
60
+ </div>
61
+ )}
62
+ </Result>
63
+ </div>
64
+ );
65
+ }
66
+
67
+ return this.props.children;
68
+ }
69
+ }
@@ -0,0 +1,35 @@
1
+ import { Modal, Skeleton } from 'antd';
2
+ import React, { lazy, Suspense } from 'react';
3
+
4
+ import { useUIStore } from '../stores/useUIStore';
5
+
6
+ // Lazy load
7
+ const PluginSettings = lazy(() => import('../features/settings/PluginSettings').then(module => ({ default: module.PluginSettings })));
8
+
9
+ /**
10
+ * 全局设置弹窗组件
11
+ */
12
+ export const GlobalSettingsModal: React.FC = () => {
13
+ const { isSettingsOpen, setIsSettingsOpen } = useUIStore();
14
+
15
+ return (
16
+ <Modal
17
+ title="设置"
18
+ open={isSettingsOpen}
19
+ onCancel={() => setIsSettingsOpen(false)}
20
+ footer={null}
21
+ width={800}
22
+ centered
23
+ className="settings-modal"
24
+ styles={{ body: { height: '600px', padding: 0, overflow: 'hidden' } }}
25
+ >
26
+ <Suspense fallback={
27
+ <div className="w-full h-full flex items-center justify-center">
28
+ <Skeleton active paragraph={{ rows: 10 }} />
29
+ </div>
30
+ }>
31
+ <PluginSettings />
32
+ </Suspense>
33
+ </Modal>
34
+ );
35
+ };
@@ -0,0 +1,79 @@
1
+ import { SidebarIconSkeleton } from '@chatbi-v/core';
2
+ import { Skeleton } from 'antd';
3
+ import React from 'react';
4
+
5
+ import { useUIStore } from '../stores/useUIStore';
6
+
7
+ export const NavSkeleton: React.FC = () => {
8
+ const { collapsed } = useUIStore();
9
+
10
+ return (
11
+ <div className={`flex flex-col items-center py-4 gap-[var(--layout-gap)] transition-all duration-300 w-full h-full`}>
12
+ {/* Brand Icon Skeleton */}
13
+ <div className={`flex items-center gap-3 mb-6 transition-all duration-300 ${!collapsed ? 'w-full px-5' : 'justify-center'}`}>
14
+ <div className="w-12 h-12 rounded-2xl bg-slate-200 dark:bg-white/10 shrink-0 animate-pulse" />
15
+ {!collapsed && (
16
+ <div className="flex flex-col gap-2 flex-1">
17
+ <div className="h-5 bg-slate-200 dark:bg-white/10 rounded w-20 animate-pulse" />
18
+ <div className="h-2 bg-slate-200 dark:bg-white/10 rounded w-12 animate-pulse" />
19
+ </div>
20
+ )}
21
+ </div>
22
+
23
+ {/* Nav Items Skeleton */}
24
+ <div className="flex-1 w-full flex flex-col gap-[var(--layout-gap)] items-center px-3 pt-2">
25
+ {[1, 2, 3, 4].map((i) => (
26
+ <SidebarIconSkeleton key={i} expanded={!collapsed} />
27
+ ))}
28
+ </div>
29
+
30
+ {/* Bottom Actions Skeleton */}
31
+ <div className="w-full flex flex-col gap-[var(--layout-gap)] mt-auto mb-2 items-center px-3">
32
+ <SidebarIconSkeleton expanded={!collapsed} />
33
+ <SidebarIconSkeleton expanded={!collapsed} />
34
+ <div className={`h-px bg-slate-200 dark:bg-white/10 my-2 transition-all duration-300 ${collapsed ? 'w-8' : 'w-full'}`} />
35
+ <div className={`flex items-center gap-3 transition-all duration-300 ${collapsed ? 'w-12 justify-center' : 'w-full px-4'}`}>
36
+ <div className="w-10 h-10 rounded-full bg-slate-200 dark:bg-white/10 animate-pulse" />
37
+ {!collapsed && <div className="h-4 bg-slate-200 dark:bg-white/10 rounded w-20 animate-pulse" />}
38
+ </div>
39
+ <SidebarIconSkeleton expanded={!collapsed} />
40
+ </div>
41
+ </div>
42
+ );
43
+ };
44
+
45
+ export const SidebarSkeleton: React.FC = () => {
46
+ return (
47
+ <div className="h-full w-full flex flex-col p-4 gap-4 animate-pulse">
48
+ {/* Header / Search */}
49
+ <div className="h-8 bg-slate-200 dark:bg-white/5 rounded-lg w-full" />
50
+
51
+ {/* List Items */}
52
+ <div className="flex-1 flex flex-col gap-3 mt-2">
53
+ {[1, 2, 3, 4, 5, 6].map((i) => (
54
+ <div key={i} className="flex flex-col gap-2 p-2">
55
+ <div className="h-4 bg-slate-200 dark:bg-white/5 rounded w-3/4" />
56
+ <div className="h-3 bg-slate-200 dark:bg-white/5 rounded w-1/2" />
57
+ </div>
58
+ ))}
59
+ </div>
60
+ </div>
61
+ );
62
+ };
63
+
64
+ export const ContentSkeleton: React.FC = () => {
65
+ return (
66
+ <div className="h-full w-full p-8 flex flex-col gap-6 animate-pulse">
67
+ {/* Header */}
68
+ <div className="h-10 bg-slate-200 dark:bg-white/5 rounded-xl w-1/3" />
69
+
70
+ {/* Content Blocks */}
71
+ <div className="flex-1 grid grid-cols-2 gap-6">
72
+ <div className="bg-slate-200 dark:bg-white/5 rounded-2xl h-full" />
73
+ <div className="bg-slate-200 dark:bg-white/5 rounded-2xl h-full" />
74
+ </div>
75
+
76
+ <div className="h-1/3 bg-slate-200 dark:bg-white/5 rounded-2xl w-full" />
77
+ </div>
78
+ );
79
+ };
@@ -0,0 +1,2 @@
1
+ export * from './GlobalErrorBoundary';
2
+ export * from './LayoutSkeletons';
@@ -0,0 +1,7 @@
1
+ /* src/custom-antd.less —— 会被 vite 注入,覆盖 antd 默认变量 */
2
+ @primary-color: #6366f1; // indigo-500 ← 与 tailwind 同步
3
+ @success-color: #22c55e; // green-500
4
+ @error-color: #ef4444; // red-500
5
+ @border-radius-base: 6px;
6
+ @font-size-base: 14px;
7
+ @line-height-base: 1.5715;