本文引用的文件
本文件面向AI有声书生成平台的通用组件,聚焦以下组件的实现与使用:MiniPlayer迷你播放器、LazyImage懒加载图片、Skeleton骨架屏系列、AudioDownload音频下载、GenerationStatusBadge生成状态徽章、NetworkStatus网络状态提示。文档从架构、数据流、状态管理、性能优化、错误处理与最佳实践等维度进行系统化梳理,并提供可视化图示帮助理解。
通用组件集中于前端工程的组件目录,配合Pinia状态管理与页面使用示例,形成“组件-状态-页面”的清晰分层。
graph TB
subgraph "组件层"
MP["MiniPlayer.vue"]
LI["LazyImage.vue"]
SK["Skeleton.vue"]
SKL["SkeletonList.vue"]
AD["AudioDownload.vue"]
GSB["GenerationStatusBadge.vue"]
NS["NetworkStatus.vue"]
end
subgraph "状态层"
AST["audio.ts(Pinia Store)"]
end
subgraph "页面层"
PLY["pages/player/index.vue"]
ALB["pages/albums/index.vue"]
DET["pages/book-generator/detail.vue"]
end
MP --> AST
PLY --> MP
PLY --> AD
ALB --> SKL
DET --> GSB
NS --> PLY
图表来源
章节来源
章节来源
组件通过Pinia Store共享音频状态,页面按需渲染组件;下载与网络状态分别独立监听与提示,形成解耦的UI增强层。
graph TB
UI["页面视图<br/>player/index.vue / albums/index.vue / book-generator/detail.vue"]
MP["MiniPlayer"]
AD["AudioDownload"]
SK["Skeleton / SkeletonList"]
GSB["GenerationStatusBadge"]
NS["NetworkStatus"]
ST["Pinia Store(audio.ts)"]
UI --> MP
UI --> AD
UI --> SK
UI --> GSB
UI --> NS
MP --> ST
AD --> ST
图表来源
性能与体验
固定定位与阴影提升可读性与层级感。
sequenceDiagram
participant Page as "页面"
participant MP as "MiniPlayer"
participant Store as "audio.ts"
Page->>MP : 渲染组件
MP->>Store : 读取 currentAudio/isPlaying
MP->>MP : 计算封面渐变/格式化时间
MP->>Store : togglePlay()/playNext()
Store-->>Page : 更新播放状态
MP->>Page : 导航到播放器页
图表来源
章节来源
最佳实践
对大图列表优先启用lazyLoad,避免一次性请求过多资源。
flowchart TD
Start(["组件挂载"]) --> Check["是否启用懒加载?"]
Check --> |是| ShowPlaceholder["显示占位图"]
Check --> |否| ShowReal["直接显示真实图"]
ShowPlaceholder --> WatchSrc["监听src变化"]
ShowReal --> WatchSrc
WatchSrc --> SetReal["设置真实src"]
SetReal --> OnLoad["onLoad回调"]
OnLoad --> AddLoaded["添加loaded类"]
AddLoaded --> EmitLoad["emit load事件"]
SetReal --> OnError["onError回调"]
OnError --> EmitError["emit error事件"]
图表来源
章节来源
使用场景
与实际数据结构保持一致的骨架尺寸与间距。
classDiagram
class Skeleton {
+type : "text"|"circle"|"rect"|"image"|"custom"
+width : string
+height : string
+animated : boolean
}
class SkeletonList {
+layout : "grid"|"list"|"search-result"|"history"
+count : number
}
SkeletonList --> Skeleton : "组合多个骨架元素"
图表来源
章节来源
平台差异
App端使用uni.onNetworkStatusChange监听网络变化。
sequenceDiagram
participant UI as "页面"
participant DL as "AudioDownload"
participant UNI as "uni.downloadFile"
participant SAVE as "uni.saveFile"
UI->>DL : 点击下载
DL->>DL : downloading=true, progress=0
DL->>UNI : 发起下载任务
UNI-->>DL : onProgressUpdate(progress)
DL->>DL : 更新进度
UNI-->>DL : success(res)
alt 状态码200
DL->>SAVE : 保存到本地
SAVE-->>DL : success(saveRes)
DL->>UI : Toast成功
else 失败
DL->>UI : 重试/弹窗提示
end
图表来源
章节来源
交互逻辑
状态类名驱动样式,保证一致性与可维护性。
flowchart TD
S["输入状态字符串"] --> Merge["合并默认映射与自定义映射"]
Merge --> Lookup{"是否存在映射?"}
Lookup --> |是| Pick["取出icon/label"]
Lookup --> |否| Fallback["使用'?'与原始状态名"]
Pick --> Render["渲染徽章"]
Fallback --> Render
图表来源
章节来源
提示策略
仅在页面顶层展示,不影响主内容交互。
sequenceDiagram
participant Page as "页面"
participant NS as "NetworkStatus"
participant H5 as "H5在线事件"
participant APP as "App网络事件"
Page->>NS : 挂载组件
alt H5环境
NS->>H5 : 监听online/offline
H5-->>NS : onOffline/onOnline
else App环境
NS->>APP : uni.onNetworkStatusChange
APP-->>NS : isConnected
end
NS->>Page : Toast提示断网/恢复
图表来源
章节来源
平台差异
NetworkStatus在H5与App采用不同API,但对外行为一致。
graph LR
MP["MiniPlayer"] --> ST["audio.ts"]
AD["AudioDownload"] --> ST
PLY["player/index.vue"] --> MP
PLY --> AD
ALB["albums/index.vue"] --> SKL["SkeletonList"]
DET["book-generator/detail.vue"] --> GSB["GenerationStatusBadge"]
NS["NetworkStatus"] --> PLY
图表来源
章节来源
章节来源
上述通用组件围绕“状态共享、性能优化、体验一致”三大目标构建:通过Pinia集中管理音频状态,以组件形式在页面中复用;以骨架屏与懒加载优化首屏与滚动体验;以统一的状态徽章与网络提示提升信息传达效率。遵循本文的最佳实践与排障建议,可在复杂业务场景下保持组件的稳定性与可维护性。