@zhin.js/client 1.0.11 → 1.0.13

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 (42) hide show
  1. package/README.md +5 -0
  2. package/client/index.ts +3 -0
  3. package/client/mediaSrc.ts +51 -0
  4. package/client/store/reducers/route.ts +4 -0
  5. package/client/types.ts +2 -1
  6. package/client/websocket/hooks.ts +217 -1
  7. package/client/websocket/index.ts +3 -1
  8. package/client/websocket/manager.ts +70 -1
  9. package/client/websocket/messageHandler.ts +9 -0
  10. package/client/websocket/types.ts +40 -0
  11. package/dist/index.d.ts +1 -0
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +2 -0
  14. package/dist/index.js.map +1 -1
  15. package/dist/mediaSrc.d.ts +16 -0
  16. package/dist/mediaSrc.d.ts.map +1 -0
  17. package/dist/mediaSrc.js +42 -0
  18. package/dist/mediaSrc.js.map +1 -0
  19. package/dist/store/reducers/route.d.ts +4 -0
  20. package/dist/store/reducers/route.d.ts.map +1 -1
  21. package/dist/store/reducers/route.js.map +1 -1
  22. package/dist/types.d.ts +2 -1
  23. package/dist/types.d.ts.map +1 -1
  24. package/dist/websocket/hooks.d.ts +48 -1
  25. package/dist/websocket/hooks.d.ts.map +1 -1
  26. package/dist/websocket/hooks.js +210 -0
  27. package/dist/websocket/hooks.js.map +1 -1
  28. package/dist/websocket/index.d.ts +1 -1
  29. package/dist/websocket/index.d.ts.map +1 -1
  30. package/dist/websocket/index.js +1 -1
  31. package/dist/websocket/index.js.map +1 -1
  32. package/dist/websocket/manager.d.ts +44 -1
  33. package/dist/websocket/manager.d.ts.map +1 -1
  34. package/dist/websocket/manager.js +48 -0
  35. package/dist/websocket/manager.js.map +1 -1
  36. package/dist/websocket/messageHandler.d.ts.map +1 -1
  37. package/dist/websocket/messageHandler.js +7 -0
  38. package/dist/websocket/messageHandler.js.map +1 -1
  39. package/dist/websocket/types.d.ts +31 -0
  40. package/dist/websocket/types.d.ts.map +1 -1
  41. package/dist/websocket/types.js.map +1 -1
  42. package/package.json +2 -2
package/README.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Zhin Client - 动态页面路由与插件配置系统
2
2
 
3
+ > **本仓库目录约定(与本包对应)**
4
+ > - **`client/`**:浏览器端源码(路由、Redux、WebSocket 等)。
5
+ > - **`dist/`**:`pnpm build` 后的发布产物;`package.json` 的 `main`/`types` 指向此处。
6
+ > 包根目录 `packages/client/` 表示 npm 包 `@zhin.js/client`,内层 `client/` 表示「Web 客户端实现」,与 [仓库结构与模块化约定](../../docs/contributing/repo-structure.md) 中 §3.4 一致。
7
+
3
8
  基于 React Router 7.0 的动态页面管理系统,集成插件配置功能,支持基于 Schema 的自动表单生成。
4
9
 
5
10
  ## 特性
package/client/index.ts CHANGED
@@ -3,6 +3,9 @@ import { twMerge } from 'tailwind-merge'
3
3
  // Types
4
4
  export * from './types'
5
5
 
6
+ // 媒体 URL(含 base64://)解析,供控制台 / 沙盒等
7
+ export { resolveMediaSrc, pickMediaRawUrl, type MediaKind } from './mediaSrc'
8
+
6
9
  // Redux Store
7
10
  export * from './store'
8
11
 
@@ -0,0 +1,51 @@
1
+ /** 用于 img / video / audio 的 src 解析时的媒体类别 */
2
+ export type MediaKind = 'image' | 'video' | 'audio'
3
+
4
+ const BASE64_PROTO = 'base64://'
5
+
6
+ /**
7
+ * 将消息段中的 url/file 等转为浏览器可用的媒体地址。
8
+ *
9
+ * 支持:
10
+ * - `http(s)://`、`blob:`、`data:` → 原样返回
11
+ * - `base64://<纯 base64>` → `data:{默认MIME};base64,<payload>`(默认按 kind:图 png / 视频 mp4 / 音频 mpeg)
12
+ * - `base64://image/png;base64,xxxx` → `data:image/png;base64,xxxx`
13
+ *
14
+ * 与群内日报、html-test 等插件生成的 `base64://${buffer.toString('base64')}` 一致。
15
+ */
16
+ export function resolveMediaSrc(
17
+ raw: string | undefined | null,
18
+ kind: MediaKind = 'image',
19
+ ): string | undefined {
20
+ if (raw == null || typeof raw !== 'string') return undefined
21
+ const s = raw.trim()
22
+ if (!s) return undefined
23
+
24
+ if (s.startsWith('data:') || s.startsWith('blob:') || s.startsWith('http://') || s.startsWith('https://')) {
25
+ return s
26
+ }
27
+
28
+ if (!s.startsWith(BASE64_PROTO)) {
29
+ return s
30
+ }
31
+
32
+ const payload = s.slice(BASE64_PROTO.length).replace(/^\s+/, '')
33
+ if (!payload) return undefined
34
+
35
+ // 已是 type/subtype;base64, 片段(不含 data: 前缀)
36
+ if (/^[\w+.-]+\/[\w+.-]+;base64,/i.test(payload)) {
37
+ return `data:${payload}`
38
+ }
39
+
40
+ const defaultMime =
41
+ kind === 'image' ? 'image/png' : kind === 'video' ? 'video/mp4' : 'audio/mpeg'
42
+ const b64 = payload.replace(/\s/g, '')
43
+ return `data:${defaultMime};base64,${b64}`
44
+ }
45
+
46
+ /** 从 segment.data 取常见媒体字段 */
47
+ export function pickMediaRawUrl(data: Record<string, unknown> | undefined): string | undefined {
48
+ if (!data) return undefined
49
+ const v = data.url ?? data.file ?? data.src ?? data.href
50
+ return typeof v === 'string' && v.trim() ? v.trim() : undefined
51
+ }
@@ -15,6 +15,10 @@ export interface RouteMenuItem {
15
15
  hideInMenu?: boolean
16
16
  requiresAuth?: boolean
17
17
  order?: number
18
+ /** 侧栏分组标签,同组内按 order 排序 */
19
+ group?: string
20
+ /** 主内容区全宽(无 max-w-7xl) */
21
+ fullWidth?: boolean
18
22
  }
19
23
  }
20
24
 
package/client/types.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  // 消息段类型定义 - 客户端版本
2
2
  export interface MessageSegment {
3
- type: 'text' | 'image' | 'at' | 'face' | 'video' | 'audio' | 'file' | 'reply'
3
+ /** record:如 ICQQ 语音等,展示时按音频处理 */
4
+ type: 'text' | 'image' | 'at' | 'face' | 'video' | 'audio' | 'record' | 'file' | 'reply'
4
5
  data: Record<string, any>
5
6
  }
6
7
 
@@ -20,7 +20,7 @@ import {
20
20
  updateSchema
21
21
  } from '../store'
22
22
  import { getWebSocketManager } from './instance'
23
- import type { UseConfigOptions, UseWebSocketOptions } from './types'
23
+ import type { UseConfigOptions, UseWebSocketOptions, FileTreeNode, DatabaseInfo, TableInfo, SelectResult, KvEntry, DatabaseType } from './types'
24
24
 
25
25
  // ============================================================================
26
26
  // WebSocket 连接 Hook
@@ -363,3 +363,219 @@ export function useEnvFiles() {
363
363
  files, loading, error, listFiles, getFile, saveFile
364
364
  }), [files, loading, error, listFiles, getFile, saveFile])
365
365
  }
366
+
367
+ // ============================================================================
368
+ // 文件管理 Hook
369
+ // ============================================================================
370
+
371
+ export function useFiles() {
372
+ const wsManager = getWebSocketManager()
373
+ const connected = useSelector(selectConfigConnected)
374
+
375
+ const [tree, setTree] = useState<FileTreeNode[]>([])
376
+ const [loading, setLoadingState] = useState(false)
377
+ const [error, setErrorState] = useState<string | null>(null)
378
+
379
+ const loadTree = useCallback(async () => {
380
+ setLoadingState(true)
381
+ setErrorState(null)
382
+ try {
383
+ const result = await wsManager.getFileTree()
384
+ setTree(result.tree)
385
+ return result.tree
386
+ } catch (err) {
387
+ const msg = err instanceof Error ? err.message : 'Unknown error'
388
+ setErrorState(msg)
389
+ throw err
390
+ } finally {
391
+ setLoadingState(false)
392
+ }
393
+ }, [wsManager])
394
+
395
+ const readFile = useCallback(async (filePath: string) => {
396
+ try {
397
+ const result = await wsManager.readFile(filePath)
398
+ return result.content
399
+ } catch (err) {
400
+ const msg = err instanceof Error ? err.message : 'Unknown error'
401
+ setErrorState(msg)
402
+ throw err
403
+ }
404
+ }, [wsManager])
405
+
406
+ const saveFile = useCallback(async (filePath: string, content: string) => {
407
+ setLoadingState(true)
408
+ setErrorState(null)
409
+ try {
410
+ return await wsManager.saveFile(filePath, content)
411
+ } catch (err) {
412
+ const msg = err instanceof Error ? err.message : 'Unknown error'
413
+ setErrorState(msg)
414
+ throw err
415
+ } finally {
416
+ setLoadingState(false)
417
+ }
418
+ }, [wsManager])
419
+
420
+ useEffect(() => {
421
+ if (connected && tree.length === 0 && !loading) {
422
+ loadTree().catch(() => {})
423
+ }
424
+ }, [connected, tree.length, loading, loadTree])
425
+
426
+ return useMemo(() => ({
427
+ tree, loading, error, loadTree, readFile, saveFile
428
+ }), [tree, loading, error, loadTree, readFile, saveFile])
429
+ }
430
+
431
+ // ============================================================================
432
+ // 数据库管理 Hook
433
+ // ============================================================================
434
+
435
+ export function useDatabase() {
436
+ const wsManager = getWebSocketManager()
437
+ const connected = useSelector(selectConfigConnected)
438
+
439
+ const [info, setInfo] = useState<DatabaseInfo | null>(null)
440
+ const [tables, setTables] = useState<TableInfo[]>([])
441
+ const [loading, setLoadingState] = useState(false)
442
+ const [error, setErrorState] = useState<string | null>(null)
443
+
444
+ const loadInfo = useCallback(async () => {
445
+ setLoadingState(true)
446
+ setErrorState(null)
447
+ try {
448
+ const result = await wsManager.getDbInfo()
449
+ setInfo(result)
450
+ return result
451
+ } catch (err) {
452
+ const msg = err instanceof Error ? err.message : 'Unknown error'
453
+ setErrorState(msg)
454
+ throw err
455
+ } finally {
456
+ setLoadingState(false)
457
+ }
458
+ }, [wsManager])
459
+
460
+ const loadTables = useCallback(async () => {
461
+ setLoadingState(true)
462
+ setErrorState(null)
463
+ try {
464
+ const result = await wsManager.getDbTables()
465
+ setTables(result.tables)
466
+ return result.tables
467
+ } catch (err) {
468
+ const msg = err instanceof Error ? err.message : 'Unknown error'
469
+ setErrorState(msg)
470
+ throw err
471
+ } finally {
472
+ setLoadingState(false)
473
+ }
474
+ }, [wsManager])
475
+
476
+ const select = useCallback(async (table: string, page?: number, pageSize?: number, where?: any) => {
477
+ try {
478
+ return await wsManager.dbSelect(table, page, pageSize, where)
479
+ } catch (err) {
480
+ const msg = err instanceof Error ? err.message : 'Unknown error'
481
+ setErrorState(msg)
482
+ throw err
483
+ }
484
+ }, [wsManager])
485
+
486
+ const insert = useCallback(async (table: string, row: any) => {
487
+ try {
488
+ return await wsManager.dbInsert(table, row)
489
+ } catch (err) {
490
+ const msg = err instanceof Error ? err.message : 'Unknown error'
491
+ setErrorState(msg)
492
+ throw err
493
+ }
494
+ }, [wsManager])
495
+
496
+ const update = useCallback(async (table: string, row: any, where: any) => {
497
+ try {
498
+ return await wsManager.dbUpdate(table, row, where)
499
+ } catch (err) {
500
+ const msg = err instanceof Error ? err.message : 'Unknown error'
501
+ setErrorState(msg)
502
+ throw err
503
+ }
504
+ }, [wsManager])
505
+
506
+ const remove = useCallback(async (table: string, where: any) => {
507
+ try {
508
+ return await wsManager.dbDelete(table, where)
509
+ } catch (err) {
510
+ const msg = err instanceof Error ? err.message : 'Unknown error'
511
+ setErrorState(msg)
512
+ throw err
513
+ }
514
+ }, [wsManager])
515
+
516
+ const dropTable = useCallback(async (table: string) => {
517
+ try {
518
+ const result = await wsManager.dbDropTable(table)
519
+ await loadTables()
520
+ return result
521
+ } catch (err) {
522
+ const msg = err instanceof Error ? err.message : 'Unknown error'
523
+ setErrorState(msg)
524
+ throw err
525
+ }
526
+ }, [wsManager, loadTables])
527
+
528
+ const kvGet = useCallback(async (table: string, key: string) => {
529
+ try {
530
+ return await wsManager.kvGet(table, key)
531
+ } catch (err) {
532
+ const msg = err instanceof Error ? err.message : 'Unknown error'
533
+ setErrorState(msg)
534
+ throw err
535
+ }
536
+ }, [wsManager])
537
+
538
+ const kvSet = useCallback(async (table: string, key: string, value: any, ttl?: number) => {
539
+ try {
540
+ return await wsManager.kvSet(table, key, value, ttl)
541
+ } catch (err) {
542
+ const msg = err instanceof Error ? err.message : 'Unknown error'
543
+ setErrorState(msg)
544
+ throw err
545
+ }
546
+ }, [wsManager])
547
+
548
+ const kvDelete = useCallback(async (table: string, key: string) => {
549
+ try {
550
+ return await wsManager.kvDelete(table, key)
551
+ } catch (err) {
552
+ const msg = err instanceof Error ? err.message : 'Unknown error'
553
+ setErrorState(msg)
554
+ throw err
555
+ }
556
+ }, [wsManager])
557
+
558
+ const kvEntries = useCallback(async (table: string) => {
559
+ try {
560
+ return await wsManager.kvGetEntries(table)
561
+ } catch (err) {
562
+ const msg = err instanceof Error ? err.message : 'Unknown error'
563
+ setErrorState(msg)
564
+ throw err
565
+ }
566
+ }, [wsManager])
567
+
568
+ useEffect(() => {
569
+ if (connected && !info && !loading) {
570
+ loadInfo().catch(() => {})
571
+ loadTables().catch(() => {})
572
+ }
573
+ }, [connected, info, loading, loadInfo, loadTables])
574
+
575
+ return useMemo(() => ({
576
+ info, tables, loading, error,
577
+ loadInfo, loadTables, dropTable,
578
+ select, insert, update, remove,
579
+ kvGet, kvSet, kvDelete, kvEntries,
580
+ }), [info, tables, loading, error, loadInfo, loadTables, dropTable, select, insert, update, remove, kvGet, kvSet, kvDelete, kvEntries])
581
+ }
@@ -31,7 +31,9 @@ export {
31
31
  useConfig,
32
32
  useAllConfigs,
33
33
  useConfigYaml,
34
- useEnvFiles
34
+ useEnvFiles,
35
+ useFiles,
36
+ useDatabase
35
37
  } from './hooks'
36
38
 
37
39
  // ============================================================================
@@ -8,7 +8,12 @@ import { MessageHandler } from './messageHandler'
8
8
  import type {
9
9
  WebSocketMessage,
10
10
  WebSocketConfig,
11
- WebSocketCallbacks
11
+ WebSocketCallbacks,
12
+ FileTreeNode,
13
+ DatabaseInfo,
14
+ TableInfo,
15
+ SelectResult,
16
+ KvEntry
12
17
  } from './types'
13
18
  import {
14
19
  ConnectionState,
@@ -233,6 +238,70 @@ export class WebSocketManager {
233
238
  return this.sendRequest({ type: 'env:save', filename, content })
234
239
  }
235
240
 
241
+ // ============================================================================
242
+ // 文件管理
243
+ // ============================================================================
244
+
245
+ async getFileTree(): Promise<{ tree: FileTreeNode[] }> {
246
+ return this.sendRequest({ type: 'files:tree' })
247
+ }
248
+
249
+ async readFile(filePath: string): Promise<{ content: string; size: number }> {
250
+ return this.sendRequest({ type: 'files:read', filePath })
251
+ }
252
+
253
+ async saveFile(filePath: string, content: string): Promise<{ success: boolean; message?: string }> {
254
+ return this.sendRequest({ type: 'files:save', filePath, content })
255
+ }
256
+
257
+ // ============================================================================
258
+ // 数据库管理
259
+ // ============================================================================
260
+
261
+ async getDbInfo(): Promise<DatabaseInfo> {
262
+ return this.sendRequest({ type: 'db:info' })
263
+ }
264
+
265
+ async getDbTables(): Promise<{ tables: TableInfo[] }> {
266
+ return this.sendRequest({ type: 'db:tables' })
267
+ }
268
+
269
+ async dbSelect(table: string, page?: number, pageSize?: number, where?: any): Promise<SelectResult> {
270
+ return this.sendRequest({ type: 'db:select', table, page, pageSize, where })
271
+ }
272
+
273
+ async dbInsert(table: string, row: any): Promise<{ success: boolean }> {
274
+ return this.sendRequest({ type: 'db:insert', table, row })
275
+ }
276
+
277
+ async dbUpdate(table: string, row: any, where: any): Promise<{ success: boolean; affected: number }> {
278
+ return this.sendRequest({ type: 'db:update', table, row, where })
279
+ }
280
+
281
+ async dbDelete(table: string, where: any): Promise<{ success: boolean; deleted: number }> {
282
+ return this.sendRequest({ type: 'db:delete', table, where })
283
+ }
284
+
285
+ async dbDropTable(table: string): Promise<{ success: boolean }> {
286
+ return this.sendRequest({ type: 'db:drop-table', table })
287
+ }
288
+
289
+ async kvGet(table: string, key: string): Promise<{ key: string; value: any }> {
290
+ return this.sendRequest({ type: 'db:kv:get', table, key })
291
+ }
292
+
293
+ async kvSet(table: string, key: string, value: any, ttl?: number): Promise<{ success: boolean }> {
294
+ return this.sendRequest({ type: 'db:kv:set', table, key, value, ttl })
295
+ }
296
+
297
+ async kvDelete(table: string, key: string): Promise<{ success: boolean }> {
298
+ return this.sendRequest({ type: 'db:kv:delete', table, key })
299
+ }
300
+
301
+ async kvGetEntries(table: string): Promise<{ entries: KvEntry[] }> {
302
+ return this.sendRequest({ type: 'db:kv:entries', table })
303
+ }
304
+
236
305
  // ============================================================================
237
306
  // 私有方法
238
307
  // ============================================================================
@@ -25,6 +25,15 @@ export class MessageHandler {
25
25
  */
26
26
  static handle(message: WebSocketMessage): void {
27
27
  try {
28
+ const t = (message as { type: string }).type
29
+ if (t === 'bot:request' || t === 'bot:notice' || t === 'bot:message') {
30
+ if (typeof window !== 'undefined') {
31
+ window.dispatchEvent(
32
+ new CustomEvent('zhin-console-bot-push', { detail: message })
33
+ )
34
+ }
35
+ return
36
+ }
28
37
  switch (message.type) {
29
38
  // 脚本管理相关消息
30
39
  case 'sync':
@@ -106,6 +106,46 @@ export interface HmrReloadMessage extends BaseMessage {
106
106
  data?: { file?: string }
107
107
  }
108
108
 
109
+ // ============================================================================
110
+ // 文件管理类型
111
+ // ============================================================================
112
+
113
+ export interface FileTreeNode {
114
+ name: string
115
+ path: string
116
+ type: 'file' | 'directory'
117
+ children?: FileTreeNode[]
118
+ }
119
+
120
+ // ============================================================================
121
+ // 数据库管理类型
122
+ // ============================================================================
123
+
124
+ export type DatabaseType = 'related' | 'document' | 'keyvalue'
125
+
126
+ export interface DatabaseInfo {
127
+ dialect: string
128
+ type: DatabaseType
129
+ tables: string[]
130
+ }
131
+
132
+ export interface TableInfo {
133
+ name: string
134
+ columns?: Record<string, { type: string; primary?: boolean; nullable?: boolean; default?: any }>
135
+ }
136
+
137
+ export interface SelectResult {
138
+ rows: any[]
139
+ total: number
140
+ page: number
141
+ pageSize: number
142
+ }
143
+
144
+ export interface KvEntry {
145
+ key: string
146
+ value: any
147
+ }
148
+
109
149
  // ============================================================================
110
150
  // 联合类型
111
151
  // ============================================================================
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { type ClassValue } from 'clsx';
2
2
  export * from './types';
3
+ export { resolveMediaSrc, pickMediaRawUrl, type MediaKind } from './mediaSrc';
3
4
  export * from './store';
4
5
  export * from './router';
5
6
  export * from './websocket';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAA;AAG5C,cAAc,SAAS,CAAA;AAGvB,cAAc,SAAS,CAAA;AAGvB,cAAc,UAAU,CAAA;AAGxB,cAAc,aAAa,CAAA;AAE3B,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAA;AAG5C,cAAc,SAAS,CAAA;AAGvB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AAG7E,cAAc,SAAS,CAAA;AAGvB,cAAc,UAAU,CAAA;AAGxB,cAAc,aAAa,CAAA;AAE3B,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC"}
package/dist/index.js CHANGED
@@ -2,6 +2,8 @@ import { clsx } from 'clsx';
2
2
  import { twMerge } from 'tailwind-merge';
3
3
  // Types
4
4
  export * from './types';
5
+ // 媒体 URL(含 base64://)解析,供控制台 / 沙盒等
6
+ export { resolveMediaSrc, pickMediaRawUrl } from './mediaSrc';
5
7
  // Redux Store
6
8
  export * from './store';
7
9
  // Router
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,IAAI,EAAE,MAAM,MAAM,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AACxC,QAAQ;AACR,cAAc,SAAS,CAAA;AAEvB,cAAc;AACd,cAAc,SAAS,CAAA;AAEvB,SAAS;AACT,cAAc,UAAU,CAAA;AAExB,YAAY;AACZ,cAAc,aAAa,CAAA;AAE3B,MAAM,UAAU,EAAE,CAAC,GAAG,MAAoB;IACxC,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;AAC9B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,IAAI,EAAE,MAAM,MAAM,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AACxC,QAAQ;AACR,cAAc,SAAS,CAAA;AAEvB,mCAAmC;AACnC,OAAO,EAAE,eAAe,EAAE,eAAe,EAAkB,MAAM,YAAY,CAAA;AAE7E,cAAc;AACd,cAAc,SAAS,CAAA;AAEvB,SAAS;AACT,cAAc,UAAU,CAAA;AAExB,YAAY;AACZ,cAAc,aAAa,CAAA;AAE3B,MAAM,UAAU,EAAE,CAAC,GAAG,MAAoB;IACxC,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;AAC9B,CAAC"}
@@ -0,0 +1,16 @@
1
+ /** 用于 img / video / audio 的 src 解析时的媒体类别 */
2
+ export type MediaKind = 'image' | 'video' | 'audio';
3
+ /**
4
+ * 将消息段中的 url/file 等转为浏览器可用的媒体地址。
5
+ *
6
+ * 支持:
7
+ * - `http(s)://`、`blob:`、`data:` → 原样返回
8
+ * - `base64://<纯 base64>` → `data:{默认MIME};base64,<payload>`(默认按 kind:图 png / 视频 mp4 / 音频 mpeg)
9
+ * - `base64://image/png;base64,xxxx` → `data:image/png;base64,xxxx`
10
+ *
11
+ * 与群内日报、html-test 等插件生成的 `base64://${buffer.toString('base64')}` 一致。
12
+ */
13
+ export declare function resolveMediaSrc(raw: string | undefined | null, kind?: MediaKind): string | undefined;
14
+ /** 从 segment.data 取常见媒体字段 */
15
+ export declare function pickMediaRawUrl(data: Record<string, unknown> | undefined): string | undefined;
16
+ //# sourceMappingURL=mediaSrc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediaSrc.d.ts","sourceRoot":"","sources":["../client/mediaSrc.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAA;AAInD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EAC9B,IAAI,GAAE,SAAmB,GACxB,MAAM,GAAG,SAAS,CAyBpB;AAED,6BAA6B;AAC7B,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAI7F"}
@@ -0,0 +1,42 @@
1
+ const BASE64_PROTO = 'base64://';
2
+ /**
3
+ * 将消息段中的 url/file 等转为浏览器可用的媒体地址。
4
+ *
5
+ * 支持:
6
+ * - `http(s)://`、`blob:`、`data:` → 原样返回
7
+ * - `base64://<纯 base64>` → `data:{默认MIME};base64,<payload>`(默认按 kind:图 png / 视频 mp4 / 音频 mpeg)
8
+ * - `base64://image/png;base64,xxxx` → `data:image/png;base64,xxxx`
9
+ *
10
+ * 与群内日报、html-test 等插件生成的 `base64://${buffer.toString('base64')}` 一致。
11
+ */
12
+ export function resolveMediaSrc(raw, kind = 'image') {
13
+ if (raw == null || typeof raw !== 'string')
14
+ return undefined;
15
+ const s = raw.trim();
16
+ if (!s)
17
+ return undefined;
18
+ if (s.startsWith('data:') || s.startsWith('blob:') || s.startsWith('http://') || s.startsWith('https://')) {
19
+ return s;
20
+ }
21
+ if (!s.startsWith(BASE64_PROTO)) {
22
+ return s;
23
+ }
24
+ const payload = s.slice(BASE64_PROTO.length).replace(/^\s+/, '');
25
+ if (!payload)
26
+ return undefined;
27
+ // 已是 type/subtype;base64, 片段(不含 data: 前缀)
28
+ if (/^[\w+.-]+\/[\w+.-]+;base64,/i.test(payload)) {
29
+ return `data:${payload}`;
30
+ }
31
+ const defaultMime = kind === 'image' ? 'image/png' : kind === 'video' ? 'video/mp4' : 'audio/mpeg';
32
+ const b64 = payload.replace(/\s/g, '');
33
+ return `data:${defaultMime};base64,${b64}`;
34
+ }
35
+ /** 从 segment.data 取常见媒体字段 */
36
+ export function pickMediaRawUrl(data) {
37
+ if (!data)
38
+ return undefined;
39
+ const v = data.url ?? data.file ?? data.src ?? data.href;
40
+ return typeof v === 'string' && v.trim() ? v.trim() : undefined;
41
+ }
42
+ //# sourceMappingURL=mediaSrc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediaSrc.js","sourceRoot":"","sources":["../client/mediaSrc.ts"],"names":[],"mappings":"AAGA,MAAM,YAAY,GAAG,WAAW,CAAA;AAEhC;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAC7B,GAA8B,EAC9B,OAAkB,OAAO;IAEzB,IAAI,GAAG,IAAI,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAA;IAC5D,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;IACpB,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAA;IAExB,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC1G,OAAO,CAAC,CAAA;IACV,CAAC;IAED,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,CAAA;IACV,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IAChE,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAA;IAE9B,0CAA0C;IAC1C,IAAI,8BAA8B,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACjD,OAAO,QAAQ,OAAO,EAAE,CAAA;IAC1B,CAAC;IAED,MAAM,WAAW,GACf,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAA;IAChF,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IACtC,OAAO,QAAQ,WAAW,WAAW,GAAG,EAAE,CAAA;AAC5C,CAAC;AAED,6BAA6B;AAC7B,MAAM,UAAU,eAAe,CAAC,IAAyC;IACvE,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAA;IAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,CAAA;IACxD,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;AACjE,CAAC"}
@@ -12,6 +12,10 @@ export interface RouteMenuItem {
12
12
  hideInMenu?: boolean;
13
13
  requiresAuth?: boolean;
14
14
  order?: number;
15
+ /** 侧栏分组标签,同组内按 order 排序 */
16
+ group?: string;
17
+ /** 主内容区全宽(无 max-w-7xl) */
18
+ fullWidth?: boolean;
15
19
  };
16
20
  }
17
21
  export interface RouteState {
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../client/store/reducers/route.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGhD,MAAM,WAAW,aAAa;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAA;IAC1B,IAAI,CAAC,EAAE;QACH,UAAU,CAAC,EAAE,OAAO,CAAA;QACpB,YAAY,CAAC,EAAE,OAAO,CAAA;QACtB,KAAK,CAAC,EAAE,MAAM,CAAA;KACjB,CAAA;CACJ;AAED,MAAM,WAAW,UAAU;IACvB,MAAM,EAAE,aAAa,EAAE,CAAA;CAC1B;AAiGD,eAAO,MAAQ,QAAQ,wFAAE,WAAW,oFAAE,WAAW;UAhCU,MAAM;aAAW,OAAO,CAAC,aAAa,CAAC;yBAgC/C,SAAS,2FAAE,WAAW,6EAAuB,CAAA;;AAChG,wBAAiC"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../client/store/reducers/route.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGhD,MAAM,WAAW,aAAa;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAA;IAC1B,IAAI,CAAC,EAAE;QACH,UAAU,CAAC,EAAE,OAAO,CAAA;QACpB,YAAY,CAAC,EAAE,OAAO,CAAA;QACtB,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,2BAA2B;QAC3B,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,0BAA0B;QAC1B,SAAS,CAAC,EAAE,OAAO,CAAA;KACtB,CAAA;CACJ;AAED,MAAM,WAAW,UAAU;IACvB,MAAM,EAAE,aAAa,EAAE,CAAA;CAC1B;AAiGD,eAAO,MAAQ,QAAQ,wFAAE,WAAW,oFAAE,WAAW;UAhCU,MAAM;aAAW,OAAO,CAAC,aAAa,CAAC;yBAgC/C,SAAS,2FAAE,WAAW,6EAAuB,CAAA;;AAChG,wBAAiC"}
@@ -1 +1 @@
1
- {"version":3,"file":"route.js","sourceRoot":"","sources":["../../../client/store/reducers/route.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"route.js","sourceRoot":"","sources":["../../../client/store/reducers/route.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export interface MessageSegment {
2
- type: 'text' | 'image' | 'at' | 'face' | 'video' | 'audio' | 'file' | 'reply';
2
+ /** record:如 ICQQ 语音等,展示时按音频处理 */
3
+ type: 'text' | 'image' | 'at' | 'face' | 'video' | 'audio' | 'record' | 'file' | 'reply';
3
4
  data: Record<string, any>;
4
5
  }
5
6
  export type MessageElement = MessageSegment;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../client/types.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAA;IAC7E,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAC1B;AAGD,MAAM,MAAM,cAAc,GAAG,cAAc,CAAA;AAG3C,MAAM,MAAM,WAAW,GAAG,cAAc,GAAG,cAAc,EAAE,GAAG,MAAM,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../client/types.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,cAAc;IAC7B,iCAAiC;IACjC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAA;IACxF,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAC1B;AAGD,MAAM,MAAM,cAAc,GAAG,cAAc,CAAA;AAG3C,MAAM,MAAM,WAAW,GAAG,cAAc,GAAG,cAAc,EAAE,GAAG,MAAM,CAAA"}