@hd-front-end/jsbridge-sdk 1.0.2 → 1.0.4

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 (26) hide show
  1. package/README.md +4 -2
  2. package/dist/index.d.ts +201 -2
  3. package/dist/index.esm.js +444 -1
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/index.js +446 -0
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.umd.js +446 -0
  8. package/dist/index.umd.js.map +1 -1
  9. package/docs/00-/351/241/271/347/233/256/346/246/202/350/247/210.md +282 -0
  10. package/docs/01-/346/236/266/346/236/204/350/256/276/350/256/241.md +623 -0
  11. package/docs/02-/346/212/200/346/234/257/345/256/236/347/216/260.md +867 -0
  12. package/docs/03-API/344/275/277/347/224/250/346/226/207/346/241/243.md +1104 -0
  13. package/docs/04-/346/265/213/350/257/225/346/226/271/346/241/210.md +360 -0
  14. package/docs/05-/350/277/201/347/247/273/346/214/207/345/215/227.md +181 -0
  15. package/docs/06-/346/236/266/346/236/204/345/233/276/351/233/206.md +738 -0
  16. package/docs/07-/346/226/260/346/241/245/346/216/245/346/226/271/346/263/225/346/211/251/345/261/225/350/257/264/346/230/216.md +139 -0
  17. package/docs/CODE_REVIEW.md +65 -0
  18. package/docs/EVALUATION.md +72 -0
  19. package/docs/README.md +258 -0
  20. package/docs//345/205/263/351/224/256/351/227/256/351/242/230/350/247/243/347/255/224.md +495 -0
  21. package/docs//346/226/207/346/241/243/346/225/264/345/220/210/350/257/264/346/230/216.md +265 -0
  22. package/docs//346/233/264/346/226/260/346/227/245/345/277/227.md +669 -0
  23. package/docs//347/224/237/344/272/247/347/272/247-/345/277/253/351/200/237/345/274/200/345/247/213-v2.md +673 -0
  24. package/docs//347/224/237/344/272/247/347/272/247-/346/236/266/346/236/204/350/256/276/350/256/241-v2.md +730 -0
  25. package/docs//350/256/276/350/256/241/347/220/206/345/277/265/350/257/264/346/230/216.md +438 -0
  26. package/package.json +3 -2
@@ -0,0 +1,867 @@
1
+ # JSBridge SDK 技术实现(生产级 v2)
2
+
3
+ > **完整代码实现(代码级文档)**
4
+
5
+ ## 📁 目录结构
6
+
7
+ ```
8
+ src/
9
+ ├── core/
10
+ │ └── Bridge.ts # 200 行
11
+ ├── monitor/
12
+ │ └── Monitor.ts # 180 行
13
+ ├── debug/
14
+ │ └── Debug.ts # 150 行
15
+ ├── api/
16
+ │ ├── device.ts # 80 行
17
+ │ ├── media.ts # 90 行
18
+ │ ├── router.ts # 60 行
19
+ │ ├── storage.ts # 50 行
20
+ │ ├── system.ts # 40 行
21
+ │ └── log.ts # 80 行 ← 新增
22
+ ├── types/
23
+ │ └── index.ts # 120 行
24
+ └── index.ts # 100 行
25
+
26
+ 总计:~1150 行
27
+ ```
28
+
29
+ ## 1. Bridge.ts - 核心通信(200行)
30
+
31
+ ```typescript
32
+ // src/core/Bridge.ts
33
+ /**
34
+ * 平台类型
35
+ */
36
+ export enum Platform {
37
+ Android = 'android',
38
+ iOS = 'ios',
39
+ Unknown = 'unknown'
40
+ }
41
+
42
+ /**
43
+ * JSBridge 核心通信类
44
+ * 兼容 Android 和 iOS
45
+ */
46
+ class Bridge {
47
+ private bridge: any = null
48
+ private isInitialized: boolean = false
49
+ private platform: Platform = Platform.Unknown
50
+
51
+ constructor() {
52
+ this.detectPlatform()
53
+ }
54
+
55
+ /**
56
+ * 检测平台
57
+ */
58
+ private detectPlatform(): void {
59
+ const ua = navigator.userAgent
60
+
61
+ if (/SoaAndroid|HDApp.*Android/i.test(ua)) {
62
+ this.platform = Platform.Android
63
+ console.log('[JSBridge] 检测到 Android 平台')
64
+ return
65
+ }
66
+
67
+ if (/iPhone|iPad|iPod/i.test(ua) && /HDApp/i.test(ua)) {
68
+ this.platform = Platform.iOS
69
+ console.log('[JSBridge] 检测到 iOS 平台')
70
+ return
71
+ }
72
+
73
+ this.platform = Platform.Unknown
74
+ console.log('[JSBridge] 未检测到原生环境')
75
+ }
76
+
77
+ /**
78
+ * 初始化 JSBridge
79
+ */
80
+ async init(): Promise<boolean> {
81
+ if (this.isInitialized) return true
82
+ if (this.platform === Platform.Unknown) {
83
+ console.warn('[JSBridge] 不在原生 App 环境中')
84
+ return false
85
+ }
86
+
87
+ return new Promise((resolve, reject) => {
88
+ // 检查是否已有 Bridge 实例
89
+ if (window.WKWebViewJavascriptBridge) {
90
+ this.bridge = window.WKWebViewJavascriptBridge
91
+ this.isInitialized = true
92
+ console.log(`[JSBridge] ${this.platform} 初始化成功(已存在)`)
93
+ resolve(true)
94
+ return
95
+ }
96
+
97
+ // 等待 Bridge 注入
98
+ window.WKWVJBCallbacks = window.WKWVJBCallbacks || []
99
+ window.WKWVJBCallbacks.push((bridge: any) => {
100
+ this.bridge = bridge
101
+ this.isInitialized = true
102
+ console.log(`[JSBridge] ${this.platform} 初始化成功`)
103
+ resolve(true)
104
+ })
105
+
106
+ // Android 特定初始化
107
+ if (this.platform === Platform.Android) {
108
+ if (window.InjectJavascript) {
109
+ window.InjectJavascript.init()
110
+ console.log('[JSBridge] Android 触发初始化')
111
+ } else {
112
+ console.error('[JSBridge] Android InjectJavascript 不存在')
113
+ reject(new Error('Android InjectJavascript 不存在'))
114
+ }
115
+ }
116
+
117
+ // iOS 特定初始化
118
+ if (this.platform === Platform.iOS) {
119
+ const iframe = document.createElement('iframe')
120
+ iframe.style.display = 'none'
121
+ iframe.src = 'https://__bridge_loaded__'
122
+ document.documentElement.appendChild(iframe)
123
+ setTimeout(() => document.documentElement.removeChild(iframe), 0)
124
+ console.log('[JSBridge] iOS 触发初始化')
125
+ }
126
+
127
+ // 超时处理(10 秒)
128
+ setTimeout(() => {
129
+ if (!this.isInitialized) {
130
+ console.error(`[JSBridge] ${this.platform} 初始化超时`)
131
+ reject(new Error(`${this.platform} 初始化超时`))
132
+ }
133
+ }, 10000)
134
+ })
135
+ }
136
+
137
+ /**
138
+ * 调用原生方法
139
+ */
140
+ call<T = any>(method: string, data?: any): Promise<T> {
141
+ if (this.platform === Platform.Unknown) {
142
+ return Promise.reject(new Error('不在原生 App 环境中'))
143
+ }
144
+
145
+ if (!this.isInitialized) {
146
+ return Promise.reject(new Error('JSBridge 未初始化'))
147
+ }
148
+
149
+ console.log(`[JSBridge] [${this.platform}] 调用: ${method}`, data)
150
+
151
+ return new Promise((resolve, reject) => {
152
+ try {
153
+ this.bridge.callHandler(method, data, (result: any) => {
154
+ console.log(`[JSBridge] [${this.platform}] 返回: ${method}`, result)
155
+ resolve(result)
156
+ })
157
+ } catch (error) {
158
+ console.error(`[JSBridge] [${this.platform}] 调用失败: ${method}`, error)
159
+ reject(error)
160
+ }
161
+ })
162
+ }
163
+
164
+ /**
165
+ * 注册方法供原生调用
166
+ */
167
+ register(method: string, handler: (data: any, callback: any) => void): void {
168
+ if (this.platform === Platform.Unknown || !this.isInitialized) {
169
+ console.warn(`[JSBridge] 无法注册方法: ${method}`)
170
+ return
171
+ }
172
+
173
+ console.log(`[JSBridge] [${this.platform}] 注册方法: ${method}`)
174
+
175
+ this.bridge.registerHandler(method, (data: any, responseCallback: any) => {
176
+ console.log(`[JSBridge] [${this.platform}] 原生调用: ${method}`, data)
177
+ try {
178
+ handler(data, responseCallback)
179
+ } catch (error) {
180
+ console.error(`[JSBridge] [${this.platform}] 处理失败: ${method}`, error)
181
+ responseCallback?.({ error: (error as Error).message })
182
+ }
183
+ })
184
+ }
185
+
186
+ getPlatform(): Platform {
187
+ return this.platform
188
+ }
189
+
190
+ inApp(): boolean {
191
+ return this.platform !== Platform.Unknown
192
+ }
193
+
194
+ isReady(): boolean {
195
+ return this.isInitialized
196
+ }
197
+ }
198
+
199
+ export const bridge = new Bridge()
200
+ ```
201
+
202
+ ## 2. log.ts - 日志API(80行)← 新增
203
+
204
+ ```typescript
205
+ // src/api/log.ts
206
+ import { bridge } from '../core/Bridge'
207
+ import { monitor } from '../monitor/Monitor'
208
+ import { debug } from '../debug/Debug'
209
+
210
+ /**
211
+ * 日志级别
212
+ */
213
+ export enum LogLevel {
214
+ DEBUG = 'DEBUG',
215
+ INFO = 'INFO',
216
+ WARN = 'WARN',
217
+ ERROR = 'ERROR'
218
+ }
219
+
220
+ /**
221
+ * 日志请求参数
222
+ */
223
+ export interface LogRequest {
224
+ tag?: string
225
+ level: LogLevel
226
+ message: string
227
+ }
228
+
229
+ /**
230
+ * 写日志到原生
231
+ */
232
+ export async function writeLog(request: LogRequest): Promise<void> {
233
+ const record = monitor.recordStart('log', bridge.getPlatform(), request)
234
+
235
+ try {
236
+ await bridge.call('log', {
237
+ tag: request.tag || 'JSBridge',
238
+ level: request.level,
239
+ message: request.message
240
+ })
241
+
242
+ monitor.recordEnd(record, true)
243
+ debug.log('debug', `日志已写入: [${request.level}] ${request.message}`)
244
+ } catch (error) {
245
+ monitor.recordEnd(record, false, undefined, (error as Error).message)
246
+ debug.log('error', `写入日志失败: ${(error as Error).message}`)
247
+ throw error
248
+ }
249
+ }
250
+
251
+ /**
252
+ * 便捷方法
253
+ */
254
+ export const log = {
255
+ debug: (message: string, tag?: string) =>
256
+ writeLog({ level: LogLevel.DEBUG, message, tag }),
257
+
258
+ info: (message: string, tag?: string) =>
259
+ writeLog({ level: LogLevel.INFO, message, tag }),
260
+
261
+ warn: (message: string, tag?: string) =>
262
+ writeLog({ level: LogLevel.WARN, message, tag }),
263
+
264
+ error: (message: string, tag?: string) =>
265
+ writeLog({ level: LogLevel.ERROR, message, tag })
266
+ }
267
+ ```
268
+
269
+ ## 3. Monitor.ts - 监控(180行)
270
+
271
+ ```typescript
272
+ // src/monitor/Monitor.ts
273
+ import { bridge } from '../core/Bridge'
274
+
275
+ export interface MonitorConfig {
276
+ enabled: boolean
277
+ autoReport?: boolean
278
+ reportInterval?: number
279
+ maxCacheSize?: number
280
+ logTag?: string
281
+ }
282
+
283
+ export interface ApiCallRecord {
284
+ api: string
285
+ platform: string
286
+ startTime: number
287
+ endTime?: number
288
+ duration?: number
289
+ success: boolean
290
+ error?: string
291
+ params?: any
292
+ result?: any
293
+ }
294
+
295
+ export interface PerformanceStats {
296
+ totalCalls: number
297
+ successCalls: number
298
+ failedCalls: number
299
+ avgDuration: number
300
+ maxDuration: number
301
+ minDuration: number
302
+ }
303
+
304
+ class Monitor {
305
+ private config: MonitorConfig
306
+ private records: ApiCallRecord[] = []
307
+ private stats: Map<string, PerformanceStats> = new Map()
308
+ private reportTimer?: NodeJS.Timeout
309
+
310
+ constructor(config: Partial<MonitorConfig> = {}) {
311
+ this.config = {
312
+ enabled: true,
313
+ reportInterval: 60000,
314
+ maxCacheSize: 100,
315
+ autoReport: false,
316
+ logTag: 'JSBridge-Monitor',
317
+ ...config
318
+ }
319
+
320
+ if (this.config.autoReport) {
321
+ this.startAutoReport()
322
+ }
323
+ }
324
+
325
+ recordStart(api: string, platform: string, params?: any): ApiCallRecord {
326
+ if (!this.config.enabled) {
327
+ return {} as ApiCallRecord
328
+ }
329
+
330
+ return {
331
+ api,
332
+ platform,
333
+ startTime: Date.now(),
334
+ success: false,
335
+ params
336
+ }
337
+ }
338
+
339
+ recordEnd(record: ApiCallRecord, success: boolean, result?: any, error?: string): void {
340
+ if (!this.config.enabled) {
341
+ return
342
+ }
343
+
344
+ record.endTime = Date.now()
345
+ record.duration = record.endTime - record.startTime
346
+ record.success = success
347
+ record.result = result
348
+ record.error = error
349
+
350
+ this.records.push(record)
351
+
352
+ if (this.records.length > this.config.maxCacheSize!) {
353
+ this.records.shift()
354
+ }
355
+
356
+ this.updateStats(record)
357
+ }
358
+
359
+ private updateStats(record: ApiCallRecord): void {
360
+ if (!record.api) return
361
+
362
+ let stats = this.stats.get(record.api)
363
+ if (!stats) {
364
+ stats = {
365
+ totalCalls: 0,
366
+ successCalls: 0,
367
+ failedCalls: 0,
368
+ avgDuration: 0,
369
+ maxDuration: 0,
370
+ minDuration: Infinity
371
+ }
372
+ this.stats.set(record.api, stats)
373
+ }
374
+
375
+ stats.totalCalls++
376
+ if (record.success) {
377
+ stats.successCalls++
378
+ } else {
379
+ stats.failedCalls++
380
+ }
381
+
382
+ if (record.duration) {
383
+ stats.maxDuration = Math.max(stats.maxDuration, record.duration)
384
+ stats.minDuration = Math.min(stats.minDuration, record.duration)
385
+ stats.avgDuration = ((stats.avgDuration * (stats.totalCalls - 1)) + record.duration) / stats.totalCalls
386
+ }
387
+ }
388
+
389
+ /**
390
+ * 上报监控数据
391
+ * ✅ v2: 通过原生 log 能力上报
392
+ */
393
+ async report(): Promise<void> {
394
+ if (this.records.length === 0) {
395
+ return
396
+ }
397
+
398
+ try {
399
+ const data = {
400
+ records: this.records,
401
+ stats: Array.from(this.stats.entries()).map(([api, stats]) => ({
402
+ api,
403
+ ...stats
404
+ })),
405
+ timestamp: Date.now()
406
+ }
407
+
408
+ // ✅ 通过原生 log 能力上报
409
+ await bridge.call('log', {
410
+ tag: this.config.logTag,
411
+ level: 'INFO',
412
+ message: `[MONITOR] ${JSON.stringify(data)}`
413
+ })
414
+
415
+ console.log('[Monitor] 监控数据已上报到原生日志')
416
+ this.clear()
417
+ } catch (error) {
418
+ console.error('[Monitor] 上报失败', error)
419
+ }
420
+ }
421
+
422
+ /**
423
+ * 立即上报错误
424
+ */
425
+ async reportError(api: string, error: string, detail?: any): Promise<void> {
426
+ if (!this.config.enabled) {
427
+ return
428
+ }
429
+
430
+ try {
431
+ const errorData = {
432
+ type: 'error',
433
+ api,
434
+ error,
435
+ detail,
436
+ platform: bridge.getPlatform(),
437
+ timestamp: Date.now()
438
+ }
439
+
440
+ // ✅ 立即通过原生 log 能力上报错误
441
+ await bridge.call('log', {
442
+ tag: this.config.logTag,
443
+ level: 'ERROR',
444
+ message: `[ERROR] ${JSON.stringify(errorData)}`
445
+ })
446
+
447
+ console.error('[Monitor] 错误已上报:', errorData)
448
+ } catch (e) {
449
+ console.error('[Monitor] 上报错误失败', e)
450
+ }
451
+ }
452
+
453
+ private startAutoReport(): void {
454
+ this.reportTimer = setInterval(() => {
455
+ this.report()
456
+ }, this.config.reportInterval)
457
+ }
458
+
459
+ updateConfig(config: Partial<MonitorConfig>): void {
460
+ this.config = { ...this.config, ...config }
461
+
462
+ if (this.config.autoReport && !this.reportTimer) {
463
+ this.startAutoReport()
464
+ } else if (!this.config.autoReport && this.reportTimer) {
465
+ clearInterval(this.reportTimer)
466
+ this.reportTimer = undefined
467
+ }
468
+ }
469
+
470
+ getStats(api?: string): any {
471
+ if (api) {
472
+ return this.stats.get(api) || null
473
+ }
474
+ return this.stats
475
+ }
476
+
477
+ getRecords(limit?: number): ApiCallRecord[] {
478
+ if (limit) {
479
+ return this.records.slice(-limit)
480
+ }
481
+ return [...this.records]
482
+ }
483
+
484
+ clear(): void {
485
+ this.records = []
486
+ this.stats.clear()
487
+ }
488
+ }
489
+
490
+ export const monitor = new Monitor()
491
+ ```
492
+
493
+ ## 4. index.ts - 统一导出(100行)
494
+
495
+ ```typescript
496
+ // src/index.ts
497
+ import { bridge, Platform } from './core/Bridge'
498
+ import { monitor, MonitorConfig } from './monitor/Monitor'
499
+ import { debug, DebugConfig } from './debug/Debug'
500
+ import * as device from './api/device'
501
+ import * as media from './api/media'
502
+ import * as router from './api/router'
503
+ import * as storage from './api/storage'
504
+ import * as system from './api/system'
505
+ import { writeLog, log, LogLevel, LogRequest } from './api/log' // ← 新增
506
+
507
+ export interface JSBridgeConfig {
508
+ debug?: Partial<DebugConfig>
509
+ monitor?: Partial<MonitorConfig>
510
+ }
511
+
512
+ /**
513
+ * 初始化 JSBridge
514
+ */
515
+ export async function init(config?: JSBridgeConfig): Promise<boolean> {
516
+ try {
517
+ // 配置 debug
518
+ if (config?.debug) {
519
+ debug.updateConfig(config.debug)
520
+ if (config.debug.useVConsole) {
521
+ await debug.initVConsole()
522
+ }
523
+ }
524
+
525
+ // 配置 monitor
526
+ if (config?.monitor) {
527
+ monitor.updateConfig(config.monitor)
528
+ }
529
+
530
+ // 初始化 bridge
531
+ const success = await bridge.init()
532
+
533
+ // 保存平台信息
534
+ (window as any).__jsbridgePlatform = bridge.getPlatform()
535
+
536
+ // ✅ 通过 log API 记录初始化成功
537
+ if (success) {
538
+ await writeLog({
539
+ level: LogLevel.INFO,
540
+ message: `JSBridge 初始化成功 [${bridge.getPlatform()}]`
541
+ })
542
+ }
543
+
544
+ return success
545
+ } catch (error) {
546
+ console.error('[JSBridge] 初始化失败', error)
547
+ debug.log('error', '初始化失败', error)
548
+
549
+ // 尝试上报错误
550
+ try {
551
+ await writeLog({
552
+ level: LogLevel.ERROR,
553
+ message: `JSBridge 初始化失败: ${(error as Error).message}`
554
+ })
555
+ } catch (e) {
556
+ // 忽略上报失败
557
+ }
558
+
559
+ return false
560
+ }
561
+ }
562
+
563
+ export function inApp(): boolean {
564
+ return bridge.inApp()
565
+ }
566
+
567
+ export function getPlatform(): Platform {
568
+ return bridge.getPlatform()
569
+ }
570
+
571
+ /**
572
+ * JSBridge API
573
+ */
574
+ export const JSBridge = {
575
+ // 设备相关
576
+ scan: device.scan,
577
+ vibrate: device.vibrate,
578
+ getDeviceInfo: device.getDeviceInfo,
579
+ getNetworkType: device.getNetworkType,
580
+
581
+ // 媒体相关
582
+ chooseMedia: media.chooseMedia,
583
+ uploadFile: media.uploadFile,
584
+ previewImage: media.previewImage,
585
+ getImageInfo: media.getImageInfo,
586
+ bluetoothPrint: media.bluetoothPrint,
587
+
588
+ // 路由相关
589
+ setNavigationBar: router.setNavigationBar,
590
+ closeWebView: router.closeWebView,
591
+ onRoute: router.onRoute,
592
+ onGetRouteInfo: router.onGetRouteInfo,
593
+ notifyRouteChange: router.notifyRouteChange,
594
+
595
+ // 存储相关
596
+ getStorage: storage.getStorage,
597
+ setStorage: storage.setStorage,
598
+ getAppInfo: storage.getAppInfo,
599
+ onRefreshStore: storage.onRefreshStore,
600
+ notifyAppOnload: storage.notifyAppOnload,
601
+
602
+ // 系统相关
603
+ makePhoneCall: system.makePhoneCall,
604
+ onPdaScan: system.onPdaScan,
605
+
606
+ // ← 日志相关(新增)
607
+ writeLog,
608
+ log
609
+ }
610
+
611
+ /**
612
+ * 监控 API
613
+ */
614
+ export const Monitor = {
615
+ getStats: monitor.getStats.bind(monitor),
616
+ getRecords: monitor.getRecords.bind(monitor),
617
+ clear: monitor.clear.bind(monitor),
618
+ report: monitor.report.bind(monitor),
619
+ reportError: monitor.reportError.bind(monitor)
620
+ }
621
+
622
+ /**
623
+ * Debug API
624
+ */
625
+ export const Debug = {
626
+ trace: debug.trace.bind(debug),
627
+ getLogs: debug.getLogs.bind(debug),
628
+ clearLogs: debug.clearLogs.bind(debug)
629
+ }
630
+
631
+ export * from './types'
632
+ export { Platform, MonitorConfig, DebugConfig, LogLevel, LogRequest }
633
+ ```
634
+
635
+ ## 5. 原生端实现
636
+
637
+ ### 5.1 Android 端
638
+
639
+ ```kotlin
640
+ // 注册 log handler
641
+ webView.registerHandler("log") { data, callback ->
642
+ val request = Gson().fromJson(data, UniLog::class.java)
643
+
644
+ // 使用 LogUtil 写入日志
645
+ when (request.level) {
646
+ "DEBUG" -> LogUtil.debug(request.tag, request.message)
647
+ "INFO" -> LogUtil.info(request.tag, request.message)
648
+ "WARN" -> LogUtil.warn(request.tag, request.message)
649
+ "ERROR" -> LogUtil.error(request.tag, request.message)
650
+ }
651
+
652
+ callback?.invoke(null)
653
+ }
654
+ ```
655
+
656
+ ### 5.2 iOS 端
657
+
658
+ ```swift
659
+ // 注册 log handler
660
+ bridge.registerHandler("log") { data, callback in
661
+ guard let request = data as? [String: Any],
662
+ let level = request["level"] as? String,
663
+ let message = request["message"] as? String else {
664
+ callback?(nil)
665
+ return
666
+ }
667
+
668
+ let tag = request["tag"] as? String ?? "JSBridge"
669
+
670
+ // 使用 OSLog 写入日志
671
+ switch level {
672
+ case "DEBUG":
673
+ os_log(.debug, log: OSLog(subsystem: "JSBridge", category: tag), "%{public}@", message)
674
+ case "INFO":
675
+ os_log(.info, log: OSLog(subsystem: "JSBridge", category: tag), "%{public}@", message)
676
+ case "WARN":
677
+ os_log(.error, log: OSLog(subsystem: "JSBridge", category: tag), "[WARN] %{public}@", message)
678
+ case "ERROR":
679
+ os_log(.fault, log: OSLog(subsystem: "JSBridge", category: tag), "%{public}@", message)
680
+ default:
681
+ break
682
+ }
683
+
684
+ callback?(nil)
685
+ }
686
+ ```
687
+
688
+ ## 6. 构建配置
689
+
690
+ ### package.json
691
+
692
+ ```json
693
+ {
694
+ "name": "@hd-front-end/jsbridge-sdk",
695
+ "version": "2.0.0",
696
+ "main": "dist/index.cjs.js",
697
+ "module": "dist/index.esm.js",
698
+ "types": "dist/types/index.d.ts",
699
+ "files": ["dist"],
700
+ "scripts": {
701
+ "build": "rollup -c",
702
+ "dev": "rollup -c -w",
703
+ "test": "jest"
704
+ },
705
+ "peerDependencies": {
706
+ "vconsole": "^3.15.0"
707
+ },
708
+ "peerDependenciesMeta": {
709
+ "vconsole": {
710
+ "optional": true
711
+ }
712
+ },
713
+ "devDependencies": {
714
+ "@rollup/plugin-typescript": "^11.0.0",
715
+ "rollup": "^3.0.0",
716
+ "typescript": "^5.0.0",
717
+ "vconsole": "^3.15.0"
718
+ }
719
+ }
720
+ ```
721
+
722
+ ### rollup.config.js
723
+
724
+ ```javascript
725
+ import typescript from '@rollup/plugin-typescript'
726
+
727
+ export default {
728
+ input: 'src/index.ts',
729
+ output: [
730
+ {
731
+ file: 'dist/index.cjs.js',
732
+ format: 'cjs'
733
+ },
734
+ {
735
+ file: 'dist/index.esm.js',
736
+ format: 'esm'
737
+ }
738
+ ],
739
+ plugins: [
740
+ typescript({
741
+ declaration: true,
742
+ declarationDir: 'dist/types'
743
+ })
744
+ ],
745
+ external: ['vconsole']
746
+ }
747
+ ```
748
+
749
+ ### tsconfig.json
750
+
751
+ ```json
752
+ {
753
+ "compilerOptions": {
754
+ "target": "ES2015",
755
+ "module": "ESNext",
756
+ "moduleResolution": "node",
757
+ "declaration": true,
758
+ "strict": true,
759
+ "esModuleInterop": true,
760
+ "skipLibCheck": true,
761
+ "forceConsistentCasingInFileNames": true
762
+ },
763
+ "include": ["src/**/*"],
764
+ "exclude": ["node_modules", "dist"]
765
+ }
766
+ ```
767
+
768
+ ## 7. 完整使用示例
769
+
770
+ ```typescript
771
+ // App.vue
772
+ import { init, JSBridge, getPlatform, Monitor } from '@hd-front-end/jsbridge-sdk'
773
+
774
+ const isDev = process.env.NODE_ENV === 'development'
775
+
776
+ export default {
777
+ async onLaunch() {
778
+ // #ifdef H5-HD
779
+ // 1. 初始化
780
+ await init({
781
+ debug: {
782
+ enabled: isDev,
783
+ useVConsole: isDev && /vconsole=true/.test(location.search),
784
+ logLevel: isDev ? 'debug' : 'error'
785
+ },
786
+ monitor: {
787
+ enabled: !isDev,
788
+ autoReport: !isDev,
789
+ reportInterval: 60000,
790
+ logTag: 'JSBridge-Monitor'
791
+ }
792
+ })
793
+
794
+ console.log('平台:', getPlatform())
795
+
796
+ // 2. 记录启动日志
797
+ await JSBridge.log.info('App 启动成功', 'AppLifeCycle')
798
+
799
+ // 3. 注册原生回调
800
+ JSBridge.onRoute((data) => this.$Router.replaceAll(data))
801
+ JSBridge.onRefreshStore((data) => this.refreshStore(data))
802
+
803
+ // 4. 获取初始数据
804
+ const appInfo = await JSBridge.getAppInfo()
805
+ this.refreshStore(JSON.parse(appInfo), true)
806
+
807
+ // 5. 通知加载完成
808
+ await JSBridge.notifyAppOnload({ name: 'MyApp' })
809
+ // #endif
810
+ }
811
+ }
812
+
813
+ // 业务组件
814
+ export default {
815
+ methods: {
816
+ async handleScan() {
817
+ // 记录用户行为
818
+ await JSBridge.log.info('用户点击扫码', 'UserBehavior')
819
+
820
+ try {
821
+ const result = await JSBridge.scan()
822
+
823
+ // 记录成功
824
+ await JSBridge.log.info(
825
+ `扫码成功: ${result.resp_result}`,
826
+ 'ScanResult'
827
+ )
828
+ } catch (error) {
829
+ // 记录错误
830
+ await JSBridge.log.error(
831
+ `扫码失败: ${error.message}`,
832
+ 'ScanError'
833
+ )
834
+ }
835
+ }
836
+ }
837
+ }
838
+ ```
839
+
840
+ ## 8. 代码统计
841
+
842
+ | 文件 | 行数 | 说明 |
843
+ |------|------|------|
844
+ | Bridge.ts | 200 | 核心通信 |
845
+ | Monitor.ts | 180 | 监控(改用log) |
846
+ | Debug.ts | 150 | Debug模式 |
847
+ | log.ts | 80 | Log API ← 新增 |
848
+ | device.ts | 80 | 设备API |
849
+ | media.ts | 90 | 媒体API |
850
+ | router.ts | 60 | 路由API |
851
+ | storage.ts | 50 | 存储API |
852
+ | system.ts | 40 | 系统API |
853
+ | types/index.ts | 120 | 类型定义 |
854
+ | index.ts | 100 | 统一导出 |
855
+ | **总计** | **~1150** | |
856
+
857
+ ## 9. 相关文档
858
+
859
+ - **[00-项目概览.md](./00-项目概览.md)** - 项目概览
860
+ - **[01-架构设计.md](./01-架构设计.md)** - **架构设计思路**
861
+ - **[03-API使用文档.md](./03-API使用文档.md)** - API 详细文档
862
+ - **[生产级-架构设计-v2.md](./生产级-架构设计-v2.md)** - 完整架构
863
+
864
+ ---
865
+
866
+ **完整的代码实现,可直接使用** 🎯
867
+