@zhin.js/console 1.0.9 → 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/CHANGELOG.md +95 -0
- package/client/index.html +16 -0
- package/client/src/components/PluginConfigForm/BasicFieldRenderers.tsx +6 -7
- package/client/src/components/PluginConfigForm/CollectionFieldRenderers.tsx +8 -8
- package/client/src/components/PluginConfigForm/CompositeFieldRenderers.tsx +3 -3
- package/client/src/components/PluginConfigForm/index.tsx +8 -7
- package/client/src/components/ThemeToggle.tsx +3 -3
- package/client/src/layouts/dashboard.tsx +14 -15
- package/client/src/main.tsx +60 -59
- package/client/src/pages/dashboard-plugin-detail.tsx +17 -17
- package/client/src/pages/dashboard-plugins.tsx +8 -8
- package/client/tsconfig.json +5 -6
- package/dist/_commonjsHelpers-C6fGbg64.js +6 -0
- package/dist/client.js +9 -0
- package/dist/index.html +31 -0
- package/dist/index.js +15 -0
- package/dist/lucide-react.js +28876 -0
- package/dist/radix-ui-themes.js +9321 -0
- package/dist/radix-ui.js +11213 -0
- package/dist/react-dom-client.js +10042 -0
- package/dist/react-dom.js +180 -0
- package/dist/react-jsx-dev-runtime.js +51 -0
- package/dist/react-jsx-runtime.js +68 -0
- package/dist/react-router.js +8141 -0
- package/dist/react.js +421 -0
- package/dist/style.css +2 -0
- package/lib/bin.d.ts.map +1 -1
- package/lib/bin.js +2 -26
- package/lib/bin.js.map +1 -1
- package/lib/build.d.ts +2 -32
- package/lib/build.d.ts.map +1 -1
- package/lib/build.js +67 -144
- package/lib/build.js.map +1 -1
- package/lib/dev.d.ts.map +1 -1
- package/lib/dev.js +1 -1
- package/lib/dev.js.map +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +0 -1
- package/lib/index.js.map +1 -1
- package/lib/websocket.d.ts.map +1 -1
- package/lib/websocket.js.map +1 -1
- package/package.json +28 -12
- package/app/bin.ts +0 -52
- package/app/build.ts +0 -211
- package/app/dev.ts +0 -84
- package/app/index.ts +0 -193
- package/app/websocket.ts +0 -109
- package/client/public/vendor/react-dom.production.min.js +0 -1
- package/client/public/vendor/react.production.min.js +0 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# @zhin.js/console
|
|
2
|
+
|
|
3
|
+
## 1.0.10
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 547028f: fix: 优化包结构,优化客户端支持
|
|
8
|
+
- Updated dependencies [547028f]
|
|
9
|
+
- @zhin.js/types@1.0.5
|
|
10
|
+
- @zhin.js/core@1.0.14
|
|
11
|
+
- @zhin.js/http@1.0.7
|
|
12
|
+
|
|
13
|
+
## 1.0.9
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- 4034b94: fix: allow host
|
|
18
|
+
- Updated dependencies [a2e1ebc]
|
|
19
|
+
- @zhin.js/core@1.0.13
|
|
20
|
+
|
|
21
|
+
## 1.0.8
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- c1a539e: fix: cli 优化,console 优化
|
|
26
|
+
- Updated dependencies [c8c3996]
|
|
27
|
+
- @zhin.js/types@1.0.4
|
|
28
|
+
- @zhin.js/core@1.0.10
|
|
29
|
+
|
|
30
|
+
## 1.0.7
|
|
31
|
+
|
|
32
|
+
### Patch Changes
|
|
33
|
+
|
|
34
|
+
- c490260: fix: 更新脚手架结构,优化包依赖
|
|
35
|
+
- Updated dependencies [c490260]
|
|
36
|
+
- @zhin.js/client@1.0.5
|
|
37
|
+
- @zhin.js/core@1.0.9
|
|
38
|
+
- @zhin.js/http@1.0.6
|
|
39
|
+
|
|
40
|
+
## 1.0.6
|
|
41
|
+
|
|
42
|
+
### Patch Changes
|
|
43
|
+
|
|
44
|
+
- 551c4d2: fix: 插件支持配置文件读取,优化 test 用例
|
|
45
|
+
- Updated dependencies [551c4d2]
|
|
46
|
+
- @zhin.js/types@1.0.3
|
|
47
|
+
- @zhin.js/client@1.0.4
|
|
48
|
+
- @zhin.js/core@1.0.8
|
|
49
|
+
- @zhin.js/http@1.0.5
|
|
50
|
+
|
|
51
|
+
## 1.0.5
|
|
52
|
+
|
|
53
|
+
### Patch Changes
|
|
54
|
+
|
|
55
|
+
- 47845fb: fix: err
|
|
56
|
+
- Updated dependencies [47845fb]
|
|
57
|
+
- @zhin.js/core@1.0.7
|
|
58
|
+
|
|
59
|
+
## 1.0.4
|
|
60
|
+
|
|
61
|
+
### Patch Changes
|
|
62
|
+
|
|
63
|
+
- c2d9047: fix: 重复插件 bug
|
|
64
|
+
- Updated dependencies [c2d9047]
|
|
65
|
+
- Updated dependencies [c2d9047]
|
|
66
|
+
- Updated dependencies [b213bbc]
|
|
67
|
+
- @zhin.js/client@1.0.3
|
|
68
|
+
- @zhin.js/core@1.0.6
|
|
69
|
+
- @zhin.js/http@1.0.4
|
|
70
|
+
|
|
71
|
+
## 1.0.3
|
|
72
|
+
|
|
73
|
+
### Patch Changes
|
|
74
|
+
|
|
75
|
+
- 5e2bddc: fix: allow fs
|
|
76
|
+
|
|
77
|
+
## 1.0.2
|
|
78
|
+
|
|
79
|
+
### Patch Changes
|
|
80
|
+
|
|
81
|
+
- d291005: fix: 更新 cli,更新 http
|
|
82
|
+
- Updated dependencies [d291005]
|
|
83
|
+
- @zhin.js/client@1.0.2
|
|
84
|
+
- @zhin.js/http@1.0.2
|
|
85
|
+
|
|
86
|
+
## 1.0.1
|
|
87
|
+
|
|
88
|
+
### Patch Changes
|
|
89
|
+
|
|
90
|
+
- 727963c: fix: 修复 sqlite 数据错误;优化 console 展示
|
|
91
|
+
- Updated dependencies [727963c]
|
|
92
|
+
- Updated dependencies [89bc676]
|
|
93
|
+
- @zhin.js/client@1.0.1
|
|
94
|
+
- @zhin.js/types@1.0.2
|
|
95
|
+
- @zhin.js/core@1.0.3
|
package/client/index.html
CHANGED
|
@@ -4,6 +4,22 @@
|
|
|
4
4
|
<meta charset='UTF-8'>
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>Zhin</title>
|
|
7
|
+
<script type="importmap">
|
|
8
|
+
{
|
|
9
|
+
"imports": {
|
|
10
|
+
"react": "./react.js",
|
|
11
|
+
"react-dom": "./react-dom.js",
|
|
12
|
+
"react-dom/client": "./react-dom-client.js",
|
|
13
|
+
"react-router": "./react-router.js",
|
|
14
|
+
"react/jsx-runtime": "./react-jsx-runtime.js",
|
|
15
|
+
"react/jsx-dev-runtime": "./react-jsx-dev-runtime.js",
|
|
16
|
+
"lucide-react": "./lucide-react.js",
|
|
17
|
+
"radix-ui": "./radix-ui.js",
|
|
18
|
+
"@radix-ui/themes": "./radix-ui-themes.js",
|
|
19
|
+
"@zhin.js/client": "./client.js"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
</script>
|
|
7
23
|
</head>
|
|
8
24
|
<body>
|
|
9
25
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
@@ -4,9 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { Flex, Box, Text, TextField, TextArea, Switch, Select, Badge, Callout } from '@radix-ui/themes'
|
|
7
|
-
import { Icons } from '@zhin.js/client'
|
|
8
7
|
import type { FieldRendererProps } from './types.js'
|
|
9
|
-
|
|
8
|
+
import { Calendar, Info, Lock, Code } from 'lucide-react'
|
|
10
9
|
export function StringFieldRenderer({ field, value, onChange }: FieldRendererProps) {
|
|
11
10
|
// 枚举类型 - 下拉选择 - 优化样式
|
|
12
11
|
if (field.enum) {
|
|
@@ -153,7 +152,7 @@ export function DateFieldRenderer({ field, value, onChange }: FieldRendererProps
|
|
|
153
152
|
className="hover:border-blue-500 dark:hover:border-blue-400 transition-colors focus-within:ring-2 focus-within:ring-blue-500/20"
|
|
154
153
|
>
|
|
155
154
|
<TextField.Slot side="left">
|
|
156
|
-
<
|
|
155
|
+
<Calendar className="w-4 h-4 text-gray-500" />
|
|
157
156
|
</TextField.Slot>
|
|
158
157
|
</TextField.Root>
|
|
159
158
|
</div>
|
|
@@ -189,7 +188,7 @@ export function RegexpFieldRenderer({ field, value, onChange }: FieldRendererPro
|
|
|
189
188
|
</TextField.Slot>
|
|
190
189
|
</TextField.Root>
|
|
191
190
|
<Flex align="center" gap="2">
|
|
192
|
-
<
|
|
191
|
+
<Info className="w-3 h-3 text-amber-600 dark:text-amber-400" />
|
|
193
192
|
<Text size="1" className="text-amber-700 dark:text-amber-300">
|
|
194
193
|
输入正则表达式模式 (省略斜杠)
|
|
195
194
|
</Text>
|
|
@@ -205,7 +204,7 @@ export function ConstFieldRenderer({ field, value }: FieldRendererProps) {
|
|
|
205
204
|
return (
|
|
206
205
|
<div className="p-3 rounded-lg bg-gray-100 dark:bg-gray-900 border border-gray-300 dark:border-gray-700">
|
|
207
206
|
<Flex align="center" gap="3">
|
|
208
|
-
<
|
|
207
|
+
<Lock className="w-4 h-4 text-gray-500 dark:text-gray-400" />
|
|
209
208
|
<Badge variant="soft" size="2" className="font-mono">
|
|
210
209
|
{String(constValue)}
|
|
211
210
|
</Badge>
|
|
@@ -222,7 +221,7 @@ export function AnyFieldRenderer({ field, value, onChange }: FieldRendererProps)
|
|
|
222
221
|
<div className="p-3 rounded-lg bg-purple-50 dark:bg-purple-900/20 border border-purple-200 dark:border-purple-800">
|
|
223
222
|
<Flex direction="column" gap="3">
|
|
224
223
|
<Flex align="center" gap="2">
|
|
225
|
-
<
|
|
224
|
+
<Code className="w-4 h-4 text-purple-600 dark:text-purple-400" />
|
|
226
225
|
<Text size="1" weight="bold" className="text-purple-700 dark:text-purple-300">
|
|
227
226
|
JSON 格式输入
|
|
228
227
|
</Text>
|
|
@@ -242,7 +241,7 @@ export function AnyFieldRenderer({ field, value, onChange }: FieldRendererProps)
|
|
|
242
241
|
className="font-mono text-sm bg-white dark:bg-gray-950 hover:border-purple-500 dark:hover:border-purple-400 transition-colors"
|
|
243
242
|
/>
|
|
244
243
|
<Flex align="center" gap="2">
|
|
245
|
-
<
|
|
244
|
+
<Info className="w-3 h-3 text-purple-600 dark:text-purple-400" />
|
|
246
245
|
<Text size="1" className="text-purple-700 dark:text-purple-300">
|
|
247
246
|
支持: 字符串、数字、布尔值、对象、数组
|
|
248
247
|
</Text>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { Flex, Box, Text, TextArea, Button, Badge, Card, Separator } from '@radix-ui/themes'
|
|
7
|
-
import {
|
|
7
|
+
import { List, Trash2, Plus, Package, Code, Info } from 'lucide-react'
|
|
8
8
|
import type { FieldRendererProps, SchemaField } from './types.js'
|
|
9
9
|
|
|
10
10
|
interface CollectionFieldProps extends FieldRendererProps {
|
|
@@ -33,7 +33,7 @@ export function ListFieldRenderer({
|
|
|
33
33
|
<div className="p-3 rounded-lg bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800">
|
|
34
34
|
<Flex direction="column" gap="2">
|
|
35
35
|
<Flex align="center" gap="2">
|
|
36
|
-
<
|
|
36
|
+
<List className="w-4 h-4 text-green-600 dark:text-green-400" />
|
|
37
37
|
<Text size="1" weight="bold" className="text-green-700 dark:text-green-300">
|
|
38
38
|
列表输入 (每行一个值)
|
|
39
39
|
</Text>
|
|
@@ -85,7 +85,7 @@ export function ListFieldRenderer({
|
|
|
85
85
|
}}
|
|
86
86
|
className="opacity-0 group-hover:opacity-100 transition-opacity"
|
|
87
87
|
>
|
|
88
|
-
<
|
|
88
|
+
<Trash2 className="w-3 h-3" />
|
|
89
89
|
</Button>
|
|
90
90
|
</Flex>
|
|
91
91
|
<div className="pl-2 border-l-2 border-blue-200 dark:border-blue-800">
|
|
@@ -106,7 +106,7 @@ export function ListFieldRenderer({
|
|
|
106
106
|
}}
|
|
107
107
|
className="w-full hover:bg-blue-100 dark:hover:bg-blue-900/30 border-2 border-dashed border-blue-300 dark:border-blue-700 hover:border-blue-500 dark:hover:border-blue-500 transition-colors"
|
|
108
108
|
>
|
|
109
|
-
<
|
|
109
|
+
<Plus className="w-4 h-4" />
|
|
110
110
|
添加项
|
|
111
111
|
</Button>
|
|
112
112
|
</Flex>
|
|
@@ -119,7 +119,7 @@ export function ArrayFieldRenderer({ field, value, onChange }: FieldRendererProp
|
|
|
119
119
|
<div className="p-3 rounded-lg bg-cyan-50 dark:bg-cyan-900/20 border border-cyan-200 dark:border-cyan-800">
|
|
120
120
|
<Flex direction="column" gap="2">
|
|
121
121
|
<Flex align="center" gap="2">
|
|
122
|
-
<
|
|
122
|
+
<List className="w-4 h-4 text-cyan-600 dark:text-cyan-400" />
|
|
123
123
|
<Text size="1" weight="bold" className="text-cyan-700 dark:text-cyan-300">
|
|
124
124
|
数组输入 (每行一个值)
|
|
125
125
|
</Text>
|
|
@@ -189,7 +189,7 @@ export function ObjectFieldRenderer({
|
|
|
189
189
|
<div className="rounded-lg border-2 border-blue-200 dark:border-blue-800 bg-gradient-to-br from-blue-50/50 to-cyan-50/50 dark:from-blue-900/10 dark:to-cyan-900/10 overflow-hidden">
|
|
190
190
|
<div className="px-4 py-2 bg-blue-100 dark:bg-blue-900/30 border-b border-blue-200 dark:border-blue-800">
|
|
191
191
|
<Flex align="center" gap="2">
|
|
192
|
-
<
|
|
192
|
+
<Package className="w-4 h-4 text-blue-600 dark:text-blue-400" />
|
|
193
193
|
</Flex>
|
|
194
194
|
</div>
|
|
195
195
|
<div className="p-4 space-y-3">
|
|
@@ -232,7 +232,7 @@ export function DictFieldRenderer({ field, value, onChange }: FieldRendererProps
|
|
|
232
232
|
<div className="p-3 rounded-lg bg-violet-50 dark:bg-violet-900/20 border border-violet-200 dark:border-violet-800">
|
|
233
233
|
<Flex direction="column" gap="3">
|
|
234
234
|
<Flex align="center" gap="2">
|
|
235
|
-
<
|
|
235
|
+
<Code className="w-4 h-4 text-violet-600 dark:text-violet-400" />
|
|
236
236
|
</Flex>
|
|
237
237
|
<TextArea
|
|
238
238
|
size="2"
|
|
@@ -250,7 +250,7 @@ export function DictFieldRenderer({ field, value, onChange }: FieldRendererProps
|
|
|
250
250
|
className="font-mono text-sm bg-white dark:bg-gray-950 hover:border-violet-500 dark:hover:border-violet-400 transition-colors"
|
|
251
251
|
/>
|
|
252
252
|
<Flex align="center" gap="2">
|
|
253
|
-
<
|
|
253
|
+
<Info className="w-3 h-3 text-violet-600 dark:text-violet-400" />
|
|
254
254
|
<Text size="1" className="text-violet-700 dark:text-violet-300">
|
|
255
255
|
键值对格式: {"key": "value"}
|
|
256
256
|
</Text>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { Flex, Box, Text, TextField, Select, Card, Badge } from '@radix-ui/themes'
|
|
7
|
-
import {
|
|
7
|
+
import { GitBranch, Layers } from 'lucide-react'
|
|
8
8
|
import type { FieldRendererProps, SchemaField } from './types.js'
|
|
9
9
|
|
|
10
10
|
interface CompositeFieldProps extends FieldRendererProps {
|
|
@@ -38,7 +38,7 @@ export function UnionFieldRenderer({ field, value, onChange }: FieldRendererProp
|
|
|
38
38
|
<div className="p-3 rounded-lg bg-gradient-to-br from-pink-50 to-rose-50 dark:from-pink-900/20 dark:to-rose-900/20 border border-pink-200 dark:border-pink-800">
|
|
39
39
|
<Flex direction="column" gap="2">
|
|
40
40
|
<Flex align="center" gap="2">
|
|
41
|
-
<
|
|
41
|
+
<GitBranch className="w-4 h-4 text-pink-600 dark:text-pink-400" />
|
|
42
42
|
</Flex>
|
|
43
43
|
<Select.Root
|
|
44
44
|
size="2"
|
|
@@ -78,7 +78,7 @@ export function IntersectFieldRenderer({
|
|
|
78
78
|
<div className="rounded-lg border-2 border-teal-200 dark:border-teal-800 bg-gradient-to-br from-teal-50/50 to-emerald-50/50 dark:from-teal-900/10 dark:to-emerald-900/10 overflow-hidden">
|
|
79
79
|
<div className="px-4 py-2 bg-teal-100 dark:bg-teal-900/30 border-b border-teal-200 dark:border-teal-800">
|
|
80
80
|
<Flex align="center" gap="2">
|
|
81
|
-
<
|
|
81
|
+
<Layers className="w-4 h-4 text-teal-600 dark:text-teal-400" />
|
|
82
82
|
</Flex>
|
|
83
83
|
</div>
|
|
84
84
|
<div className="p-4 space-y-3">
|
|
@@ -18,8 +18,9 @@ import {
|
|
|
18
18
|
Card
|
|
19
19
|
} from '@radix-ui/themes'
|
|
20
20
|
import { Accordion } from 'radix-ui'
|
|
21
|
-
import {
|
|
21
|
+
import { useConfig } from '@zhin.js/client'
|
|
22
22
|
import type { PluginConfigFormProps, SchemaField, Schema } from './types.js'
|
|
23
|
+
import { Settings, ChevronDown, CheckCircle, AlertCircle, X, Save } from 'lucide-react'
|
|
23
24
|
import { FieldRenderer, isComplexField } from './FieldRenderer.js'
|
|
24
25
|
import { NestedFieldRenderer } from './NestedFieldRenderer.js'
|
|
25
26
|
|
|
@@ -128,13 +129,13 @@ export function PluginConfigForm({ pluginName, onSuccess }: Omit<PluginConfigFor
|
|
|
128
129
|
className="w-full p-3 hover:bg-gray-50 dark:hover:bg-gray-900/50 rounded-lg transition-colors"
|
|
129
130
|
>
|
|
130
131
|
<Flex align="center" gap="2">
|
|
131
|
-
<
|
|
132
|
+
<Settings className="w-5 h-5 text-blue-600 dark:text-blue-400" />
|
|
132
133
|
<Text size="3" weight="bold">插件配置</Text>
|
|
133
134
|
<Badge size="1" color="gray" variant="soft">
|
|
134
135
|
{Object.keys(fields).length} 项
|
|
135
136
|
</Badge>
|
|
136
137
|
</Flex>
|
|
137
|
-
<
|
|
138
|
+
<ChevronDown
|
|
138
139
|
className="w-5 h-5 text-gray-500 transition-transform duration-200 group-data-[state=open]:rotate-180"
|
|
139
140
|
/>
|
|
140
141
|
</Flex>
|
|
@@ -147,7 +148,7 @@ export function PluginConfigForm({ pluginName, onSuccess }: Omit<PluginConfigFor
|
|
|
147
148
|
{successMessage && (
|
|
148
149
|
<div className="mb-3 animate-in fade-in slide-in-from-top-2 duration-300">
|
|
149
150
|
<Callout.Root color="green" size="1" className="shadow-sm">
|
|
150
|
-
<Callout.Icon><
|
|
151
|
+
<Callout.Icon><CheckCircle /></Callout.Icon>
|
|
151
152
|
<Callout.Text className="font-medium">{successMessage}</Callout.Text>
|
|
152
153
|
</Callout.Root>
|
|
153
154
|
</div>
|
|
@@ -157,7 +158,7 @@ export function PluginConfigForm({ pluginName, onSuccess }: Omit<PluginConfigFor
|
|
|
157
158
|
{error && (
|
|
158
159
|
<div className="mb-3 animate-in fade-in slide-in-from-top-2 duration-300">
|
|
159
160
|
<Callout.Root color="red" size="1" className="shadow-sm">
|
|
160
|
-
<Callout.Icon><
|
|
161
|
+
<Callout.Icon><AlertCircle /></Callout.Icon>
|
|
161
162
|
<Callout.Text className="font-medium">{error}</Callout.Text>
|
|
162
163
|
</Callout.Root>
|
|
163
164
|
</div>
|
|
@@ -206,7 +207,7 @@ export function PluginConfigForm({ pluginName, onSuccess }: Omit<PluginConfigFor
|
|
|
206
207
|
disabled={loading}
|
|
207
208
|
className="hover:bg-gray-200 dark:hover:bg-gray-800 transition-colors"
|
|
208
209
|
>
|
|
209
|
-
<
|
|
210
|
+
<X className="w-4 h-4" />
|
|
210
211
|
取消
|
|
211
212
|
</Button>
|
|
212
213
|
<Button
|
|
@@ -222,7 +223,7 @@ export function PluginConfigForm({ pluginName, onSuccess }: Omit<PluginConfigFor
|
|
|
222
223
|
</>
|
|
223
224
|
) : (
|
|
224
225
|
<>
|
|
225
|
-
<
|
|
226
|
+
<Save className="w-4 h-4" />
|
|
226
227
|
<span>保存配置</span>
|
|
227
228
|
</>
|
|
228
229
|
)}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useTheme } from '../hooks/useTheme'
|
|
2
|
-
import {
|
|
2
|
+
import { Moon, Sun } from 'lucide-react'
|
|
3
3
|
|
|
4
4
|
export function ThemeToggle() {
|
|
5
5
|
const { theme, toggleTheme } = useTheme()
|
|
@@ -11,9 +11,9 @@ export function ThemeToggle() {
|
|
|
11
11
|
title={theme === 'light' ? '切换到暗色模式' : '切换到亮色模式'}
|
|
12
12
|
>
|
|
13
13
|
{theme === 'light' ? (
|
|
14
|
-
<
|
|
14
|
+
<Moon className="w-5 h-5" />
|
|
15
15
|
) : (
|
|
16
|
-
<
|
|
16
|
+
<Sun className="w-5 h-5" />
|
|
17
17
|
)}
|
|
18
18
|
</button>
|
|
19
19
|
)
|
|
@@ -2,7 +2,8 @@ import { Outlet, Link, useSelector, useDispatch, toggleSidebar, setActiveMenu, u
|
|
|
2
2
|
import React, { useMemo } from "react"
|
|
3
3
|
import { Avatar, DropdownMenu } from 'radix-ui'
|
|
4
4
|
import * as Themes from '@radix-ui/themes'
|
|
5
|
-
import {
|
|
5
|
+
import {Menu, Search,Bell,User,Users,BarChart3,HelpCircle,LogOut} from 'lucide-react'
|
|
6
|
+
import { cn } from "@zhin.js/client"
|
|
6
7
|
import { ThemeToggle } from "../components/ThemeToggle"
|
|
7
8
|
|
|
8
9
|
const { Box, Flex, Text, Heading, IconButton, Badge, TextField, ScrollArea, Container } = Themes
|
|
@@ -83,11 +84,9 @@ export default function DashboardLayout() {
|
|
|
83
84
|
onClick={() => dispatch(setActiveMenu(item.key))}
|
|
84
85
|
className={cn("menu-item", isActive && "active")}
|
|
85
86
|
>
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
</div>
|
|
90
|
-
)}
|
|
87
|
+
<div className="icon">
|
|
88
|
+
{item.icon}
|
|
89
|
+
</div>
|
|
91
90
|
{sidebarOpen && (
|
|
92
91
|
<div className="text">
|
|
93
92
|
<div className="title">{item.title}</div>
|
|
@@ -143,7 +142,7 @@ export default function DashboardLayout() {
|
|
|
143
142
|
onClick={() => dispatch(toggleSidebar())}
|
|
144
143
|
className="hover-lift rounded-xl"
|
|
145
144
|
>
|
|
146
|
-
<
|
|
145
|
+
<Menu className="w-5 h-5" />
|
|
147
146
|
</IconButton>
|
|
148
147
|
<Flex direction="column" gap="0">
|
|
149
148
|
<Heading size="3" className="text-gray-900 dark:text-gray-100">控制台</Heading>
|
|
@@ -154,7 +153,7 @@ export default function DashboardLayout() {
|
|
|
154
153
|
{/* 中间搜索栏 */}
|
|
155
154
|
<Flex className="hidden md:flex flex-1 max-w-xl mx-6">
|
|
156
155
|
<Box className="relative">
|
|
157
|
-
<
|
|
156
|
+
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400 dark:text-gray-500" />
|
|
158
157
|
<TextField.Root
|
|
159
158
|
placeholder="搜索功能、用户、设置..."
|
|
160
159
|
size="2"
|
|
@@ -175,7 +174,7 @@ export default function DashboardLayout() {
|
|
|
175
174
|
size="2"
|
|
176
175
|
className="hover-lift rounded-xl"
|
|
177
176
|
>
|
|
178
|
-
<
|
|
177
|
+
<Bell className="w-5 h-5" />
|
|
179
178
|
</IconButton>
|
|
180
179
|
<Badge
|
|
181
180
|
color="red"
|
|
@@ -221,24 +220,24 @@ export default function DashboardLayout() {
|
|
|
221
220
|
</Text>
|
|
222
221
|
</Box>
|
|
223
222
|
<DropdownMenu.Item>
|
|
224
|
-
<
|
|
223
|
+
<User className="mr-2 h-4 w-4" />
|
|
225
224
|
我的设置
|
|
226
225
|
</DropdownMenu.Item>
|
|
227
226
|
<DropdownMenu.Item>
|
|
228
|
-
<
|
|
227
|
+
<Users className="mr-2 h-4 w-4" />
|
|
229
228
|
团队设置
|
|
230
229
|
</DropdownMenu.Item>
|
|
231
230
|
<DropdownMenu.Item>
|
|
232
|
-
<
|
|
231
|
+
<BarChart3 className="mr-2 h-4 w-4" />
|
|
233
232
|
数据分析
|
|
234
233
|
</DropdownMenu.Item>
|
|
235
234
|
<DropdownMenu.Item>
|
|
236
|
-
<
|
|
235
|
+
<HelpCircle className="mr-2 h-4 w-4" />
|
|
237
236
|
帮助与反馈
|
|
238
237
|
</DropdownMenu.Item>
|
|
239
238
|
<DropdownMenu.Separator />
|
|
240
239
|
<DropdownMenu.Item color="red">
|
|
241
|
-
<
|
|
240
|
+
<LogOut className="mr-2 h-4 w-4" />
|
|
242
241
|
退出登录
|
|
243
242
|
</DropdownMenu.Item>
|
|
244
243
|
</DropdownMenu.Content>
|
|
@@ -250,7 +249,7 @@ export default function DashboardLayout() {
|
|
|
250
249
|
{/* 主内容区域 */}
|
|
251
250
|
<Flex className="flex-1 overflow-auto">
|
|
252
251
|
<Container size="4" p="6">
|
|
253
|
-
|
|
252
|
+
<Outlet />
|
|
254
253
|
</Container>
|
|
255
254
|
</Flex>
|
|
256
255
|
</Flex>
|
package/client/src/main.tsx
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { StrictMode, useEffect, useState } from 'react'
|
|
2
2
|
import { createRoot } from 'react-dom/client'
|
|
3
3
|
import { Provider as ReduxProvider } from 'react-redux'
|
|
4
|
-
import {
|
|
4
|
+
import {Home, Package, Bot, FileText} from 'lucide-react'
|
|
5
|
+
import { store, DynamicRouter, persistor, addPage, useSelector } from '@zhin.js/client'
|
|
5
6
|
import DashboardLayout from './layouts/dashboard'
|
|
6
7
|
import DashboardHome from './pages/dashboard-home'
|
|
7
8
|
import DashboardPlugins from './pages/dashboard-plugins'
|
|
@@ -17,80 +18,80 @@ import { initializeTheme } from './theme'
|
|
|
17
18
|
// Initialize theme on app load
|
|
18
19
|
initializeTheme()
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
// 路由配置
|
|
22
|
-
const routes = [
|
|
23
|
-
{
|
|
24
|
-
key: 'dashboard-layout',
|
|
25
|
-
path: '/',
|
|
26
|
-
title: 'Dashboard',
|
|
27
|
-
element: <DashboardLayout />,
|
|
28
|
-
redirect: '/dashboard',
|
|
29
|
-
meta: { order: 0 },
|
|
30
|
-
children: [
|
|
31
|
-
{
|
|
32
|
-
key: 'dashboard-home',
|
|
33
|
-
index: true,
|
|
34
|
-
path: '',
|
|
35
|
-
title: '系统概览',
|
|
36
|
-
icon: <Icons.Home className="w-5 h-5" />,
|
|
37
|
-
element: <DashboardHome />,
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
{
|
|
41
|
-
key: 'dashboard-plugins',
|
|
42
|
-
path: '/plugins',
|
|
43
|
-
title: '插件管理',
|
|
44
|
-
icon: <Icons.Package className="w-5 h-5" />,
|
|
45
|
-
element: <DashboardPlugins />,
|
|
46
|
-
meta: { order: 2 }
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
key: 'dashboard-plugin-detail',
|
|
50
|
-
title: '插件详情',
|
|
51
|
-
path: '/plugins/:name',
|
|
52
|
-
element: <DashboardPluginDetail />,
|
|
53
|
-
meta: { hideInMenu: true }
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
key: 'dashboard-bots',
|
|
57
|
-
path: '/bots',
|
|
58
|
-
title: '机器人',
|
|
59
|
-
icon: <Icons.Bot className="w-5 h-5" />,
|
|
60
|
-
element: <DashboardBots />,
|
|
61
|
-
meta: { order: 3 }
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
key: 'dashboard-logs',
|
|
65
|
-
path: '/logs',
|
|
66
|
-
title: '系统日志',
|
|
67
|
-
icon: <Icons.FileText className="w-5 h-5" />,
|
|
68
|
-
element: <DashboardLogs />,
|
|
69
|
-
meta: { order: 4 }
|
|
70
|
-
}
|
|
71
|
-
]
|
|
72
|
-
}
|
|
73
|
-
]
|
|
74
|
-
|
|
75
21
|
// 路由初始化组件
|
|
76
22
|
function RouteInitializer() {
|
|
77
23
|
const entries = useSelector(state => state.script.entries)
|
|
78
24
|
const loadedScripts = useSelector(state => state.script.loadedScripts)
|
|
79
|
-
const [
|
|
25
|
+
const [initialized, setInitialized] = useState(false)
|
|
80
26
|
|
|
81
27
|
useEffect(() => {
|
|
28
|
+
// 路由配置 - 使用 Component 属性而不是 element
|
|
29
|
+
const routes = [
|
|
30
|
+
{
|
|
31
|
+
key: 'dashboard-layout',
|
|
32
|
+
path: '/',
|
|
33
|
+
title: 'Dashboard',
|
|
34
|
+
element: <DashboardLayout/>,
|
|
35
|
+
redirect: '/dashboard',
|
|
36
|
+
meta: { order: 0 },
|
|
37
|
+
children: [
|
|
38
|
+
{
|
|
39
|
+
key: 'dashboard-home',
|
|
40
|
+
index: true,
|
|
41
|
+
path: '',
|
|
42
|
+
title: '系统概览',
|
|
43
|
+
// Icon 仍然作为数据存储,不是在渲染上下文中使用
|
|
44
|
+
icon: <Home className="w-5 h-5" />,
|
|
45
|
+
element: <DashboardHome/>,
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
{
|
|
49
|
+
key: 'dashboard-plugins',
|
|
50
|
+
path: '/plugins',
|
|
51
|
+
title: '插件管理',
|
|
52
|
+
icon: <Package className="w-5 h-5" />,
|
|
53
|
+
element: <DashboardPlugins/>,
|
|
54
|
+
meta: { order: 2 }
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
key: 'dashboard-plugin-detail',
|
|
58
|
+
title: '插件详情',
|
|
59
|
+
path: '/plugins/:name',
|
|
60
|
+
element: <DashboardPluginDetail/>,
|
|
61
|
+
meta: { hideInMenu: true }
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
key: 'dashboard-bots',
|
|
65
|
+
path: '/bots',
|
|
66
|
+
title: '机器人',
|
|
67
|
+
icon: <Bot className="w-5 h-5" />,
|
|
68
|
+
element: <DashboardBots/>,
|
|
69
|
+
meta: { order: 3 }
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
key: 'dashboard-logs',
|
|
73
|
+
path: '/logs',
|
|
74
|
+
title: '系统日志',
|
|
75
|
+
icon: <FileText className="w-5 h-5" />,
|
|
76
|
+
element: <DashboardLogs/>,
|
|
77
|
+
meta: { order: 4 }
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
|
|
82
83
|
// 添加静态路由
|
|
83
84
|
routes.forEach(route => {
|
|
84
85
|
addPage(route)
|
|
85
86
|
})
|
|
86
|
-
|
|
87
|
+
setInitialized(true)
|
|
87
88
|
}, [])
|
|
88
89
|
|
|
89
90
|
// 检查是否所有脚本都已加载
|
|
90
91
|
const allScriptsLoaded = entries.length === 0 || entries.length === loadedScripts.length
|
|
91
92
|
|
|
92
93
|
// 等待静态路由和动态脚本都加载完成
|
|
93
|
-
if (!
|
|
94
|
+
if (!initialized || !allScriptsLoaded) {
|
|
94
95
|
return (
|
|
95
96
|
<div className="flex items-center justify-center h-screen">
|
|
96
97
|
<div className="text-center">
|