@zhin.js/client 1.0.0 → 1.0.2

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 (43) hide show
  1. package/README.md +334 -67
  2. package/app/index.html +4 -3
  3. package/app/postcss.config.js +5 -0
  4. package/app/src/components/ThemeToggle.tsx +21 -0
  5. package/app/src/hooks/useTheme.ts +17 -0
  6. package/app/src/layouts/dashboard.tsx +259 -0
  7. package/app/src/main.tsx +121 -0
  8. package/app/src/pages/dashboard-bots.tsx +198 -0
  9. package/app/src/pages/dashboard-home.tsx +301 -0
  10. package/app/src/pages/dashboard-logs.tsx +298 -0
  11. package/app/src/pages/dashboard-plugin-detail.tsx +360 -0
  12. package/app/src/pages/dashboard-plugins.tsx +166 -0
  13. package/app/src/style.css +1105 -0
  14. package/app/src/theme/index.ts +92 -0
  15. package/app/tailwind.config.js +70 -0
  16. package/app/tsconfig.json +5 -0
  17. package/dist/index.js +15 -3
  18. package/package.json +20 -7
  19. package/src/index.ts +19 -3
  20. package/src/router/index.tsx +55 -0
  21. package/src/store/index.ts +111 -0
  22. package/src/store/reducers/index.ts +16 -0
  23. package/src/store/reducers/route.ts +122 -0
  24. package/src/store/reducers/script.ts +103 -0
  25. package/src/store/reducers/ui.ts +31 -0
  26. package/src/types.ts +11 -17
  27. package/src/websocket/index.ts +193 -0
  28. package/src/websocket/useWebSocket.ts +42 -0
  29. package/app/components.d.ts +0 -33
  30. package/app/src/App.vue +0 -7
  31. package/app/src/main.ts +0 -127
  32. package/app/src/pages/$.vue +0 -899
  33. package/app/src/pages/404.vue +0 -11
  34. package/app/src/pages/contexts/overview.vue +0 -177
  35. package/app/src/pages/dashboard.vue +0 -323
  36. package/app/src/pages/plugins/installed.vue +0 -734
  37. package/app/src/pages/system/status.vue +0 -241
  38. package/app/src/services/api.ts +0 -155
  39. package/app/src/styles/README.md +0 -202
  40. package/app/src/styles/common.css +0 -0
  41. package/global.d.ts +0 -19
  42. package/src/router.ts +0 -44
  43. package/src/store.ts +0 -53
package/README.md CHANGED
@@ -1,99 +1,366 @@
1
- # @zhin.js/client
1
+ # Zhin Client - 动态页面路由系统
2
2
 
3
- 基于 Vue 3 PrimeVue Zhin 机器人 Web 客户端,提供现代化的 Web 管理界面。
3
+ 基于 React Router 7.0 的动态页面管理系统,支持在 `main.tsx` 中直接进行页面路由操作。
4
4
 
5
- ## 功能特性
5
+ ## 特性
6
6
 
7
- - 🎨 基于 Vue 3 和 PrimeVue 的现代界面
8
- - 📊 机器人状态监控和管理
9
- - 🔧 插件管理和配置
10
- - 📝 日志查看和分析
11
- - 🛠️ 开发工具和调试支持
12
- - 📱 响应式设计,支持移动端
13
-
14
- ## 技术栈
15
-
16
- - **前端框架**: Vue 3 + TypeScript
17
- - **UI 组件**: PrimeVue 4.x
18
- - **状态管理**: Pinia
19
- - **路由**: Vue Router
20
- - **构建工具**: Vite
21
- - **主题**: PrimeUI 主题系统
7
+ - 🌳 **树形路由结构** - 使用树形结构管理页面路由,支持任意深度的嵌套
8
+ - **动态页面管理** - 运行时添加、删除、更新页面
9
+ - **React Router 7.0** - 使用最新的 React Router
10
+ - **TypeScript 支持** - 完整的类型定义
11
+ - **WebSocket 集成** - 支持动态加载插件入口脚本
12
+ - **Redux 状态管理** - 集成 Redux 持久化
13
+ - ✅ **简单易用** - 在 `main.tsx` 中直接操作页面路由
22
14
 
23
15
  ## 安装
24
16
 
25
17
  ```bash
26
- npm install @zhin.js/client
18
+ pnpm add react-router@7.0.0 events @types/events
27
19
  ```
28
20
 
29
- ## 使用
21
+ ## 基本使用
22
+
23
+ ### 1. 设置页面路由
24
+
25
+ ```tsx
26
+ // main.tsx
27
+ import { addPage, DynamicRouter } from '@zhin.js/client'
30
28
 
31
- 这个包通常与 `@zhin.js/console` 插件一起使用:
29
+ // 导入图标
30
+ import { Home, LayoutDashboard } from 'lucide-react'
32
31
 
33
- ```javascript
34
- // 插件中
35
- import '@zhin.js/console' // 这会自动加载客户端
32
+ // 添加页面
33
+ addPage({
34
+ key: 'home',
35
+ path: '/',
36
+ title: '首页',
37
+ icon: <Home className="w-5 h-5" />,
38
+ element: <HomePage />
39
+ })
40
+
41
+ addPage({
42
+ key: 'dashboard',
43
+ path: '/dashboard',
44
+ title: '仪表盘',
45
+ icon: <LayoutDashboard className="w-5 h-5" />,
46
+ element: <DashboardPage />
47
+ })
48
+
49
+ // 渲染应用
50
+ createRoot(document.getElementById('root')).render(
51
+ <Provider store={store}>
52
+ <PersistGate loading={null} persistor={persistor}>
53
+ <DynamicRouter />
54
+ </PersistGate>
55
+ </Provider>
56
+ )
36
57
  ```
37
58
 
38
- ## 开发
59
+ ### 2. 页面操作
60
+
61
+ ```tsx
62
+ import { addPage, removePage, updatePage } from '@zhin.js/client'
63
+
64
+ import { Settings } from 'lucide-react'
39
65
 
40
- ### 项目结构
66
+ // 添加页面
67
+ addPage({
68
+ key: 'settings',
69
+ path: '/settings',
70
+ title: '设置',
71
+ icon: <Settings className="w-5 h-5" />,
72
+ element: <SettingsPage />
73
+ })
41
74
 
75
+ // 删除页面
76
+ removePage('/settings')
77
+
78
+ // 更新页面
79
+ updatePage('/settings', {
80
+ key: 'settings',
81
+ path: '/settings',
82
+ title: '设置(更新)',
83
+ icon: <Settings className="w-5 h-5" />,
84
+ element: <UpdatedSettingsPage />
85
+ })
86
+
87
+ // 向后兼容的旧 API(已废弃)
88
+ import { addRoute, removeRoute, updateRoute } from '@zhin.js/client'
89
+ // 这些 API 仍然可用,但推荐使用新的 addPage 等 API
42
90
  ```
43
- app/
44
- ├── src/
45
- │ ├── App.vue # 主应用组件
46
- │ ├── main.ts # 应用入口
47
- │ └── pages/ # 页面组件
48
- │ ├── $.vue # 动态路由
49
- │ ├── 404.vue # 404页面
50
- │ └── dashboard.vue # 仪表板
51
- ├── index.html # HTML模板
52
- └── components.d.ts # 组件类型声明
91
+
92
+ ### 3. 自动父路由查找
93
+
94
+ ```tsx
95
+ // main.tsx
96
+ import { addPage } from '@zhin.js/client'
97
+ import { Home, Users, Settings } from 'lucide-react'
98
+
99
+ // 1. 添加顶级页面
100
+ addPage({
101
+ key: 'home',
102
+ path: '/',
103
+ title: '首页',
104
+ icon: <Home className="w-5 h-5" />,
105
+ element: <HomePage />
106
+ })
107
+
108
+ addPage({
109
+ key: 'admin',
110
+ path: '/admin',
111
+ title: '管理',
112
+ element: <AdminLayout />
113
+ })
114
+
115
+ // 2. 自动查找父路由:/admin/users
116
+ // 会查找 /admin 是否存在,如果存在,插入 users 到 /admin
117
+ addPage({
118
+ key: 'admin-users',
119
+ path: '/admin/users',
120
+ title: '用户管理',
121
+ icon: <Users className="w-5 h-5" />,
122
+ element: <UsersPage />
123
+ })
124
+
125
+ addPage({
126
+ key: 'admin-settings',
127
+ path: '/admin/settings',
128
+ title: '系统设置',
129
+ icon: <Settings className="w-5 h-5" />,
130
+ element: <AdminSettingsPage />
131
+ })
132
+
133
+ // 3. 自动查找父路由:/admin/users/detail
134
+ // 会查找 /admin/users 是否存在,如果存在,插入 detail 到 /admin/users
135
+ addPage({
136
+ key: 'user-detail',
137
+ path: '/admin/users/detail',
138
+ title: '用户详情',
139
+ element: <UserDetailPage />
140
+ })
141
+
142
+ // 4. 动态添加嵌套页面
143
+ setTimeout(() => {
144
+ // 会自动查找 /admin 是否存在,如果存在,插入 analytics 到 /admin
145
+ addPage({
146
+ key: 'admin-analytics',
147
+ path: '/admin/analytics',
148
+ title: '分析',
149
+ element: <AnalyticsPage />
150
+ })
151
+ }, 2000)
152
+
153
+ // 5. 动态添加更深层嵌套
154
+ setTimeout(() => {
155
+ // 会自动查找 /admin/analytics 是否存在,如果存在,插入 reports 到 /admin/analytics
156
+ addPage({
157
+ key: 'analytics-reports',
158
+ path: '/admin/analytics/reports',
159
+ title: '分析报告',
160
+ element: <ReportsPage />
161
+ })
162
+ }, 4000)
53
163
  ```
54
164
 
55
- ### 开发命令
165
+ ### 4. 事件监听
56
166
 
57
- ```bash
58
- npm run build # 构建
59
- npm run clean # 清理构建文件
167
+ ```tsx
168
+ import { routerManager } from '@zhin.js/client'
169
+
170
+ // 监听路由变化
171
+ routerManager.onRouteChange(() => {
172
+ console.log('Routes changed')
173
+ })
174
+
175
+ // 监听路由添加
176
+ routerManager.onRouteAdd((route) => {
177
+ console.log('Route added:', route.path)
178
+ })
179
+
180
+ // 监听路由删除
181
+ routerManager.onRouteRemove((path) => {
182
+ console.log('Route removed:', path)
183
+ })
60
184
  ```
61
185
 
62
- ## API 集成
186
+ ## API 参考
63
187
 
64
- 客户端通过以下方式与后端通信:
65
- - 📡 WebSocket 实时通信
66
- - 🌐 REST API 调用
67
- - 📊 状态同步机制
188
+ ### 页面管理 API(推荐)
189
+
190
+ ```tsx
191
+ // 添加页面
192
+ addPage(route: RouteMenuItem): void
193
+
194
+ // 删除页面
195
+ removePage(path: string): void
196
+
197
+ // 更新页面
198
+ updatePage(path: string, updates: Partial<RouteMenuItem>): void
199
+
200
+ // 获取页面
201
+ getPage(path: string): RouteMenuItem | undefined
202
+
203
+ // 获取所有页面
204
+ getAllPages(): RouteMenuItem[]
205
+
206
+ // 清空所有页面
207
+ clearPages(): void
208
+ ```
68
209
 
69
- ## 路由配置
210
+ ### 旧 API(已废弃,保留向后兼容)
70
211
 
71
- - `/` - 仪表板首页
72
- - `/plugins` - 插件管理
73
- - `/logs` - 日志查看
74
- - `/settings` - 系统设置
75
- - `/404` - 错误页面
212
+ ```tsx
213
+ /** @deprecated 请使用 addPage */
214
+ addRoute(route: RouteMenuItem): void
76
215
 
77
- ## 依赖项
216
+ /** @deprecated 请使用 removePage */
217
+ removeRoute(path: string): void
78
218
 
79
- - `pinia` - 状态管理
80
- - `primevue` - UI组件库
81
- - `@primeuix/themes` - 主题系统
82
- - `vue-router` - 路由管理
219
+ /** @deprecated 请使用 updatePage */
220
+ updateRoute(path: string, route: RouteMenuItem): void
83
221
 
84
- ## 自定义扩展
222
+ /** @deprecated 请使用 getPage */
223
+ getRoute(path: string): RouteMenuItem | undefined
85
224
 
86
- 支持通过插件系统扩展:
87
- - 自定义页面组件
88
- - 自定义主题样式
89
- - 自定义功能模块
225
+ /** @deprecated 请使用 getAllPages */
226
+ getAllRoutes(): RouteMenuItem[]
227
+
228
+ /** @deprecated 请使用 clearPages */
229
+ clearRoutes(): void
230
+ ```
231
+
232
+ ### routerManager 对象
233
+
234
+ ```tsx
235
+ // 事件监听方法
236
+ routerManager.onRouteChange(callback: () => void): () => void
237
+ routerManager.onRouteAdd(callback: (route: RouteConfig) => void): () => void
238
+ routerManager.onRouteRemove(callback: (path: string) => void): () => void
239
+ routerManager.onRouteUpdate(callback: (path: string, route: RouteConfig) => void): () => void
240
+ routerManager.onRouteClear(callback: () => void): () => void
241
+ ```
242
+
243
+ ### RouteMenuItem 接口
244
+
245
+ ```tsx
246
+ interface RouteMenuItem {
247
+ key: string // 唯一标识
248
+ path: string // 路由路径
249
+ title: string // 页面标题
250
+ icon?: ReactNode // 图标元素(直接传入 React 元素,如 <Home className="w-5 h-5" />)
251
+ element?: ReactNode // React 组件
252
+ children?: RouteMenuItem[] // 子路由
253
+ meta?: {
254
+ order?: number // 排序
255
+ hideInMenu?: boolean // 是否在菜单中隐藏
256
+ requiresAuth?: boolean // 是否需要认证
257
+ [key: string]: any
258
+ }
259
+ }
260
+ ```
261
+
262
+ ## 高级用法
263
+
264
+ ### 动态页面操作
265
+
266
+ ```tsx
267
+ import { addPage, updatePage, removePage } from '@zhin.js/client'
268
+
269
+ // 运行时动态添加页面
270
+ setTimeout(() => {
271
+ addPage({
272
+ key: 'dynamic',
273
+ path: '/dynamic',
274
+ title: '动态页面',
275
+ element: <div>Dynamic Page</div>
276
+ })
277
+ }, 2000)
278
+
279
+ // 动态更新页面
280
+ setTimeout(() => {
281
+ updatePage('/dynamic', {
282
+ key: 'dynamic',
283
+ path: '/dynamic',
284
+ title: '动态页面(已更新)',
285
+ element: <div>Updated Page</div>
286
+ })
287
+ }, 4000)
288
+
289
+ // 动态删除页面
290
+ setTimeout(() => {
291
+ removePage('/dynamic')
292
+ }, 6000)
293
+ ```
294
+
295
+ ### WebSocket 动态加载
296
+
297
+ ```tsx
298
+ import { useWebSocket, addPage } from '@zhin.js/client'
299
+
300
+ function App() {
301
+ // 连接 WebSocket,接收动态入口脚本
302
+ const ws = useWebSocket({
303
+ onMessage: (message) => {
304
+ console.log('收到消息:', message)
305
+ }
306
+ })
307
+
308
+ return (
309
+ <div>
310
+ <p>WebSocket 状态: {ws.connected ? '已连接' : '未连接'}</p>
311
+ <p>已加载入口: {ws.entries.length}</p>
312
+ <DynamicRouter />
313
+ </div>
314
+ )
315
+ }
316
+
317
+ // 插件入口脚本示例(my-plugin-entry.ts)
318
+ import { addPage } from '@zhin.js/client'
319
+ import { Puzzle } from 'lucide-react'
320
+
321
+ addPage({
322
+ key: 'my-plugin',
323
+ path: '/my-plugin',
324
+ title: '我的插件',
325
+ icon: <Puzzle className="w-5 h-5" />,
326
+ element: <MyPluginPage />
327
+ })
328
+ ```
329
+
330
+ ### 事件统计
331
+
332
+ ```tsx
333
+ // 路由统计
334
+ let routeCount = 0
335
+ routerManager.onRouteAdd(() => {
336
+ routeCount++
337
+ console.log(`Total routes: ${routeCount}`)
338
+ })
339
+
340
+ routerManager.onRouteRemove(() => {
341
+ routeCount--
342
+ console.log(`Total routes: ${routeCount}`)
343
+ })
344
+ ```
345
+
346
+ ### 条件事件监听
347
+
348
+ ```tsx
349
+ // 只监听特定路径的路由变化
350
+ routerManager.onRouteAdd((route) => {
351
+ if (route.path.startsWith('/admin')) {
352
+ console.log('Admin route added:', route.path)
353
+ }
354
+ })
355
+ ```
90
356
 
91
- ## 浏览器支持
357
+ ## 注意事项
92
358
 
93
- - Chrome/Edge 88+
94
- - Firefox 85+
95
- - Safari 14+
359
+ 1. **路由路径唯一性** - 确保路由路径的唯一性,避免冲突
360
+ 2. **事件清理** - 记得清理事件监听器,避免内存泄漏
361
+ 3. **性能考虑** - 大量路由时考虑使用懒加载
362
+ 4. **类型安全** - 使用 TypeScript 确保类型安全
96
363
 
97
- ## 许可证
364
+ ## 示例项目
98
365
 
99
- MIT License
366
+ 查看 `app/src/main.tsx` 中的完整示例。
package/app/index.html CHANGED
@@ -2,11 +2,12 @@
2
2
  <html lang='en'>
3
3
  <head>
4
4
  <meta charset='UTF-8'>
5
- <meta name='viewport' content='width=device-width, initial-scale=1.0'>
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Zhin</title>
7
7
  </head>
8
8
  <body>
9
- <div id='app'></div>
10
- <script src='/src/main.ts' type='module'></script>
9
+ <noscript>You need to enable JavaScript to run this app.</noscript>
10
+ <div id="root"></div>
11
+ <script src='/src/main.tsx' type='module'></script>
11
12
  </body>
12
13
  </html>
@@ -0,0 +1,5 @@
1
+ export default {
2
+ plugins: {
3
+ "@tailwindcss/postcss": {},
4
+ },
5
+ };
@@ -0,0 +1,21 @@
1
+ import { useTheme } from '../hooks/useTheme'
2
+ import { Icons } from '@zhin.js/client'
3
+
4
+ export function ThemeToggle() {
5
+ const { theme, toggleTheme } = useTheme()
6
+
7
+ return (
8
+ <button
9
+ onClick={toggleTheme}
10
+ className="p-2 hover:bg-accent rounded-lg transition-colors text-foreground"
11
+ title={theme === 'light' ? '切换到暗色模式' : '切换到亮色模式'}
12
+ >
13
+ {theme === 'light' ? (
14
+ <Icons.Moon className="w-5 h-5" />
15
+ ) : (
16
+ <Icons.Sun className="w-5 h-5" />
17
+ )}
18
+ </button>
19
+ )
20
+ }
21
+
@@ -0,0 +1,17 @@
1
+ import { useState, useEffect } from 'react'
2
+ import { type Theme, applyTheme, getInitialTheme } from '../theme'
3
+
4
+ export function useTheme() {
5
+ const [theme, setTheme] = useState<Theme>(getInitialTheme)
6
+
7
+ useEffect(() => {
8
+ applyTheme(theme)
9
+ }, [theme])
10
+
11
+ const toggleTheme = () => {
12
+ setTheme(prev => prev === 'light' ? 'dark' : 'light')
13
+ }
14
+
15
+ return { theme, setTheme, toggleTheme }
16
+ }
17
+