@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.
- package/dist/app/.env +8 -0
- package/dist/app/.env.hbs +8 -0
- package/dist/app/README.md.hbs +16 -0
- package/dist/app/chatbi.config.ts.hbs +60 -0
- package/{templates/default/apps/main → dist/app}/index.html.hbs +3 -4
- package/dist/app/package.json.hbs +34 -0
- package/dist/app/src/App.tsx.hbs +92 -0
- package/dist/app/src/components/GlobalErrorBoundary.tsx.hbs +69 -0
- package/dist/app/src/components/GlobalSettingsModal.tsx.hbs +35 -0
- package/dist/app/src/components/LayoutSkeletons.tsx.hbs +79 -0
- package/dist/app/src/components/index.ts.hbs +2 -0
- package/dist/app/src/custom-antd.less.hbs +7 -0
- package/dist/app/src/features/settings/ConfigRenderStrategy.tsx.hbs +119 -0
- package/dist/app/src/features/settings/ExtensionSettings.tsx.hbs +52 -0
- package/dist/app/src/features/settings/PluginList.tsx.hbs +115 -0
- package/dist/app/src/features/settings/PluginSettings.tsx.hbs +123 -0
- package/dist/app/src/features/settings/SchemaSettingsRenderer.tsx.hbs +56 -0
- package/dist/app/src/hooks/useAppRoutes.ts.hbs +39 -0
- package/dist/app/src/hooks/usePluginLoader.ts.hbs +22 -0
- package/dist/app/src/hooks/usePluginSettings.ts.hbs +29 -0
- package/dist/app/src/hooks/useThemeSync.ts.hbs +108 -0
- package/dist/app/src/index.css.hbs +45 -0
- package/dist/app/src/layouts/BackgroundEffects.tsx.hbs +10 -0
- package/dist/app/src/layouts/MainContent.tsx.hbs +58 -0
- package/dist/app/src/layouts/SidebarNav.tsx.hbs +182 -0
- package/dist/app/src/main.tsx.hbs +43 -0
- package/dist/app/src/providers/AppProviders.tsx.hbs +36 -0
- package/dist/app/src/services/api/index.ts.hbs +37 -0
- package/dist/app/src/services/api/modules/auth.ts.hbs +18 -0
- package/dist/app/src/services/config-service.ts.hbs +48 -0
- package/dist/app/src/stores/storage-adapter.ts.hbs +29 -0
- package/dist/app/src/stores/useSessionStore.ts.hbs +22 -0
- package/dist/app/src/stores/useUIStore.ts.hbs +64 -0
- package/dist/app/tailwind.config.cjs.hbs +14 -0
- package/dist/app/tsconfig.json.hbs +26 -0
- package/dist/app/vite.config.ts.hbs +89 -0
- package/dist/index.js +5662 -4194
- package/{templates/default → dist/monorepo}/package.json.hbs +5 -0
- package/dist/monorepo/pnpm-workspace.yaml.hbs +10 -0
- package/dist/{default → monorepo}/tsconfig.json.hbs +3 -1
- package/{templates/default/plugins/demo-plugin → dist/plugin}/package.json.hbs +9 -3
- package/dist/plugin/src/index.tsx.hbs +90 -0
- package/dist/plugin/tsconfig.json.hbs +14 -0
- package/package.json +18 -6
- package/templates/app/.env.hbs +8 -0
- package/templates/app/README.md.hbs +16 -0
- package/templates/app/chatbi.config.ts.hbs +60 -0
- package/{dist/default/apps/main → templates/app}/index.html.hbs +3 -4
- package/templates/app/package.json.hbs +34 -0
- package/templates/app/src/App.tsx.hbs +92 -0
- package/templates/app/src/components/GlobalErrorBoundary.tsx.hbs +69 -0
- package/templates/app/src/components/GlobalSettingsModal.tsx.hbs +35 -0
- package/templates/app/src/components/LayoutSkeletons.tsx.hbs +79 -0
- package/templates/app/src/components/index.ts.hbs +2 -0
- package/templates/app/src/custom-antd.less.hbs +7 -0
- package/templates/app/src/features/settings/ConfigRenderStrategy.tsx.hbs +119 -0
- package/templates/app/src/features/settings/ExtensionSettings.tsx.hbs +52 -0
- package/templates/app/src/features/settings/PluginList.tsx.hbs +115 -0
- package/templates/app/src/features/settings/PluginSettings.tsx.hbs +123 -0
- package/templates/app/src/features/settings/SchemaSettingsRenderer.tsx.hbs +56 -0
- package/templates/app/src/hooks/useAppRoutes.ts.hbs +39 -0
- package/templates/app/src/hooks/usePluginLoader.ts.hbs +22 -0
- package/templates/app/src/hooks/usePluginSettings.ts.hbs +29 -0
- package/templates/app/src/hooks/useThemeSync.ts.hbs +108 -0
- package/templates/app/src/index.css.hbs +45 -0
- package/templates/app/src/layouts/BackgroundEffects.tsx.hbs +10 -0
- package/templates/app/src/layouts/MainContent.tsx.hbs +58 -0
- package/templates/app/src/layouts/SidebarNav.tsx.hbs +182 -0
- package/templates/app/src/main.tsx.hbs +43 -0
- package/templates/app/src/providers/AppProviders.tsx.hbs +36 -0
- package/templates/app/src/services/api/index.ts.hbs +37 -0
- package/templates/app/src/services/api/modules/auth.ts.hbs +18 -0
- package/templates/app/src/services/config-service.ts.hbs +48 -0
- package/templates/app/src/stores/storage-adapter.ts.hbs +29 -0
- package/templates/app/src/stores/useSessionStore.ts.hbs +22 -0
- package/templates/app/src/stores/useUIStore.ts.hbs +64 -0
- package/templates/app/tailwind.config.cjs.hbs +14 -0
- package/templates/app/tsconfig.json.hbs +26 -0
- package/templates/app/vite.config.ts.hbs +89 -0
- package/templates/monorepo/.gitignore.hbs +3 -0
- package/{dist/default → templates/monorepo}/package.json.hbs +5 -0
- package/templates/monorepo/pnpm-workspace.yaml.hbs +10 -0
- package/templates/{default → monorepo}/tsconfig.json.hbs +3 -1
- package/{dist/default/plugins/demo-plugin → templates/plugin}/package.json.hbs +9 -3
- package/templates/plugin/src/index.tsx.hbs +90 -0
- package/templates/plugin/tsconfig.json.hbs +14 -0
- package/dist/default/apps/main/package.json.hbs +0 -20
- package/dist/default/apps/main/src/App.tsx.hbs +0 -162
- package/dist/default/apps/main/src/components/NavIcon.tsx.hbs +0 -41
- package/dist/default/apps/main/src/hooks/usePluginLoader.ts.hbs +0 -25
- package/dist/default/apps/main/src/index.css.hbs +0 -8
- package/dist/default/apps/main/src/main.tsx.hbs +0 -13
- package/dist/default/apps/main/src/pages/Guide.tsx.hbs +0 -133
- package/dist/default/apps/main/tailwind.config.cjs.hbs +0 -17
- package/dist/default/apps/main/tsconfig.json.hbs +0 -10
- package/dist/default/apps/main/vite.config.ts.hbs +0 -16
- package/dist/default/plugins/demo-plugin/src/index.tsx.hbs +0 -44
- package/dist/default/plugins/demo-plugin/tsconfig.json.hbs +0 -10
- package/dist/default/pnpm-workspace.yaml.hbs +0 -3
- package/templates/default/apps/main/package.json.hbs +0 -20
- package/templates/default/apps/main/src/App.tsx.hbs +0 -162
- package/templates/default/apps/main/src/components/NavIcon.tsx.hbs +0 -41
- package/templates/default/apps/main/src/hooks/usePluginLoader.ts.hbs +0 -25
- package/templates/default/apps/main/src/index.css.hbs +0 -8
- package/templates/default/apps/main/src/main.tsx.hbs +0 -13
- package/templates/default/apps/main/src/pages/Guide.tsx.hbs +0 -133
- package/templates/default/apps/main/tailwind.config.cjs.hbs +0 -17
- package/templates/default/apps/main/tsconfig.json.hbs +0 -10
- package/templates/default/apps/main/vite.config.ts.hbs +0 -16
- package/templates/default/plugins/demo-plugin/src/index.tsx.hbs +0 -44
- package/templates/default/plugins/demo-plugin/tsconfig.json.hbs +0 -10
- package/templates/default/pnpm-workspace.yaml.hbs +0 -3
- /package/dist/{default/apps/main → app}/postcss.config.cjs.hbs +0 -0
- /package/{templates/default → dist/monorepo}/.gitignore.hbs +0 -0
- /package/dist/{default → monorepo}/README.md.hbs +0 -0
- /package/templates/{default/apps/main → app}/postcss.config.cjs.hbs +0 -0
- /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",
|
|
@@ -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-
|
|
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": "
|
|
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
|
-
"
|
|
15
|
-
|
|
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}}
|
package/package.json
CHANGED
|
@@ -1,35 +1,47 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chatbi-v/cli",
|
|
3
|
-
"version": "1.0.
|
|
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-
|
|
27
|
-
"@chatbi-v/
|
|
28
|
-
"@chatbi-v/plugin-
|
|
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,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
|
-
<!
|
|
2
|
-
<html lang="
|
|
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
|
|
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,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;
|