@chatbi-v/cli 1.0.8 → 1.0.10
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/index.js +5342 -4330
- package/dist/monorepo/.gitignore.hbs +3 -0
- package/package.json +11 -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 +39 -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 -1
- package/templates/monorepo/pnpm-workspace.yaml.hbs +10 -0
- package/{dist/default → templates/monorepo}/tsconfig.json.hbs +3 -1
- package/{dist/default/plugins/demo-plugin → templates/plugin}/package.json.hbs +7 -2
- 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 -178
- 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/{dist/default/apps/main → templates/app}/postcss.config.cjs.hbs +0 -0
- /package/{dist/default → templates/monorepo}/README.md.hbs +0 -0
|
@@ -12,7 +12,12 @@
|
|
|
12
12
|
"scripts": {
|
|
13
13
|
"build": "chatbi-cli build"
|
|
14
14
|
},
|
|
15
|
-
"
|
|
16
|
-
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
},
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"@chatbi-v/core": "^1.0.4",
|
|
19
|
+
"react": ">=18.0.0",
|
|
20
|
+
"react-dom": ">=18.0.0",
|
|
21
|
+
"antd": ">=5.0.0"
|
|
17
22
|
}
|
|
18
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}}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@chatbi-v/main",
|
|
3
|
-
"private": true,
|
|
4
|
-
"type": "module",
|
|
5
|
-
"scripts": {
|
|
6
|
-
"dev": "vite",
|
|
7
|
-
"build": "vite build"
|
|
8
|
-
},
|
|
9
|
-
"dependencies": {
|
|
10
|
-
"react": "^18.3.1",
|
|
11
|
-
"react-dom": "^18.3.1",
|
|
12
|
-
"react-router-dom": "^6.22.3",
|
|
13
|
-
"antd": "^5.20.0",
|
|
14
|
-
"@ant-design/icons": "^5.2.6",
|
|
15
|
-
"@chatbi-v/core": "link:../../.chatbi/core"
|
|
16
|
-
},
|
|
17
|
-
"devDependencies": {
|
|
18
|
-
"@vitejs/plugin-react": "^4.3.1"
|
|
19
|
-
}
|
|
20
|
-
}
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
import React, { useMemo, useState } from 'react'
|
|
2
|
-
import { Routes, Route, Navigate, Link, useLocation, useNavigate } from 'react-router-dom'
|
|
3
|
-
import { usePluginLoader } from './hooks/usePluginLoader'
|
|
4
|
-
import { pluginManager, PluginSlot, Slot, SidebarIconSkeleton, type PluginExtension } from '@chatbi-v/core'
|
|
5
|
-
import { QuestionCircleOutlined, MenuFoldOutlined, MenuUnfoldOutlined, ThunderboltOutlined } from '@ant-design/icons'
|
|
6
|
-
import GuidePage from './pages/Guide'
|
|
7
|
-
import { NavIcon } from './components/NavIcon'
|
|
8
|
-
|
|
9
|
-
const App: React.FC = () => {
|
|
10
|
-
const { pluginsLoaded } = usePluginLoader()
|
|
11
|
-
const location = useLocation()
|
|
12
|
-
const navigate = useNavigate()
|
|
13
|
-
const [collapsed, setCollapsed] = useState(false)
|
|
14
|
-
|
|
15
|
-
// 收集插件路由
|
|
16
|
-
const routes = useMemo(() => {
|
|
17
|
-
return pluginsLoaded ? pluginManager.getRoutes() : []
|
|
18
|
-
}, [pluginsLoaded])
|
|
19
|
-
|
|
20
|
-
// 当前激活的 Tab (路径去掉前导斜杠)
|
|
21
|
-
const activeTab = useMemo(() => {
|
|
22
|
-
return location.pathname.replace(/^\//, '')
|
|
23
|
-
}, [location.pathname])
|
|
24
|
-
|
|
25
|
-
// 默认路由重定向逻辑
|
|
26
|
-
const defaultRoute = useMemo(() => {
|
|
27
|
-
if (routes.length > 0) {
|
|
28
|
-
return routes[0].path
|
|
29
|
-
}
|
|
30
|
-
return '/guide'
|
|
31
|
-
}, [routes])
|
|
32
|
-
|
|
33
|
-
if (!pluginsLoaded) {
|
|
34
|
-
return (
|
|
35
|
-
<div className="h-screen flex items-center justify-center bg-gray-50">
|
|
36
|
-
<div className="text-center">
|
|
37
|
-
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-indigo-500 mx-auto mb-4"></div>
|
|
38
|
-
<p className="text-gray-500">正在加载插件与内核...</p>
|
|
39
|
-
</div>
|
|
40
|
-
</div>
|
|
41
|
-
)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return (
|
|
45
|
-
<div className={`flex h-screen flex-col overflow-hidden font-sans ${
|
|
46
|
-
{{#if isNebula}}'bg-purple-50'{{else if isGlass}}'bg-slate-100'{{else}}'bg-gray-50'{{/if}}
|
|
47
|
-
}`}>
|
|
48
|
-
{/* Header */}
|
|
49
|
-
<header className={`flex h-16 items-center justify-between px-6 text-white shadow-md z-10 ${
|
|
50
|
-
{{#if isNebula}}'bg-gradient-to-r from-indigo-900 to-purple-900'{{else if isGlass}}'bg-white/70 backdrop-blur-md text-slate-900 border-b border-white/20'{{else}}'bg-slate-900'{{/if}}
|
|
51
|
-
}`}>
|
|
52
|
-
<div className="flex items-center gap-4">
|
|
53
|
-
<div className="flex items-center gap-2 group cursor-pointer" onClick={() => navigate('/')}>
|
|
54
|
-
<div className={`w-8 h-8 rounded-lg flex items-center justify-center shadow-lg transition-transform group-hover:scale-105 ${
|
|
55
|
-
{{#if isNebula}}'bg-purple-500 shadow-purple-500/20'{{else if isGlass}}'bg-blue-500 shadow-blue-500/20'{{else}}'bg-indigo-500 shadow-indigo-500/20'{{/if}}
|
|
56
|
-
}`}>
|
|
57
|
-
<ThunderboltOutlined className="text-lg text-white" />
|
|
58
|
-
</div>
|
|
59
|
-
<h2 className={`m-0 text-lg font-bold tracking-tight uppercase ${
|
|
60
|
-
{{#if isGlass}}'text-slate-800'{{else}}'text-white'{{/if}}
|
|
61
|
-
}`}>
|
|
62
|
-
{{name}}
|
|
63
|
-
</h2>
|
|
64
|
-
</div>
|
|
65
|
-
<nav className="ml-8 flex gap-4">
|
|
66
|
-
<Link
|
|
67
|
-
to="/guide"
|
|
68
|
-
className={`flex items-center gap-1.5 px-3 py-1 rounded transition-colors ${
|
|
69
|
-
location.pathname === '/guide'
|
|
70
|
-
? ({{#if isGlass}}'bg-blue-500/10 text-blue-600'{{else}}'bg-indigo-500/20 text-indigo-300'{{/if}})
|
|
71
|
-
: ({{#if isGlass}}'text-slate-500 hover:text-slate-800'{{else}}'text-gray-400 hover:text-white'{{/if}})
|
|
72
|
-
}`}
|
|
73
|
-
>
|
|
74
|
-
<QuestionCircleOutlined />
|
|
75
|
-
<span>开发指南</span>
|
|
76
|
-
</Link>
|
|
77
|
-
</nav>
|
|
78
|
-
</div>
|
|
79
|
-
<div className="header-actions flex items-center gap-4">
|
|
80
|
-
<PluginSlot slot={Slot.Header} />
|
|
81
|
-
</div>
|
|
82
|
-
</header>
|
|
83
|
-
|
|
84
|
-
<div className="flex flex-1 overflow-hidden">
|
|
85
|
-
{/* Sidebar */}
|
|
86
|
-
<aside
|
|
87
|
-
className={`flex flex-col border-r transition-all duration-300 ease-in-out ${
|
|
88
|
-
collapsed ? 'w-16' : 'w-64'
|
|
89
|
-
} ${
|
|
90
|
-
{{#if isGlass}}'bg-white/40 backdrop-blur-lg border-white/20 shadow-xl shadow-slate-200/50'{{else if isNebula}}'bg-white border-purple-100 shadow-sm'{{else}}'bg-white border-gray-200 shadow-sm'{{/if}}
|
|
91
|
-
}`}
|
|
92
|
-
>
|
|
93
|
-
<div className={`p-4 border-b text-xs font-semibold uppercase tracking-wider overflow-hidden whitespace-nowrap ${collapsed ? 'text-center px-0' : ''} ${
|
|
94
|
-
{{#if isNebula}}'bg-purple-50/50 text-purple-400 border-purple-50'{{else if isGlass}}'bg-blue-50/30 text-blue-500 border-white/20'{{else}}'bg-gray-50/50 text-gray-400 border-gray-50'{{/if}}
|
|
95
|
-
}`}>
|
|
96
|
-
{collapsed ? '···' : '插件菜单'}
|
|
97
|
-
</div>
|
|
98
|
-
<div className="flex-1 overflow-y-auto no-scrollbar py-4 px-2">
|
|
99
|
-
<PluginSlot
|
|
100
|
-
slot={Slot.Sidebar}
|
|
101
|
-
className="flex flex-col gap-2 w-full items-center"
|
|
102
|
-
skeleton={
|
|
103
|
-
<div className="flex flex-col gap-4 w-full items-center px-2">
|
|
104
|
-
{[1, 2, 3].map(i => <SidebarIconSkeleton key={i} />)}
|
|
105
|
-
</div>
|
|
106
|
-
}
|
|
107
|
-
renderItem={({ key, extension }: { key: string, extension: PluginExtension }) => (
|
|
108
|
-
<NavIcon
|
|
109
|
-
key={key}
|
|
110
|
-
icon={extension.meta?.icon}
|
|
111
|
-
label={extension.meta?.label}
|
|
112
|
-
active={
|
|
113
|
-
activeTab === (extension.meta?.path || extension.meta?.key)?.replace(/^\//, '') ||
|
|
114
|
-
activeTab.startsWith(((extension.meta?.path || extension.meta?.key)?.replace(/^\//, '') || '') + '/')
|
|
115
|
-
}
|
|
116
|
-
onClick={() => navigate(extension.meta?.path || '/')}
|
|
117
|
-
expanded={!collapsed}
|
|
118
|
-
/>
|
|
119
|
-
)}
|
|
120
|
-
/>
|
|
121
|
-
</div>
|
|
122
|
-
|
|
123
|
-
{/* Sidebar Footer */}
|
|
124
|
-
<div className="p-2 border-t border-gray-100">
|
|
125
|
-
<NavIcon
|
|
126
|
-
icon={collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
|
|
127
|
-
onClick={() => setCollapsed(!collapsed)}
|
|
128
|
-
title={collapsed ? "展开侧边栏" : "折叠侧边栏"}
|
|
129
|
-
label={collapsed ? "展开" : "折叠"}
|
|
130
|
-
expanded={!collapsed}
|
|
131
|
-
/>
|
|
132
|
-
</div>
|
|
133
|
-
</aside>
|
|
134
|
-
|
|
135
|
-
{/* Main Content */}
|
|
136
|
-
<main className="flex-1 relative overflow-hidden flex flex-col">
|
|
137
|
-
<div className={`absolute top-0 left-0 right-0 h-1 z-20 ${
|
|
138
|
-
{{#if isNebula}}'bg-purple-500/20'{{else if isGlass}}'bg-blue-500/20'{{else}}'bg-indigo-500/10'{{/if}}
|
|
139
|
-
}`} />
|
|
140
|
-
|
|
141
|
-
<div className="flex-1 overflow-y-auto p-6 scroll-smooth bg-transparent">
|
|
142
|
-
<div className={`mx-auto max-w-7xl h-full ${
|
|
143
|
-
{{#if isGlass}}'bg-white/60 backdrop-blur-md rounded-2xl border border-white/40 shadow-xl p-8'{{else}}''{{/if}}
|
|
144
|
-
}`}>
|
|
145
|
-
<Routes>
|
|
146
|
-
<Route path="/guide" element={<GuidePage />} />
|
|
147
|
-
{routes.map(route => (
|
|
148
|
-
<Route key={route.path} path={route.path} element={<route.component />} />
|
|
149
|
-
))}
|
|
150
|
-
<Route path="/" element={<Navigate to={defaultRoute} replace />} />
|
|
151
|
-
</Routes>
|
|
152
|
-
</div>
|
|
153
|
-
</div>
|
|
154
|
-
|
|
155
|
-
{/* Footer Slot */}
|
|
156
|
-
<div className={`mt-auto px-6 py-3 border-t text-xs text-gray-400 flex justify-between items-center ${
|
|
157
|
-
{{#if isGlass}}'bg-white/30 border-white/20'{{else if isNebula}}'bg-purple-50/30 border-purple-50'{{else}}'bg-white border-gray-100'{{/if}}
|
|
158
|
-
}`}>
|
|
159
|
-
<div>ChatBI-V Plugin Container v1.0.0</div>
|
|
160
|
-
<PluginSlot slot={Slot.Footer} />
|
|
161
|
-
</div>
|
|
162
|
-
</main>
|
|
163
|
-
</div>
|
|
164
|
-
|
|
165
|
-
{/* Footer */}
|
|
166
|
-
<footer className="h-10 flex items-center px-4 bg-white border-t border-gray-200 text-xs text-gray-400 shrink-0">
|
|
167
|
-
<div className="flex-1 flex items-center">
|
|
168
|
-
<PluginSlot slot={Slot.StatusBar} />
|
|
169
|
-
</div>
|
|
170
|
-
<div>
|
|
171
|
-
SDK Version: 1.0.0
|
|
172
|
-
</div>
|
|
173
|
-
</footer>
|
|
174
|
-
</div>
|
|
175
|
-
)
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
export default App
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
export const NavIcon = React.memo(({
|
|
4
|
-
icon,
|
|
5
|
-
active,
|
|
6
|
-
onClick,
|
|
7
|
-
title,
|
|
8
|
-
label,
|
|
9
|
-
expanded,
|
|
10
|
-
}: {
|
|
11
|
-
icon: React.ReactNode;
|
|
12
|
-
active?: boolean;
|
|
13
|
-
onClick?: () => void;
|
|
14
|
-
title?: string;
|
|
15
|
-
label?: string;
|
|
16
|
-
expanded?: boolean;
|
|
17
|
-
}) => (
|
|
18
|
-
<div
|
|
19
|
-
onClick={onClick}
|
|
20
|
-
title={title}
|
|
21
|
-
className={`flex items-center cursor-pointer transition-all duration-300 relative group
|
|
22
|
-
${expanded ? 'w-full' : 'w-12'} px-3 h-11 rounded-xl
|
|
23
|
-
${
|
|
24
|
-
active
|
|
25
|
-
? 'bg-indigo-500/15 text-indigo-600 font-semibold shadow-sm ring-1 ring-indigo-500/20'
|
|
26
|
-
: 'text-slate-500 hover:bg-slate-100 hover:text-slate-900 hover:scale-105 active:scale-95'
|
|
27
|
-
}`}
|
|
28
|
-
>
|
|
29
|
-
<div className="w-6 h-6 flex items-center justify-center shrink-0">
|
|
30
|
-
<div className={`text-xl transition-transform duration-300 ${!expanded && active ? 'scale-110' : ''}`}>{icon}</div>
|
|
31
|
-
</div>
|
|
32
|
-
|
|
33
|
-
<div className={`overflow-hidden whitespace-nowrap transition-all duration-300 ease-in-out ${
|
|
34
|
-
expanded ? 'w-auto opacity-100 ml-3' : 'w-0 opacity-0 ml-0'
|
|
35
|
-
}`}>
|
|
36
|
-
<span className="text-sm block">
|
|
37
|
-
{label}
|
|
38
|
-
</span>
|
|
39
|
-
</div>
|
|
40
|
-
</div>
|
|
41
|
-
));
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { usePluginLoader as useCoreLoader } from '@chatbi-v/core'
|
|
2
|
-
import { useMemo } from 'react'
|
|
3
|
-
|
|
4
|
-
// 离线插件注册表
|
|
5
|
-
const offlineRegistry = {
|
|
6
|
-
"theme-manager": () => import("@chatbi-v/plugin-theme-manager"),
|
|
7
|
-
"system-user": () => import("@chatbi-v/plugin-system-user"),
|
|
8
|
-
"system-monitor": () => import("@chatbi-v/plugin-system-monitor"),
|
|
9
|
-
"demo-plugin": () => import("@chatbi-v/plugin-demo-plugin")
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export const usePluginLoader = () => {
|
|
13
|
-
const options = useMemo(() => ({
|
|
14
|
-
pluginConfigs: {
|
|
15
|
-
'theme-manager': { enabled: true },
|
|
16
|
-
'system-user': { enabled: true },
|
|
17
|
-
'system-monitor': { enabled: true },
|
|
18
|
-
'demo-plugin': { enabled: true }
|
|
19
|
-
},
|
|
20
|
-
registry: offlineRegistry,
|
|
21
|
-
sharedContext: { api: {} }
|
|
22
|
-
}), [])
|
|
23
|
-
|
|
24
|
-
return useCoreLoader(options)
|
|
25
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import ReactDOM from 'react-dom/client'
|
|
3
|
-
import { HashRouter } from 'react-router-dom'
|
|
4
|
-
import App from './App'
|
|
5
|
-
import './index.css'
|
|
6
|
-
|
|
7
|
-
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
8
|
-
<React.StrictMode>
|
|
9
|
-
<HashRouter>
|
|
10
|
-
<App />
|
|
11
|
-
</HashRouter>
|
|
12
|
-
</React.StrictMode>,
|
|
13
|
-
)
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Typography, Card, Space, Divider, List, Tag } from 'antd';
|
|
3
|
-
import {
|
|
4
|
-
FolderOpenOutlined,
|
|
5
|
-
RocketOutlined,
|
|
6
|
-
BuildOutlined,
|
|
7
|
-
CodeOutlined,
|
|
8
|
-
BlockOutlined,
|
|
9
|
-
SettingOutlined
|
|
10
|
-
} from '@ant-design/icons';
|
|
11
|
-
|
|
12
|
-
const { Title, Paragraph, Text } = Typography;
|
|
13
|
-
|
|
14
|
-
const GuidePage: React.FC = () => {
|
|
15
|
-
return (
|
|
16
|
-
<div className="max-w-4xl mx-auto py-8 px-4">
|
|
17
|
-
<Typography>
|
|
18
|
-
<Title level={2} className="flex items-center gap-2">
|
|
19
|
-
<RocketOutlined className="text-indigo-500" />
|
|
20
|
-
欢迎使用 {{name}} 开发容器
|
|
21
|
-
</Title>
|
|
22
|
-
<Paragraph className="text-gray-500 text-lg">
|
|
23
|
-
这是一个基于 ChatBI-V SDK 构建的业务插件开发环境。你可以通过此容器快速开发、调试并预览你的插件。
|
|
24
|
-
</Paragraph>
|
|
25
|
-
</Typography>
|
|
26
|
-
|
|
27
|
-
<Divider />
|
|
28
|
-
|
|
29
|
-
<Space direction="vertical" size="large" className="w-full">
|
|
30
|
-
{/* 项目目录介绍 */}
|
|
31
|
-
<Card
|
|
32
|
-
title={<span className="flex items-center gap-2"><FolderOpenOutlined /> 项目目录介绍</span>}
|
|
33
|
-
variant="borderless"
|
|
34
|
-
className="shadow-sm"
|
|
35
|
-
>
|
|
36
|
-
<List
|
|
37
|
-
itemLayout="horizontal"
|
|
38
|
-
dataSource={[
|
|
39
|
-
{
|
|
40
|
-
title: 'apps/main',
|
|
41
|
-
description: '宿主应用框架,负责加载插件、提供布局和基础能力。',
|
|
42
|
-
icon: <BlockOutlined className="text-blue-500" />
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
title: 'plugins/',
|
|
46
|
-
description: '业务插件源码目录,你开发的所有插件都应放置在此目录下。',
|
|
47
|
-
icon: <CodeOutlined className="text-green-500" />
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
title: '.chatbi/',
|
|
51
|
-
description: '离线 SDK 资源,包含核心库 (@chatbi-v/core) 和内置标准插件。',
|
|
52
|
-
icon: <SettingOutlined className="text-orange-500" />
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
title: 'scripts/',
|
|
56
|
-
description: '辅助开发脚本,如快速创建插件脚本。',
|
|
57
|
-
icon: <BuildOutlined className="text-purple-500" />
|
|
58
|
-
}
|
|
59
|
-
]}
|
|
60
|
-
renderItem={(item) => (
|
|
61
|
-
<List.Item>
|
|
62
|
-
<List.Item.Meta
|
|
63
|
-
avatar={item.icon}
|
|
64
|
-
title={<Text strong>{item.title}</Text>}
|
|
65
|
-
description={item.description}
|
|
66
|
-
/>
|
|
67
|
-
</List.Item>
|
|
68
|
-
)}
|
|
69
|
-
/>
|
|
70
|
-
</Card>
|
|
71
|
-
|
|
72
|
-
{/* 开发指南 */}
|
|
73
|
-
<Card
|
|
74
|
-
title={<span className="flex items-center gap-2"><BuildOutlined /> 开发指南</span>}
|
|
75
|
-
variant="borderless"
|
|
76
|
-
className="shadow-sm"
|
|
77
|
-
>
|
|
78
|
-
<div className="space-y-4">
|
|
79
|
-
<div>
|
|
80
|
-
<Text strong className="block mb-2">1. 安装依赖</Text>
|
|
81
|
-
<Tag color="default" className="font-mono px-2 py-1">pnpm install</Tag>
|
|
82
|
-
</div>
|
|
83
|
-
<div>
|
|
84
|
-
<Text strong className="block mb-2">2. 启动开发环境</Text>
|
|
85
|
-
<Tag color="blue" className="font-mono px-2 py-1">pnpm dev</Tag>
|
|
86
|
-
<Paragraph className="mt-2 text-gray-500 text-sm">
|
|
87
|
-
该命令会同时启动宿主应用和监听插件变化。
|
|
88
|
-
</Paragraph>
|
|
89
|
-
</div>
|
|
90
|
-
<div>
|
|
91
|
-
<Text strong className="block mb-2">3. 构建发布</Text>
|
|
92
|
-
<Tag color="green" className="font-mono px-2 py-1">pnpm build</Tag>
|
|
93
|
-
<Paragraph className="mt-2 text-gray-500 text-sm">
|
|
94
|
-
生成生产环境可用的静态资源。
|
|
95
|
-
</Paragraph>
|
|
96
|
-
</div>
|
|
97
|
-
</div>
|
|
98
|
-
</Card>
|
|
99
|
-
|
|
100
|
-
{/* 插件开发指南 */}
|
|
101
|
-
<Card
|
|
102
|
-
title={<span className="flex items-center gap-2"><CodeOutlined /> 插件开发指南</span>}
|
|
103
|
-
variant="borderless"
|
|
104
|
-
className="shadow-sm"
|
|
105
|
-
>
|
|
106
|
-
<Typography>
|
|
107
|
-
<Paragraph>
|
|
108
|
-
要创建一个新的业务插件,请运行:
|
|
109
|
-
</Paragraph>
|
|
110
|
-
<Tag color="magenta" className="font-mono px-2 py-1 mb-4">pnpm create:plugin [plugin-name]</Tag>
|
|
111
|
-
|
|
112
|
-
<Title level={5}>插件核心结构:</Title>
|
|
113
|
-
<Paragraph>
|
|
114
|
-
每个插件都需要继承自 <Text code>Plugin</Text> 类并导出。关键属性包括:
|
|
115
|
-
</Paragraph>
|
|
116
|
-
<ul className="list-disc pl-5 space-y-2 text-gray-600">
|
|
117
|
-
<li><Text strong>id</Text>: 插件唯一标识。</li>
|
|
118
|
-
<li><Text strong>metadata.routes</Text>: 定义插件自带的页面路由。</li>
|
|
119
|
-
<li><Text strong>metadata.extensions</Text>: 通过插槽 (Slot) 扩展宿主应用的 UI。</li>
|
|
120
|
-
<li><Text strong>onLoad</Text>: 插件加载时的初始化逻辑。</li>
|
|
121
|
-
</ul>
|
|
122
|
-
</Typography>
|
|
123
|
-
</Card>
|
|
124
|
-
</Space>
|
|
125
|
-
|
|
126
|
-
<div className="mt-12 text-center text-gray-400 text-sm">
|
|
127
|
-
© 2025 ChatBI-V System. All rights reserved.
|
|
128
|
-
</div>
|
|
129
|
-
</div>
|
|
130
|
-
);
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
export default GuidePage;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/** @type {import('tailwindcss').Config} */
|
|
2
|
-
module.exports = {
|
|
3
|
-
content: [
|
|
4
|
-
"./index.html",
|
|
5
|
-
"./src/**/*.{js,ts,jsx,tsx}",
|
|
6
|
-
"../../plugins/*/src/**/*.{js,ts,jsx,tsx}",
|
|
7
|
-
"../../.chatbi/plugins/*/dist/*.{js,mjs}"
|
|
8
|
-
],
|
|
9
|
-
theme: {
|
|
10
|
-
extend: {
|
|
11
|
-
colors: {
|
|
12
|
-
primary: '#6366f1',
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
plugins: [],
|
|
17
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vite'
|
|
2
|
-
import react from '@vitejs/plugin-react'
|
|
3
|
-
import path from 'path'
|
|
4
|
-
|
|
5
|
-
export default defineConfig({
|
|
6
|
-
plugins: [react()],
|
|
7
|
-
resolve: {
|
|
8
|
-
alias: {
|
|
9
|
-
'@chatbi-v/core': path.resolve(__dirname, '../../.chatbi/core'),
|
|
10
|
-
'@chatbi-v/plugin-theme-manager': path.resolve(__dirname, '../../.chatbi/plugins/theme-manager/dist/index.mjs'),
|
|
11
|
-
'@chatbi-v/plugin-system-user': path.resolve(__dirname, '../../.chatbi/plugins/system-user/dist/index.mjs'),
|
|
12
|
-
'@chatbi-v/plugin-system-monitor': path.resolve(__dirname, '../../.chatbi/plugins/system-monitor/dist/index.mjs'),
|
|
13
|
-
'@chatbi-v/plugin-demo-plugin': path.resolve(__dirname, '../../plugins/demo-plugin/src/index.tsx'),
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
})
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { Plugin, PluginContext, Slot } from '@chatbi-v/core'
|
|
3
|
-
import { MessageOutlined } from '@ant-design/icons'
|
|
4
|
-
|
|
5
|
-
export class {{className}} implements Plugin {
|
|
6
|
-
id = '{{pluginId}}'
|
|
7
|
-
metadata = {
|
|
8
|
-
id: '{{pluginId}}',
|
|
9
|
-
name: '{{pluginId}} Plugin',
|
|
10
|
-
version: '1.0.0',
|
|
11
|
-
type: '{{pluginType}}' as const,
|
|
12
|
-
routes: [
|
|
13
|
-
{
|
|
14
|
-
path: '/{{pluginId}}',
|
|
15
|
-
component: () => <div style=\{{ padding: '20px', background: '#f5f5f5', borderRadius: '8px' }}>
|
|
16
|
-
<h3>Hello from {{pluginId}} Plugin!</h3>
|
|
17
|
-
<p>This is a {{pluginType}} plugin generated by ChatBI CLI.</p>
|
|
18
|
-
</div>,
|
|
19
|
-
meta: {
|
|
20
|
-
title: '{{pluginId}}',
|
|
21
|
-
icon: 'MessageOutlined'
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
],
|
|
25
|
-
extensions: [
|
|
26
|
-
{
|
|
27
|
-
slot: Slot.Sidebar,
|
|
28
|
-
component: () => null,
|
|
29
|
-
order: 10,
|
|
30
|
-
meta: {
|
|
31
|
-
title: '{{pluginId}}',
|
|
32
|
-
icon: <MessageOutlined />,
|
|
33
|
-
path: '/{{pluginId}}'
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
]
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
onLoad(context: PluginContext) {
|
|
40
|
-
context.logger.info('{{className}} Loaded!')
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export default {{className}}
|
|
File without changes
|
|
File without changes
|