跳转到内容

产品手册

包名 we-livesdk · 版本 1.2.0 · UMD 全局 window.LiveSDK

浏览器端直播 SDK:拉流播放、IM 聊天、互动、商品营销、运营弹框,挂到一个容器即起一个直播间。本手册覆盖全部对外能力——每个配置、方法、事件、模块、Store。

实现状态图例:✅ 已实现 · 🚧 占位未实现(Phase 2) · ⚠️ 待服务端验证(payload 推断)

能力 实现 状态
视频(直播 + VOD 回放) 腾讯云 TCPlayer
IM 聊天 腾讯 IM @tencentcloud/chat
实时信令 LAPS WebSocket @zan/laps,断线降级 HTTP 轮询
服务端时钟 config/detail + LAPS + 营销 HTTP 统一锚定,单调推进
观看时长 / 任务上报 WatchClock 真实媒体计时 + ordinary/Range 独立可靠 channel ✅(服务端 fence/finalAck ⚠️)
互动(点赞/礼物/分享) 内置 app 模块
商品列表 / 营销弹框 entry 模块 ✅(推送 payload ⚠️)
运营浮层(券/抽奖/任务/讲解) entry 模块 ⚠️
主题 / i18n / 弹框 运行时 API
弹幕 / 水印 / 清晰度插件 plugin 弹幕/水印 🚧 · 清晰度 ✅

兼容:iOS 12+ / Android 7+ / Safari 12+(ES2017)。UMD 经 Babel 转译,无原生 ESM 依赖。


Terminal window
pnpm add we-livesdk
import { LiveSDK } from 'we-livesdk'
import 'we-livesdk/styles'
const sdk = new LiveSDK({
activityId: 'xxx',
token: 'xxx',
merchantId: 'xxx',
api: { baseUrl: 'https://api.example.com' },
})
await sdk.mount('#live-container')
sdk.on('ready', ({ detail }) => { document.title = detail.title ?? '' })

拉流地址与 IM 凭证由 SDK 凭 activityId + token + merchantIdmount() 内自动认证拉取,无需手动传。仅用外部 IM 时才传 tim

import 'we-livesdk/embed.css'
const { LiveSDK, DefinitionPlugin } = await import('we-livesdk/legacy')
const sdk = new LiveSDK({
activityId,
token,
merchantId,
api: { baseUrl },
bootstrap: {
roomDetailPolicy: 'required',
roomDetail: hostCachedRoomDetail,
},
})
sdk.use(new DefinitionPlugin())
await sdk.mount(target)

we-livesdk/legacy 是无 CSS 副作用的单文件安全 ESM,首字节注入 iOS 12 polyfill;we-livesdk/embed.css 关闭 preflight,包含 SDK Tailwind utilities、构建期提取的 Svelte scoped 样式与 TCPlayer 播放器样式,并统一限制在 .livesdk-container 下。该入口供宿主构建器动态导入,不提供 window.LiveSDK 全局。

<link rel="stylesheet" href="we-livesdk/styles.css">
<script src="we-livesdk/dist-umd/livesdk.umd.js"></script>
<div id="live-container"></div>
<script>
new LiveSDK.LiveSDK({ activityId: 'xxx', token: 'xxx', merchantId: 'xxx' }).mount('#live-container')
</script>

构建:pnpm build:umddist-umd/{livesdk.umd.js, livesdk.iife.js, livesdk.esm.js, livesdk.legacy.js} + dist/embed.css;UMD/IIFE 全局名 LiveSDK


new LiveSDK(config)。仅 activityId / token / merchantId 必填;缺失抛错。

字段 类型 必填 默认 说明
activityId string 直播间 id
token string JWT 访问令牌
merchantId string 商户 id
storeId number 门店 id;房间营销 cmd 6010 上报透传,缺省按 0
api SDKApiConfig HTTP API 地址;运行时 api.baseUrl 优先于构建期 VITE_API_ENDPOINT,两者都缺失则认证 fail-closed
endpoints EndpointConfig 统一 HTTP / LAPS WS / 观看上报端点;优先于兼容字段和构建环境变量,可经 setEndpoints 动态更新
watchSession WatchSessionConfig 可信登录/bootstrap 服务签发的观看会话上下文;缺失时不启用可靠任务上报
bootstrap SDKBootstrapConfig sdk-fetch mount 认证的房间详情启动策略;宿主缓存模式可固定为 required
locale string 'zh-CN' UI 语言,未知值告警回退
entryModules AppEntryModuleId[] 全部 启用哪些运营入口模块
tim TIMConfig 外部 IM 凭证;不传则认证自动注入
ws WSConfig WebSocket 配置;不配则降级 HTTP 轮询
wsUrl string ⚠️ 已废弃,用 ws.url
modules ModuleConfig[] 全部 核心模块开关 { id, options? }
appModules AppModuleConfigs 全部启用 互动 app 模块开关
options SDKOptions SDK 运行选项(日志、主题、i18n、浮窗图标可见性等)
layout LayoutConfig 横竖屏 / Tab / 快捷评论
telemetry TelemetryConfig 遥测上报,须显式 enabled:true(见 SPEC-TELEMETRY-LOGGING)
sensitiveWords string[] 客户端敏感词;空则不过滤(fail-open)
user { nickName?, avatar? } 宿主 IM 用户资料;levelId 由 ve/token 自动注入,宿主不传
features FeatureConfig {} 业务 UI 可见性(按钮/入口开关);运行时可经 updateFeatures/setFeature 增量更新。零配置 = 今日行为(见下「业务特性配置」)
uiTextSize UiTextSizeConfigPartial<Record<UiTextSizeScene, 'default' | 'large' | 'xlarge'>> {} 场景级 UI 字号默认值(static 层)。集成方设的默认会被用户运行时选择覆盖(runtime > static > default,见下「字号档位」)。仅支持已登记场景,未声明的档位回退 largedefault
handlers { redPacket?: RedPacketHandlers } 宿主能力注入;红包读流程由 SDK 负责,提现/待收款确认等微信写动作交给宿主

SDKApiConfigbaseUrl?:string(协议 + host,可带或不带尾 /;内部会 trim 并移除尾 /)。所有 SDK HTTP 模块统一按 api.baseUrl → 构建期 VITE_API_ENDPOINT → fail-closed 解析,不含测试域名硬编码兜底。

EndpointConfigapiBaseUrl?:string · wsUrl?:string · watchReportBaseUrl?:string。优先级:运行时 setEndpoints → 构造期 endpoints → 兼容字段 → 构建变量。ordinary/Range Adapter 分别追加内置 path,保留 base pathname(支持 SaaS 前缀);拒绝完整 URL、跨域、query/hash、凭据和路径穿越。HTTP/上报仅接受 https://,WS 仅接受 wss://

WatchSessionConfigwatchSessionId:string · predecessorSessionId?:string · handoffCapability:'fence_v1'|'none' · predecessorFinalization:'successor_authorized'|'current_session_only'。必须由可信后端签发;SDK 不自行生成 predecessor 或宣称 fence 能力。⚠️ 服务端回显、finalAck 和 fence 协议须按宿主测试文档确认。

SDKBootstrapConfigroomDetailPolicy?:'sdk-fetch'|'required' · roomDetail?:RoomDetailBootstrap。缺省 sdk-fetch 时 SDK 自行请求详情;required 时必须提供合法宿主缓存 seed,缺失、字段非法或房间/商户不匹配均认证失败,不会回退请求详情。

RoomDetailBootstrap{ source:'host-cache', activityId:string, merchantId:string, detail:RoomDetailBody }detail.id / detail.siteId 必须分别匹配 activityId / merchantIdliveStatus 必须为 101~108

RedPacketHandlerswithdraw?:({amount})=>Promise<RedPacketHandlerResult> · confirmReceipt?:(record)=>Promise<RedPacketHandlerResult>,其中 RedPacketHandlerResult.status'success'|'cancelled'|'fail'|'pending',可带 message

TIMConfigsdkAppId:number · userId:string · userSig:string · groupId:string

WSConfigurl:string · reconnectBaseDelay(1000) · reconnectMaxDelay(30000) · reconnectMaxAttempts(10) · heartbeatInterval(25000) · authTimeout(5000) · loginRetryMax(3)

WS 地址优先级:ws.urlwsUrl(废弃) → 构建期 VITE_WS_URL。三者均未配置时不连接 WS,降级 HTTP 轮询;没有内置测试地址兜底。线上务必显式传 ws.url

SDKOptionsorigin?:string(保留字段,当前不参与 HTTP API 地址解析;请使用 api.baseUrl) · saveUserInfo?:boolean · logLevel?:'silent'|'error'|'warn'|'info'|'debug'(默认 warn) · theme?:SDKTheme · i18n?:Partial<I18nMessages> · floatingInteractionIcons?:{key:string,visible?:boolean}[](image-text-float 图标可见性锁;支持 SYS: 前缀;受控 key:QUESTION/QUESTIONNAIRE/CHECKIN/LOTTERY/LUCKYMONEY/COUPON;未配置默认可见,⚠️ 配置形状待服务端/集成方校验) · goodsMarketing?:{autoOpenExchangeCoupon?:boolean}(默认 false;false 时兑换券胶囊只发 goods.promotion.click、由宿主自开;true 时 SDK 已自开,宿主不得从该事件重复调用 openGoodsMarketing

LayoutConfigorientation?:'portrait'|'landscape'|'auto'(默认 auto,跟随后台 screenType) · playerFit?:'cover'|'contain'(作用于 <video> object-fit,直播 TCPlayer / VOD 回放均生效;缺省按朝向:竖屏 cover 铺满裁剪消黑边,横屏 contain 等比留黑边——对齐 SPEC AC-L-01) · topOffset?:number|string(顶部安全偏移,默认 0px;App 沉浸式嵌入时避让系统状态栏——TopBar / 公告跑马灯 / 营销活动面板顶部对齐到此值。number 按 px,string 允许 CSS length / calc / env。运行时可 setTopOffset() 覆盖) · chatTabs?:{key,label}[] · modulesOrder?:{chatOffset?} · shortcutComments?:(string|{text,delaySec?})[] · shortcutCommentsEnabled?:boolean(默认 true)

AppModuleConfigsviewerCount · like · gift · goods · security,每项 { enabled?: boolean },默认全开。

遥测与 options.logLevel 完全独立,默认关闭;仅 enabled:true 才启用。第三方 Transport 收到经过字段白名单、采样和裁剪的 v3 batch,其中 ctx.userKey 为明文。

字段 类型 默认 说明
enabled boolean false 总开关
profile 'off'|'errors'|'sampled'|'debug' enabled 时 sampled 上报档位
endpoint string 按 build mode 与 transport 互斥;开发态冲突抛错,生产态关闭遥测并本地告警,不中断 SDK
transport TelemetryTransport 内置 HTTP/Beacon 自定义单一 Sink
identityMode 'hash'|'plain+hash' hash 废弃兼容字段;不再改变身份输出,ctx.userKey 始终为明文
experiments {id,variant}[] [] 最多 16 项短 ID
diagnostic {userKey,expiresAt} 明文 userKey 精确匹配当前 ctx.userKey 且未来不超过 30 分钟时,才允许生产 100% 诊断采样
sampleRate number 0.1 sampled 稳定采样;生产无有效 diagnostic 时最高 0.1,允许调用方降低
batchSize/flushIntervalMs number 20/10000 条数/时间阈值
maxQueue/maxBytes number 100/64KiB 有界队列,硬上限不可提高
appContext TelemetryAppContext 商户/房间/应用/构建/设备上下文;uid 作为明文 ctx.userKeyplaintextIdentity 为废弃兼容字段

appContext 会完整保留宿主传入的页面、应用、构建、引擎字段,SDK 仅用构造参数覆盖 merchantId/activityId。身份字段中,ctx.userKey 上报去首尾空白后的明文用户标识,ctx.deviceKey 继续上报 SHA-256 截断哈希,空用户不生成 userKey。内置 HTTP 使用 text/plain;charset=UTF-8,单批硬上限 48KiB;不上传 token、Cookie、评论正文、完整 URL/拉流地址、headers、原始 response 或 UA。sendBeacon=true 仅表示浏览器接受排队,不代表服务端落库。

遥测 v3 的完整解析对照表为 TELEMETRY-V3-REFERENCE.md。14/14 个事件的 payload 顺序、类型、单位、枚举/位图以及顶层 batch、ctx/stats/sidecars 字段均由同一 manifest 生成;严格解析器遇到未知 code、错误 arity、未知枚举/位图或未登记字段会直接失败,避免导出日志被静默错解。当前 funnel.summary 类型映射为 goods=1、coupon=2、task=3、checkin=4、reward=5、goodsMarketing=6。该门禁只要求客户端生成或导出的请求体可完整解析,不要求证明服务端已接收或落库。

AppEntryModuleId'roomMarketing' | 'lottery' | 'taskReward' | 'productList' | 'commentary' | 'goodsMarketing'roomMarketing = 房间营销统一入口,签到/福袋/券合流,见下「运营入口模块」/「事件 ws.room_activity」)

UiTextSizeConfigPartial<Record<UiTextSizeScene, UiTextSizeMode>>UiTextSizeMode = 'default' | 'large' | 'xlarge'。已登记场景:

UiTextSizeScene 说明 default large xlarge
im.comment.content 评论正文 text-sm/5 text-base/6 text-lg/7
im.comment.nickname 评论 / 送礼 / 普通消息昵称 text-sm text-base text-lg
im.comment.level 评论等级徽标 text-[10px] text-xs text-sm
im.comment.avatar 评论头像(有头像评论的圆形头像尺寸) h-[18px] w-[18px] h-[20px] w-[20px] h-[22px] w-[22px]
im.welcome.content 温馨提示标签与正文 text-sm text-base
im.enter.content 进场消息浮条 text-xs text-sm
im.shortcut.content 快捷评论按钮文案 text-xs text-sm
im.order.content 用户下单悬浮消息(昵称/商品/「立即购买」按钮) text-sm text-base text-lg

「更多面板」字体大小会全场景同档联动(评论 content/nickname/level/avatar + 温馨提示 + 入场 + 快捷评论 + 下单消息,详见下「字号档位」)。welcome/enter/shortcut 三场景仅支持 default/large 两档;未声明的档位回退到 largedefault

const sdk = new LiveSDK({
activityId, token, merchantId,
uiTextSize: {
'im.comment.content': 'large',
'im.comment.nickname': 'large',
'im.comment.level': 'large',
'im.welcome.content': 'large',
'im.enter.content': 'large',
'im.shortcut.content': 'large',
},
})

config.features 统一收口业务 UI 可见性(按钮/入口是否渲染),与 appModules(WS 数据模块开关 / 数据源)正交:appModules.goods.enabled=false → 数据空、面板渲染空;features.goods['cart.open'].enabled=false → 面板在、购物车按钮隐。

FeatureKey = 该功能激活时 emit 的精确事件键(单一真相源,1:1 映射,无平行词表)。enabled:false 隐藏入口后,该事件无法由 SDK UI 触发。

FeatureKey 默认 说明 对应事件
topbar.userCenter true 右上角「个人中心」入口 topbar.userCenter
topbar.businessInfo 跟随 server 右上角「经营信息」入口(默认回退 liveStore.businessInfoToggle topbar.businessInfo
goods.cart.open true 商品橱窗标题栏「购物车」入口 goods.cart.open
goods.cart.add true 橱窗列表卡「加入购物车」按钮(仍受积分商品/售罄门控叠加) goods.cart.add
goods.order.open true 商品橱窗标题栏「订单」入口 goods.order.open
more.quality true 「更多」面板清晰度入口 + 底栏更多按钮清晰度下标(仍受多档流 + DefinitionPlugin 门控叠加) more.quality
more.fontSize true 「更多」面板字体大小入口 more.fontSize
more.cleanScreen true 「更多」面板清屏入口 more.cleanScreen
more.redPacket true 「更多」面板「我的红包」入口(emit 后 openRedPacket() more.redPacket
more.score true 「更多」面板「我的积分」入口(宿主导航) more.score
more.coupon true 「更多」面板「我的券码」入口(宿主导航) more.coupon
more.order true 「更多」面板「我的订单」入口(宿主导航) more.order
more.feedback true 「更多」面板「意见/反馈」入口(emit 后转发 topbar.feedback more.feedback

可见性优先级:运行时(setFeature/updateFeatures)> 构造期 config.features > 服务端兜底/默认。三层都未设 enabled 时回退最后一层 → 零配置即今日行为。

// 构造期:隐藏个人中心 + 橱窗购物车入口
const sdk = new LiveSDK({
activityId, token, merchantId,
features: { topbar: { userCenter: { enabled: false } }, goods: { 'cart.open': { enabled: false } } },
})
// 运行时:增量更新(链式,emit features.update)
sdk.setFeature('topbar.businessInfo', { enabled: true }) // 强显经营信息(覆盖 server off)
.updateFeatures({ goods: { 'cart.add': { enabled: false } } })
sdk.getFeatures() // → 当前 static+runtime 合并快照

FeatureConfig / FeatureItemOptions:namespace 分组(topbar / goods),leaf key = 事件键去首段命名空间(保留后续点,如 goods 组下 'cart.open')。FeatureItemOptions = { enabled?: boolean, order?: number, badge?: number, [key:string]: unknown }order 等为前向兼容预留;badge 见下)。

FeatureItemOptions.badge入口图标(购物车 / 订单)显示数字角标。badge 数字 host-owned(购物车/订单页在宿主侧):

  • 静态初值:构造期 config.features.<key>.badge 播种。
  • 动态更新:运行时 sdk.setBadge(key, n)(专用 API,链式,emit badge.update)。n<=0 视为清空(无角标)。
  • 显示规则n>0 显示;n>99 显示 99+0/未设 隐藏。

⚠️ badge 动态只走 setBadge,勿用 setFeature({badge})(setFeature 管「可见性」,setBadge 管「计数」,职责分离)。setFeature({badge}) 不会生效到角标。

BadgeKey 说明
goods.cart.open 商品橱窗标题栏「购物车」入口图标右上角标
goods.order.open 商品橱窗标题栏「订单」入口图标右上角标
// 静态初值
const sdk = new LiveSDK({ activityId, token, merchantId,
features: { goods: { 'cart.open': { badge: 5 } } } })
// 动态更新(链式,emit badge.update)
sdk.setBadge('goods.cart.open', 3) // 购物车角标 → 3
.setBadge('goods.order.open', 0) // 订单角标清空
sdk.getBadge('goods.cart.open') // → 3

其余 topbar 入口(feedback/redeem/redPacket/task/invite)暂未纳入,仍走各自 server toggle;后续按「扩展契约 SOP」(PLAN-FEATURE-CONFIG.md)迁移。底栏购物车按钮(interact.cart,开橱窗)不纳入,已有 actionbar.update 动态覆盖。


方法 签名 说明
构造 new LiveSDK(config) 创建实例,初始化模块(未拉流/未挂载)
mount (target: string|HTMLElement) => Promise<void> 认证 → 注入凭证 → 挂载 UI → 初始化模块 → emit ready
destroy () => void emit destroy,卸载 UI、断 WS/IM、清定时器与本实例弹框
on / off / once (event, handler) => this 事件订阅(类型安全)
getEmitter () => IEventEmitter 取底层 emitter
getServerTime () => number | undefined 当前校准后的服务端 epoch 毫秒;首个有效服务端锚点到达前返回 undefined,不回退设备时间。锚点来自 config/detail.serverTime、LAPS serverTime / ws.room_config.serverTime,营销 HTTP timestamp 在未锚定时补充
getWatchProgress () => Readonly<WatchProgressSnapshot> 本机真实媒体观看快照;含 total/byKind/state/sequence/reason,服务端任务进度不会写回
setEndpoints (partial: EndpointConfig) => Promise<this> 动态更新端点;相同规范化值 no-op。HTTP 后续请求、WS 换址重连、观看上报后续周期/最终 flush 使用新值
getEndpoints () => Readonly<EndpointConfig> 当前规范化端点快照,不含凭证
use (plugin: IPlugin) => this 注册插件
getModule <T>(id: ModuleId) => T|undefined 取核心模块实例
getAppModule <T>(id: AppEntryModuleId) => T|undefined 取运营入口模块实例
setTheme (theme: SDKTheme) => this 增量改主题,已挂载即施色
setThemeColor (color: string) => this 便捷 = setTheme({primaryColor})
setFontSize (size: string) => this 便捷 = setTheme({fontSize})
setUiTextSize (config: UiTextSizeConfig) => this 增量设置场景字号(runtime > 构造期 uiTextSize),仅保留已登记场景与 default/large/xlarge 合法值;链式、mount 前可用。更多面板「字体大小」内部即用此方法批量联动 content/nickname/level/avatar 四场景
setUiTextSizeScene (scene: UiTextSizeScene, mode: UiTextSizeMode) => this 单场景字号设置便捷方法;非法 mode 会被忽略
getUiTextSize () => Readonly<UiTextSizeConfig> 当前场景字号快照(static+runtime 合并)
setTopOffset (value: number | string) => this 顶部安全偏移运行时设置(number 按 px;string 允许 CSS length / calc / env):归一化后写 store(runtime > static > 0px),emit topOffset.update {value};mount 前可用。TopBar / 公告跑马灯 / 营销活动面板顶部对齐到该值
getTopOffset () => string 当前生效的顶部偏移(归一化字符串,如 '100px' / '0px';runtime > static > 默认)
setCleanScreen (active: boolean) => this 清屏态运行时切换:写 store + emit ui.cleanscreen.changed {active}active=true 进入清屏(隐全部业务 UI),false 退出;mount 前可用(store 构造期即建)。进房默认 false,不持久(刷新/重进重置)
getCleanScreen () => boolean 当前清屏态(true=清屏中,false=正常)
updateFeatures (partial: FeatureConfig) => this 增量更新业务特性(runtime 层深合并),emit features.update {partial};mount 前可用
setFeature (key: FeatureKey, options: FeatureItemOptions) => this 单键便捷设置,emit features.update {partial, key}key = 对应事件键
getFeatures () => Readonly<FeatureConfig> 当前特性配置快照(static+runtime 合并,不含服务端兜底)
setBadge (key: BadgeKey, n: number) => this 入口图标数字 badge 运行时设置(n<=0 清空),emit badge.update {key, value};mount 前可用
getBadge (key: BadgeKey) => number | undefined 入口 badge 当前值(runtime > static;未设返 undefined
showLoading (text?: string) => this 显示全局 loading(可选文案)。全局唯一 overlay,颜色跟随主题色
hideLoading () => this 隐藏全局 loading
modal (opts: ModalOptions) => Promise<boolean> 打开本实例弹框,resolve 确认/取消
dialog (opts: ModalOptions) => Promise<boolean> modal 别名(命令式 Dialog 入口,复用 Modal 内核)。表单/snippet 注入为后续能力
toast (message: string, opts?: { duration?, type? }) => ToastHandle 通用 toast(直采 svelte-sonner),返回 { id, dismiss() }。含 toast.success/error/warning(message)。直播结束自动清场本实例 toast
showToast (opts: { content, duration?, mask? }) => this 轻量 toast(小程序 wx.showToast 风格):全局单例——再次调用仅替换 content 并重置计时(不堆叠)。默认 duration=5000ms 自动关(<=0 不自动关);mask=true 渲染透明蒙层拦截底层点击(默认 false 不拦截);最多两行(line-clamp-2)、最大宽 90%、容器内顶层(z=100000,仅覆盖 SDK 容器,非整屏)。与 sdk.toast()(svelte-sonner 堆叠、整屏)独立并存。链式返回 this
hideToast () => this 隐藏轻量 toast(清计时)。链式返回 this
t (key: I18nKey) => string 取本地化文案
openGoodsMarketing (numIid, opts?:{scoreGoods?}) => void 打开营销弹框,按 numIid 惰性拉取
closeGoodsMarketing () => void 关闭营销弹框
claimMarketingCoupon (couponId: number) => void 领取营销弹框内优惠券
loadMoreMarketingCoupons () => void 加载更多兑换券(分页,对齐 goods-coupon-popup loadMore)
registerMarketingSection (kind, component) => void 注册营销 section 渲染器(未知 kind 不抛错)
claimCoupon (packetId: string) => Promise<{status:'pickup'|'sendCompleted'}> 实时券领取(券=福袋 type=1,上行 6010 + 等 6020 或 8s 乐观回退);委托 roomMarketing entry
joinCheckIn (checkInId?: string) => void 签到参与(省略 id → 取当前 active 签到)。乐观返成功,真实态由 6000/6020 幂等校正
joinLuckyPacket (packetId: string) => Promise<{phase:'attended'|'won'|'lost', awardAmount?}|undefined> 福袋参与(等开奖结果或 8s 回退)
setUiTextSizeScene (scene: UiTextSizeScene, mode: 'default' | 'large' | 'xlarge') => this 单场景字号设置(runtime),同步持久化到 localStorage(key livesdk:uiTextSize),刷新/重进自动恢复;mount 前可用(见下「字号档位」)。注意:仅设单个场景(如 im.comment.content)时,昵称/等级/头像不会跟随——需整条消息统一放大请用「更多面板」或 setUiTextSize 四场景同设
getUiTextSize () => Readonly<UiTextSizeConfig> 当前合并后的字号配置快照({...static, ...runtime}

只读属性config(归一化配置)· i18n · stores(见下)。

mount() 仅支持腾讯云直播(liveType=6),其它类型 emit auth.error 中止;数据类降级 emit auth.warning 不阻断。失败抛 AuthError

显示文案 mode Tailwind class 实际字号
默认 default text-sm/5 14px
large text-base/6 16px
xlarge text-lg/7 18px
  • 作用范围:「更多面板」字体大小是整条 IM 消息的统一缩放——同时联动 im.comment.content(正文)、im.comment.nickname(昵称)、im.comment.level(等级徽标)、im.comment.avatar(头像)、im.welcome.content(温馨提示)、im.enter.content(进场浮条)、im.shortcut.content(快捷评论)、im.order.content(用户下单悬浮消息)八个场景,大字体下昵称/头像/温馨提示/进场/下单消息同比放大,避免只有正文放大的割裂观感。
  • 持久化:用户选择写入 localStorage(key livesdk:uiTextSize),刷新/重进自动恢复。
  • 优先级:runtime(持久化) > SDKConfig.uiTextSize(static) > default
  • mode large 显示为「中」:mode 值为公开契约不可改名,文案经 i18n 解耦。
  • 单场景写入:集成方也可仅设 im.comment.content 等单个场景(setUiTextSizeScene),未设场景回退 default——此路径下昵称/头像/温馨提示/进场/下单消息不会跟随正文缩放,如需整条 IM 消息统一放大请全场景同设或用「更多面板」。

sdk.on(name, handler)。下表含 payload 类型。

事件 Payload 触发
ready {detail: RoomDetailBody} mount 完成;detail 为直播详情对象(title 直播间名称 / liveStatus / extendSet.coverImg 封面 / planBeginDate 计划开播 等)
destroy undefined destroy()
error {code,message} 全局错误
auth.success {streamUrl,qualityList} 认证成功;qualityList 为服务端归一化清晰度列表
auth.error {code?,message} 身份类失败,中止 mount
auth.warning {reason,branch?:'configDetail'|'replayAddress'} 数据类降级
事件 Payload 触发
live.status LiveStatus 状态变更
live.orientation Orientation 横竖屏确定
live.config Record<string,unknown> 后台配置推送
live.thumb {thumb} 点赞总数(LAPS 心跳/登录)
live.startTime number 预告计划开播时间(ms)
live.coverImg string 预告封面图
事件 Payload 触发
player.ready undefined 可播
player.playing / player.pause undefined 播放 / 暂停
player.waiting / player.stalled / player.recovered undefined 缓冲 / 中断 / 恢复
player.firstframe undefined 真首帧(一次性)
player.ended undefined 播放结束
player.error {code,message} 播放错误
player.duration {duration} 时长(VOD)
player.timeupdate {currentTime} 进度(节流 250ms,内部)
player.replay.segment {index,total} 回放切段
player.quality.changed {code,name} 兼容事件:请求目标/回滚档位已改变,不代表目标流已经真实出帧
player.quality.switching {switchId,fromCode,toCode,name,reason} 运行时切流事务开始;当前源继续播放,目标源开始隐藏预加载;reasonmanual|downgrade|upgrade|decode-error
player.quality.switched {switchId,code,name,reason} 目标 generation 已取得真实进度并完成画面交换;新接入方应以此作为完成事件
player.quality.switch-failed {switchId,fromCode,toCode,name,reason,recovery,error} 切流失败;recoveryrolled-back|next-lower|noneerror 为可序列化 {code,message}
player.quality.switch-cancelled {switchId,fromCode,toCode,name,reason,cause,supersededBySwitchId?} 切流取消;causesuperseded|destroy|terminal

player.quality.changed 仅表示 SDK 的目标档位状态已经改变,是兼容旧事件;player.quality.switched 才表示目标流真实出帧。推荐通过同一 switchIdswitching → switched/switch-failed/switch-cancelled 判断完整生命周期。

同一事务对目标 URL 最多内部重试一次,并复用播放器的协议候选;重试不重复发 switching/changed。运行时切档保留当前播放器继续出画面,在隐藏、静音的 standby 播放器预加载目标源;目标取得 loadstart → playing → progress 证据后才交换显示层并释放旧播放器。音量/静音交接使用 Player 通过公开控制方法维护的缓存真值。预加载失败、超时或被新请求替代时只释放 standby,当前源不换源、不回切;非 superseded 取消还会把档位、URL 与 store 恢复为 confirmed 真值。切流期间调用 pause() 会同步暂停两个播放器并挂起提交/超时,调用 play() 后恢复事务。首次起播、VOD 与故障自愈仍是单播放器路径。

双槽位存在时,平台和声音状态均不改变预加载路径:iOS/WebKit 已开声、预加载中开声及微信桥接开声都继续保留 active 画面并预加载原 standby,不得对 active 直接换源。开声只同步声音真值;交换时不修改旧 active 的 muted 状态,旧 active 停止后再把缓存音量/静音应用到新 active。媒体画面层固定为 z-index: 0,控制条和水印覆盖层为 z-index: 10;聊天输入仅由布局层 ChatInput 承载,Player 内不重复渲染 Danmu 输入框。

事件 Payload 触发
chat.message ChatMessage 新消息
chat.pinned ChatMessage|null 置顶变更
chat.mute boolean|{muted} 全员禁言开关
im.ready / im.reconnected undefined IM 就绪 / 重连
im.user_banned / im.user_kicked {userId,reason?} 用户被禁言 / 踢出
im.error / im.net_error {code,message} IM 致命错误 / 网络断开
im.warning {code,message} 缺凭证休眠告警
事件 Payload 触发
interact.like {delta,count?,reaction?:ReactionKey} 点赞帧
interact.like.total {total} 点赞累计总数(角标权威源)
interact.gift GiftPayload 礼物
interact.cart / interact.share undefined 底栏购物车 / 分享点击
interact.more {action?} 底栏更多点击
user.join UserProfile 用户进房
room.viewerCount {count} 观看数(每 10s 轮询)
事件 Payload 触发
goods.show GoodsItem 展示商品卡
goods.hide {goodsId} 隐藏商品卡
goods.list GoodsCardItem[](讲解品置顶 + 其余 seq 升序 + numIid 确定性 tiebreak;项含可选 marketingActivities 营销摘要) HTTP 首屏全量列表就绪
goods.list.error {message?} HTTP 商品列表拉取失败(fail-soft,橱窗内显重试入口)
goods.list.retry undefined 商品橱窗「重新加载」按钮点击 → SDK 触发 GoodsListFetcher 重新拉取首屏列表(host 可监听做埋点/二次处理)
goods.buy {numIid,scoreGoods?} 点购买/兑换按钮(列表卡 + 浮窗卡统一;host 接管下单)
goods.card.click {numIid,name?,scoreGoods?} 商品卡片整体点击(列表卡 + 浮窗卡空白区,购买/加车/促销按钮已 stopPropagation)。host 通常开商详页
goods.promotion.click {numIid,scoreGoods?} 兑换券胶囊点击通知:autoOpenExchangeCoupon=false 时 host 可自开;true 时 SDK 已自开,本事件仅作通知/埋点,host 不得重复打开
goods.cart.add {numIid,scoreGoods?} 列表卡「加入购物车」按钮点击(仅非积分商品、未售罄)
goods.cart.open undefined 商品橱窗标题栏「购物车」入口点击(host 开完整购物车页;区别于 interact.cart,后者由底栏购物车按钮发出、用于开橱窗)
goods.order.open undefined 商品橱窗标题栏「订单」入口点击(host 开订单列表)
goods.config ⚠️ Record<string,unknown> 商品配置推送
goods.open / goods.close undefined 商品面板开 / 关
goods.marketing.open {numIid} 营销弹框打开
goods.marketing.show MarketingDetail 营销详情就绪(sections 可含 fullReduction 满减/满赠摘要,本地归一不发请求)
goods.marketing.error {numIid,message?} 营销拉取失败(可重试)
goods.marketing.close undefined 营销弹框关闭

⚠️ 行为变更(破坏性):浮窗卡(HotSellCard)购买按钮原外抛 interact.cart,现统一为 goods.buy(与列表卡一致)。依赖浮窗卡 interact.cart 的宿主需迁移:改监听 goods.buy 做下单;如需开橱窗,监听底栏 interact.cart。 事件冒泡约定:点购买 / 加车 / 促销按钮触发卡片整体 goods.card.click(已 stopPropagation);点卡片空白区才触发。

兑换券入口与弹框(按 scoreGoodsInfo.useCouponType 分流)

积分商品(scoreGoods=true)的兑换券胶囊与 goods.marketing.* 弹框按 useCouponType 三态分流,对齐 live-app:

  • useCouponType=1(商品券):入口胶囊数量取 scoreGoodsInfo.couponNum;弹框标题「可用兑换券」,并行请求分页券列表(loadMoreMarketingCoupons 加载更多)与用户已有数量,提示行展示「需要 X 张 / 已有 Y 张」(mine 缺失或请求失败按 0,不整行隐藏),券卡片显示「已获得」;展示万能券提示。
  • useCouponType=2(普通券+万能券):入口胶囊数量累加内联 scoreGoodsInfo.couponList 计数;弹框标题「商品所需兑换券」,直接归一/合并/过滤零计数内联列表(不发分页与已有数量请求),展示「需要/已有」「已获得」;supportUniversalCoupon=true 时展示「数量不足可使用万能券」提示。内联列表为空时不渲染胶囊。
  • useCouponType=0/空(不使用):不渲染兑换券胶囊、不打开兑换券弹框(即便 couponNum/couponList 有值)。

向后兼容:商品不在列表(上下文 found=false)且 scoreGoods=true 时程序式 openGoodsMarketing 回退为类型 1 分页分支(旧 SDK 行为),不因上下文缺失抛错;found=falsescoreGoods=false 走普通优惠券 coupon section。autoOpenExchangeCoupon 默认值与 goods.promotion.click 语义不变。

房间营销(roomMarketing:签到 / 福袋 / 券)

Section titled “房间营销(roomMarketing:签到 / 福袋 / 券)”

LAPS 6000/6010/6020 + HTTP 79952 首屏 → lapsBridge 收敛为单一事件族 ws.room_activity(判别联合 RoomActivityOp),由 RoomMarketingEntryroomMarketingStore.dispatch 驱动 cards / 弹窗队列 / 服务端时钟。参与经 sdk.claimCoupon / joinCheckIn / joinLuckyPacket(见上「实例方法」)。

事件 Payload 触发
ws.room_activity RoomActivityOp(判别联合:coupon_create / lucky_create / checkin_start / checkin_end / display / finish / result 6000 签到/福袋建卡显隐结束、6020 本人开奖结果(仅本人 agentId 命中)。券=福袋 type=1,create 由 luckyPacket.type 路由,display/finish/result 按 cards[id].kind 回查路由
ws.server_time number(服务端毫秒) 每帧服务端时钟锚定 → roomMarketingStore.setServerTime(同钟铁律:倒计时基准与锚点同源同 floor)
ws.reconnect {attempts} 重连 → resync(15s cooldown + in-flight 合并 + pruneGhost + 重拉首屏建卡)

互动工具聚合抽屉(FloatMoreDrawer)FloatBar「更多」点击后立即打开 60% 高度 contained 抽屉(overlayVariant=light),同时触发 SDK 内部 _refreshInteractiveTools() 静默拉取 79952 并 reconcilePrime(不自动弹详情)。列表数据来自 roomMarketingStore.interactiveItems(签到/福袋/券时间轴);点击卡片仅 show(id),抽屉保持打开,详情层(CouponLayer/CheckInLayer/LuckyLayer)外壳 z-[1200] 覆盖抽屉。刷新失败保留旧列表;refreshing 仅显示非阻塞指示器。无公开刷新 API

⚠️ 已废止事件(ActivityPanel/liveStore.coupons 体系,勿监听)activity.change / activity.result / activity.participate(旧签到福袋面板,已删 ActivityPanel);coupon.show / coupon.open / coupon.close(旧 CouponStack 徽标链路,已归 roomMarketingStore.floatItems);ws.coupon_dispatch(旧 6000/6020 回落通道,已归 ws.room_activity)。

左上角营销互动浮窗(image-text-float)⚠️

Section titled “左上角营销互动浮窗(image-text-float)⚠️”
事件 Payload 触发
imagetext.change ImageTextChange LAPS check.in.* / lucky.packet.* 映射为浮窗数据变更;内部 ImageTextEntry 消费
imagetext.entry.click {type,current,stableKey} 用户点击浮窗图标;ImageTextEntry 路由到对应面板,集成方也可监听自定义面板
imagetext.icon.close {stableKey,type} 用户关闭单个浮窗图标
imagetext.more.click undefined 用户打开「更多」抽屉
checkin.show / checkin.close {currentId} / undefined 签到图标点击 / 签到面板关闭
checkin.detail CheckInDetail 签到详情拉取成功
checkin.submit_result {success,message} 签到提交结果
checkin.kickout {banTips} 截止未签到且活动要求禁止观看
事件 Payload 触发
watch.progress WatchProgressSnapshot 真实媒体证明、状态或累计变化;服务端秒数不写回
watch.state.changed {previous,current,snapshot} idle/watching/suspended/ended 状态变化
watch.report.calibration.* WatchReportEventMeta 校准开始、ACK、stale、失败或 best-effort 降级
watch.report.queued/attempt/retry/ack/rejected/parked WatchReportEventMeta ordinary/Range 上报漏斗(脱敏元数据)
watch.report.exit.queued/kickout.queued/finalize.error/final.abandoned WatchReportEventMeta 退出、踢出与最终对账诊断
duration.change {totalMs,seconds} 废弃兼容别名;WatchClock 每跨 5s 映射一次
duration.report {seconds,success} 废弃兼容别名;仅 ordinary 逻辑 ACK/终态失败
app.module.init / app.module.destroy {moduleId} app 模块生命周期
事件 Payload 触发
features.update {partial: FeatureConfig, key?: FeatureKey} updateFeatures(无 key)/ setFeature(带 key)后 emit
badge.update {key: BadgeKey, value: number | undefined} setBadge 后 emit;value=undefined 表示清空(n<=0
topOffset.update {value: string} setTopOffset 后 emit;value 为可直接用于 CSS 的归一化长度串(如 '100px'
ui.cleanscreen.changed {active: boolean} setCleanScreen 后 emit;active=true 进入清屏(隐全部业务 UI),false 退出
事件 Payload 触发
ws.connected / ws.disconnected undefined / {reason?} 连接 / 断开
ws.reconnect {attempts} 重连尝试
ws.error / ws.auth_failed {code,message} WS 错误 / 认证失败
ws.room_status {status,reason?} 5000 房间状态
ws.room_config Record<string,unknown> 5010 房间配置
ws.kicked {roomId,reason?} 1001 强制移出
ws.enter_message {roomId,data:{type,content}} 5020 进场消息
ws.audience_change {agentId,roomId,eventType,eventData?} 2020 观众变更(1禁言/2取消/3封禁/4踢出)
ws.message / ws.server_time WSMessage / number 原始帧 / 服务端时间(内部)
ws.commentary ⚠️ / ws.goods_config ⚠️ Record<string,unknown> 讲解 / 商品推送
事件 Payload
lottery.start / task.new / commentary.push Record<string,unknown>
lottery.open|close · task.open|close · commentary.open|close undefined

⚠️ coupon.show / coupon.open / coupon.close / ws.coupon_dispatch 已废止(券归 ws.room_activity + roomMarketingStore)。 完整事件名常量见导出的 SDK_EVENTS


type LiveStatus = 'not_started'|'ongoing'|'ended'|'banned'|'paused'|'error'|'expired'|'playback'
// 对应服务端 102/101/103/104/105/106/107/108
// not_started(102 预告态) 仍展示 IM 聊天模块,支持用户聊天;结束/禁播/异常等阻断态仍展示状态遮罩。
type ReactionKey = 'heart'|'ghost'|'qbox'|'rockhand'|'joystick'
interface ChatMessage {
id; userId; userName; userAvatar?; content; timestamp
type: 'text'|'system'|'pinned'|'enter'|'welcome'|'comment'
template?; level?; levelName?; levelColor?; levelIcon?; welcomeTitle? // 等级/欢迎语扩展
}
interface GiftPayload { giftId; giftName; giftIcon?; userId; userName; count }
interface GiftAnimation { userId; giftId; giftName; count; timestamp }
interface UserProfile { userId; userName; avatar?; level? }
interface GoodsItem { id; name; price; image?; url?; sellOut?; priceHidden? }
interface GoodsCardItem { numIid; name; price; image; url?; explainStatus; floatingStatus; sellOut; priceHidden; hasPublish; hotNum; reminderType; reminderText?; quantity?; seq?; tags?; isPresell?; goodsType?; scoreGoods?; scoreGoodsInfo?; marketingActivities?; supportUniversalCoupon? }
// GoodsCardItem.scoreGoodsInfo(积分商品详情,scoreGoods=true 时存在):
// score?; price?; couponNum?; couponName?; couponId?; couponList?; exchangeNum?; limitNum?
// useCouponType?: 0|1|2 —— 0/空=不使用(无兑换券胶囊/弹窗)、1=商品券(couponNum + 分页接口,列表态 couponList=null)、
// 2=普通券+万能券(列表态内联 couponList,实测项 {couponNum,couponId,couponName};code/consumeNum/count/name 可选未下发)
// couponList[] 项:{ couponNum?; couponName?; couponId?; code?; consumeNum?; count?; name? }
// GoodsCardItem.supportUniversalCoupon?: boolean —— 是否支持万能券(商品项顶层;仅 useCouponType=2 消费;缺失→false)
interface MarketingActivity { actId; actType; actName } // 商品关联营销摘要(goodsCard/get marketingActivities 内联,仅三字段,无明细)
interface FullReductionSectionData { activities: MarketingActivity[] } // fullReduction section 数据(v2 摘要级)
// 兑换券(积分商品)section 数据;ExchangeCouponSectionData.couponType 决定渲染分支
interface ExchangeCouponSectionData {
coupons: Array<{ couponNum?; couponName?; name?; couponId?; code?; consumeNum?; count? }>
couponType?: 1 | 2 // 1=商品券(分页)/2=普通券+万能券(内联);marketingApi 必填,驱动渲染分支
count: number // 商品所需兑换券总数(type1=scoreGoodsInfo.couponNum / type2=sum(couponList)),非券种数
mine?: number // 用户已持有数(mySelfCouponNum;仅 type1)
isSupportUniversalCoupon?: boolean // 是否展示万能券提示(仅 type2)
hasMore?; pageNo?; loadingMore?; loadMoreError? // 分页(仅 type1)
}
interface LikeBurst { id: number; reaction: ReactionKey; count: number }
interface SDKError { code: number; message: string }

sdk.getModule<T>(id)id ∈ liveRoom|player|im|interact|user|marketing|security

方法 说明
play() / pause() 播放 / 暂停
setVolume(v) 音量 [0,1]
seek(time) 跳转(仅 VOD)
attachElement(el) 绑定 video 元素
initStream(url) 手动设流地址并起播
setReplayList(list) / getReplayList() 注入 / 取回放分段
currentReplayIndex / isVodPlaying / isReplay 只读 getter

能力:直播 HLS/FLV(TCPlayer)+ VOD 多段回放(分段容错、整轮重试 3 次、15s 超时探测);直播错误指数退避重连。

方法 说明
sendTextMessage(text) 发文本
sendCustomMessage({type,data?,description?}) 发自定义消息
sendLikeMessage(count?) / sendGiftMessage(gift) 发点赞 / 礼物
getHistoryMessages(count=20) 拉历史
getOnlineCount() / getLikeCount() 在线数 / 点赞数
getAdapter() 取适配器(userSig 重登用)
setCredentials(creds) 注入 IM 凭证(init 前)

凭证优先级:config.tim > 认证注入。缺凭证 → emit im.warning 并休眠。

sendLike(count?) · sendGift(gift)(IM 不可用时降级本地 emit)。

方法 / 属性 说明
setProfile({ nickName?, avatar? }) 运行时更新昵称 / 头像并 sync 到 TIM updateMyProfile
refreshUserSig(newSig) userSig 过期重登
setUserId(id) 设置 userId
userName · avatar · levelId 只读;levelId 来自 auth ve/token.agentLevelId,不可宿主注入

构造期可通过 config.user 注入昵称 / 头像;mount 时与 JWT 昵称合并(宿主 > JWT > userId)。发评时 TIM cloudCustomData 只附 { levelId },收端用 live.memberLevels 匹配等级徽章。

const sdk = new LiveSDK({ activityId, token, merchantId, user: { nickName: '小明', avatar: 'https://...' } })
await sdk.getModule('user')?.setProfile({ avatar: 'https://new-avatar.png' })

无 host 方法;init() 内拉房间元数据并 emit live.* / room.viewerCount。状态码 101–108 → LiveStatus

showGoodsCard(goodsId) · hideGoodsCard() —— 占位空实现(Phase 2)。当前商品能力走 entry 模块 productList/goodsMarketing

setWatermark(text) · clearWatermark() —— 占位空实现(Phase 2)


构造期实例化,config.appModules.<key> = { enabled:false } 可关。默认全开。

模块 key 方法 / getter emit
ViewerCount ✅ viewerCount count · setCount(n) room.viewerCount
Like ✅ like total · like(userId,delta=1) interact.like.total
Gift ✅ gift queue · sendGift(p) · dequeue() interact.gift
Goods ✅ goods visibleGoods · show(g) · hide(id) goods.show / goods.hide
Security ✅ security isContentAllowed(c) · checkRateLimit(uid)
  • Likelive.thumb(服务端权威)+ interact.like(增量)合并算总数。
  • Security(app 层,区别于 core security 🚧):聊天限流 10 条/秒 + 非空校验。
  • WatchClock ✅(Player 内部,非 appModules):播放意图 + 真实媒体进度双门控,live/replay 分项、source epoch、watchdog 与 48h 稳定用户 scope 持久化;不持有任务/HTTP 状态。旧 DurationTracker 网络链路已不可达且不再从主包导出。

运营入口模块(entryModules)⚠️

Section titled “运营入口模块(entryModules)⚠️”

WS 驱动的运营浮层,config.entryModules 选择启用(默认全开)。多数 open()/close() 仅发信号事件,UI 由集成方或内置组件渲染。

模块 id 命令式方法 主要 emit 状态
房间营销(签到/福袋/券统一) roomMarketing prime(roomId)(首屏 HTTP 79952)resync(roomId)(重连)经 SDK:claimCoupon / joinCheckIn / joinLuckyPacket ws.room_activity(订阅);6010 上行 reportCheckIn / reportLuckyPacketJoin
抽奖 lottery open() close() lottery.start/open/close ⚠️
任务奖励 taskReward open() close() refresh() getState() subscribe() receiveOrdinaryTask() acknowledgeReward() task.new/open/close/state.changed/reward.present/reward.closed/receive.result ✅(ordinary/Range;fence/finalAck 联调 ⚠️)
讲解 commentary open() close() commentary.push/open/close ⚠️
商品列表 productList open()(惰性拉列表)close() goods.config/open/close/list/show/hide ✅(推送 ⚠️)
商品营销 goodsMarketing 经 SDK:openGoodsMarketing / closeGoodsMarketing / claimMarketingCoupon goods.marketing.*

⚠️ = payload schema 由 5010/6000/7000 LAPS 帧推断,测试环境无真实下行,上线前须以真实信令校验goodsMarketing 为命令式(无 WS 订阅);taskReward 的 HTTP 配置/上报/领奖链路已实现,只有 task.new WS 子字段与服务端 fence/finalAck 能力仍需联调。

⚠️ 已废止 entry:旧 coupon(优惠券 open()/close() + coupon.* 事件)、imageTextFloat(营销互动浮窗 + checkin.show)、checkIn(签到面板 submit)已被统一 roomMarketing 取代(详见 SPEC-ROOM-MARKETING.md)。勿据此集成。


响应式状态,供自定义 UI 读取。_ 前缀为内部方法。

Store 暴露名 关键状态 公开方法 存在条件
live live status viewerCount title orientation startTime coverImg previewText endText countdownEnabled replayList trailerUrl kicked serverTime(同 getServerTime(),毫秒)buyingFrenzy shortcutComments memberLevels · 派生 videoState isPortrait/isLandscape setRoomConfig(cfg)serverTime 会重校时实例统一时钟) 总是
player player isPlaying isPaused volume quality qualityList manualMode ready currentTime duration buffering error · 派生 isMuted progress hasError setVolume setQuality setQualityList setManualMode switchQuality(code) getQualityList() setControlsVisible toggleControls 总是
chat chat messages(≤1000) pinned unreadCount muted userMuted userBanned banTips historyLoaded sendMessage loadHistory setSelfId setSelfName setSelfAvatar setMuteStatus setWelcomeConfig 总是
enterMessage enterMessage current{item:{id,userName,timestamp},playKey}null _destroy(内部清理) mount 后;受 liveWatch.enterMsgSwitch===1 门控
interact interact likeCount likeBursts(≤30) giftQueue sendLike consumeBurst(id) removeGift(id) 总是
user user profile authenticated levelId · 派生 userId userName avatar —(只读) 总是
goodsList goodsList goods:Map · getter list floatCard loaded(首帧推送前 false,UI 据此渲染骨架而非空态) applyChange(payload) getByNumIid(numIid)(按 numIid 同步取商品快照,供满减摘要本地归一) productList 启用时
marketing marketing open numIid scoreGoods loading sections error setOpening(numIid,scoreGoods) setReady setError reset goodsMarketing 启用时
roomMarketing roomMarketing cards(Record<id,RoomActivityCard>) · 派生 currentModalId currentCard floatItems(visible 卡按 createTime 降序) interactiveItems(互动工具时间轴) refreshing(静默刷新中) serverNowSec clockAnchored(未锚定倒计时显示 00:00 dispatch(op) show(id) dismiss() reconcilePrime({ops,liveIds,retiredIds}) primeDispatch(ops) primeShow(id) participateCheckIn(id) participateLucky(id) registerPickup(id) setRefreshing(v) setServerTime(ms) pruneGhost(ids) getServerNowMs() reset() roomMarketing 启用时(默认)
loading loading visible text settled show(text?) hide() settle() 总是(构造期即建)
topOffset topOffset resolve()(runtime > static > '0px' setStatic(value?) set(value) 总是(构造期即建)
cleanScreen cleanScreen get()true=清屏中) set(v: boolean) 总是(构造期即建)
uiTextSize uiTextSize resolve(scene) · snapshot() setStatic(config) update(partial) setScene(scene, mode) 总是(构造期即建)

全局 loadingmount() 一调用即在容器上独立挂载一个唯一 overlay(先于 LiveRoom,覆盖 auth 网络阶段),默认 visible=true。「首帧可见」——player.firstframe 真首帧(首个真 playing、解码出帧,区别于 player.playing 的 ‘play’ 意图)、可播态 player.error、或进入终态 live.statusnot_started/ended/paused/banned/error/expired,由 StatusOverlay 接管)任一先到 → 自动收起(绝不卡死)。中途卡顿(player.waiting/stalled)复用同一 overlay 显隐,恢复即收起。颜色跟随主题色 --primary。对外/对内可用 showLoading(text?) / hideLoading() 手动控制(全局唯一,不会出现两个 loading)。

聊天敏感词:发送端命中 → 本地影子回显(仅本人可见);接收端命中 → 丢弃;无 matcher/异常 → fail-open 放行。

进场消息浮条:liveWatch.enterMsgSwitch===1 时启用,消息源为 IM user.join(含本人进房自进场事件);enterMessage store 以 FIFO 队列单条展示,UI 由 NotificationMessage 在 IM 消息列表上方渲染 3s 右进左出动画。同用户 60s 窗口内重复进场去重;enterMsgSwitch!==1 或缺省时不展示。

直播预告态(live.status='not_started' / 服务端 liveStatus=102):状态层继续展示封面、预告文案、倒计时,但 IM 聊天面板与输入栏保持展示和可操作;结束、禁播、暂停、异常、过期等阻断态仍由状态层接管。


SDKTheme 字段(全可选,局部应用)映射到挂载容器上的 CSS 变量——颜色字段走 shadcn token(HSL 通道,传 hex 自动转通道),其余走无前缀自定义属性;默认值在 app.css。

字段 CSS 变量 默认 说明
primaryColor --primary hsl(10 100% 63%)(珊瑚) 主色;hex→HSL 通道,供 bg-primary/text-primary/bg-primary/10
backgroundColor --background 0 0% 100% hex→HSL 通道
overlayColor --overlay-color rgba(0,0,0,.6) 原值
chatBgColor --chat-bg-color rgba(0,0,0,.4) 原值
textColor --foreground 222.2 84% 4.9% hex→HSL 通道
fontFamily --font-family 系统字体栈 原值
fontSize --font-size 14px 原值
radius --radius 0.5rem 原值

次色 --secondary: 330 81% 60%(粉)+ --secondary-foreground: 0 0% 100% 在 app.css 固定(非 SDKTheme 字段),供 bg-secondary/text-secondary。 旧 --live-* / --livesdk-* 前缀变量与 applyTheme/DEFAULT_THEME/ThemeConfig 已移除(统一 shadcn token)。

初始:options.theme;运行时:setTheme / setThemeColor / setFontSize(增量合并,已挂载即施色,未挂载缓存到 mount)。

场景字号不走全局 fontSize,而是通过 config.uiTextSize 或运行时 setUiTextSize / setUiTextSizeScene 控制。它只影响已登记的 IM 文案场景,不会整体缩放 SDK UI。


  • config.locale(默认 'zh-CN',未知值告警回退)。当前内置 locale:zh-CN
  • config.options.i18n: Partial<I18nMessages> 覆盖部分文案。
  • 取值:sdk.t(key)(仅接受已知 I18nKey)。
  • 文案分类(共 67 key):status.*(状态浮层)· chat.*(输入/消息)· player.*(播放控件)· interact.*(底栏)· goods.*(商品橱窗/卡片:标题/加载/空态/拉取失败/失败描述/重试/购物车·订单入口/加车/讲解中/已抢光/促销/抢购/兑换/待开价/关闭)· coupon.label · room.viewerCount · task.entry · gift.sent · milestone.default · hotSell.cta · more.*(更多面板:字体大小、清屏)· common.cancel(通用取消)。
  • 底部聊天输入框默认 placeholder:chat.input.placeholder = 快来和大家聊聊吧~;集成方仍可通过 config.options.i18n 覆盖。

新增 key(字号设置 / 清屏 / 通用取消)

key 文案
more.font_size 字体大小
more.cleanScreen 清屏
more.red_packet 我的红包
more.score 我的积分
more.coupon 我的券码
more.order 我的订单
more.feedback 意见/反馈
more.font_size.default 默认
more.font_size.large
more.font_size.xlarge
player.cleanScreen.exit 退出清屏
common.cancel 取消

sdk.modal(opts): Promise<boolean>(resolve true=确认 / false=取消/关闭)。归属本实例,destroy() 仅关本实例弹框。

ModalOptionstype?:'info'|'danger'(默认 info) · title? · content?(纯文本)/ html?({@html},自行防 XSS) · confirmText?(默认“确认”) · cancelText?(传了才显示取消按钮) · confirm?/cancel?:()=>void|Promise(异步,报错则阻塞关闭) · singleton?(true 先关其它弹框)。

弹框挂载目标自带独立 .livesdk-container 样式边界;单点登录踢出等终态 Modal 即使在 sdk.destroy() 后按契约留屏,Tailwind/embed 样式仍持续生效,直至弹框关闭。

浮层组件(Dialog / Drawer / Toaster / Empty)✅

Section titled “浮层组件(Dialog / Drawer / Toaster / Empty)✅”

命令式:sdk.dialog(opts) = sdk.modal 别名;sdk.toast(msg) / .success / .error / .warning(直采 svelte-sonner,多实例共享唯一全局 Toaster + 实例级 id 追踪,destroy()/直播结束仅清本实例)。

轻量 toast(小程序 wx.showToast 风格,独立于 sdk.toast):sdk.showToast({ content, duration?, mask? }) / sdk.hideToast()。全局单例——再次 showToast 仅替换 content 并重置计时(不堆叠、不闪烁两次);默认 5s 自动关(duration<=0 不自动关,仅 hideToast 手动关);mask=true 渲染透明蒙层拦截底层点击(默认 false → 点击穿透不挡操作);最多两行、最大宽 90%、容器内顶层(z=100000,仅覆盖 SDK 容器,非整屏——渲染层挂载于 SDK 容器内,absolute inset-0。SDK 内部核心层亦可经 this.showToast() 调用;destroy()/直播结束自动清场。多 LiveSDK 实例共享同一单例(符合「一次只一个」语义)。

声明式组件(we-livesdk 顶层导出,类型 DialogProps/DrawerProps/EmptyProps):

组件 形态 关键 props
Dialog bits-ui 直采,居中卡 open($bindable) · title/content/html · type · confirmText/cancelText · confirm/cancel(异步) · onConfirm/onCancel/onOpenChange · contained(默认 false=body fixed) · dismissible(默认 false 防误触) · showClose/hideButtons
Drawer 原生底弹(弃 vaul,无手势关) open($bindable) · title/description/descriptionHtml · showClose/showSubmit/submitText · overlayVariant · safeAreaBottom(默认 true,底部 env 安全距离) · children/footer(Snippet) · contained · onClose/onClosed(150ms)/onSubmit/onOpenChange · defer 字段(snapPoints/非 bottom direction 等)保留类型、dev warn、prod 降级 MVP
Toaster svelte-sonner <Toaster>(去 mode-watcher) 由 SDK 构造期自动挂载(全局唯一),一般无需手动渲染
Empty 通用空态占位(居中 + 通用图标) text(默认「暂无数据」) · description · icon(默认通用 lucide Inbox,传任意 lucide 图标覆盖) · iconSize(默认 48) · class · testid(默认 empty) · children(Snippet,放重试按钮等)。商品橱窗(暂无商品)/营销面板(暂无优惠券)空态已复用

Dialog preventScroll={false}(不锁宿主 body);Drawer 用 --vh 约束高度(min 30% / max 80%,禁裸 100vh),嵌套 z 由 drawerStore(base 1090 + depth×10)自动管理。商品橱窗/营销面板已收敛为 <Drawer contained>


sdk.use(new Plugin(opts))IPlugin{ id:string; install(sdk); uninstall?(sdk) }。子路径 we-livesdk/plugins

插件 选项(默认) 状态
DanmuPlugin speed(8) fontSize(14) opacity(.85) maxLines(3) 🚧 占位
WatermarkPlugin text position(‘top-right’) opacity(.4) 🚧 占位
DefinitionPlugin defaultQuality(‘preset’) auto(true) allowUpgrade(false) stallWindowMs(10s episode 上限) stallThreshold(可靠帧连续冻结窗,默认3;不可靠时至少4窗) cooldownMs(15s) dropFrameSampleMs(5s) dropFrameRatio(0.1,连续2个且每窗≥30帧才命中) decodeErrorCooldownMs(5s) decodeErrorThreshold(2) · 只读 manualMode + 方法 setManualMode(bool) · manualOverrideMs(@deprecated)

DefinitionPlugin 已公开导出(ESM 主路径 + UMD 全局 LiveSDK.DefinitionPlugin),为 opt-in 插件——宿主须显式注册才生效:

// ESM
import { LiveSDK, DefinitionPlugin } from 'we-livesdk'
const sdk = new LiveSDK({ activityId, token, merchantId })
sdk.use(new DefinitionPlugin())
// UMD(裸 HTML)
const sdk = new LiveSDK.LiveSDK({ activityId, token, merchantId })
sdk.use(new LiveSDK.DefinitionPlugin())

注册后:起播按 defaultQuality 选档、健康 episode/连续丢帧/解码错误驱动自动降档;手动请求被 Player 接纳后立即进入永久 manualMode 锁定,解码错误硬路径仍可降档。默认 defaultQuality:'preset'allowUpgrade:false;选择「自动」或调用 setManualMode(false) 才解除锁定。每个真实 player.quality.switched 都显示一次切换成功提示,不受普通提示的 30 秒冷却抑制;弱网、失败和恢复类普通提示仍限频。「更多」面板清晰度入口需插件存在才显示(门控 hasMultiQuality && getPlugin('definition'))。未注册时手动切档本身仍可用(走 player.switchQuality),但无入口、无自动降级。DanmuPlugin/WatermarkPlugin 仍为 Phase 2 占位实现,注册不报错但暂无实际效果。自定义插件按 IPlugin 实现即可立即生效。

首次 101 起播会在 auth.success 前原子确定最终档位/URL,事件后只启动最终源;108→101 先退出 VOD,再恢复真实手动档(档位消失时用服务端预设并保持锁定)。运行时事务不立即替换当前源,而是在隐藏、静音的 standby 中预加载目标流;仅由目标 generation 的 loadstart + playing + 相对进度增长 提交并交换画面。ready、公共 player.playing 和绝对非零进度均不足以完成切流;预加载失败只清理 standby,旧画面继续播放。iOS/WebKit 和所有声音状态都沿用同一 standby 预加载路径,禁止因开声退回 active 单播放器换源。公开 pause() 会暂停 active/standby、挂起事务门与超时,play() 后恢复;detach 等非替代取消会恢复 confirmed 档位/URL。候选/回滚中间错误只走内部 observer,不污染公开错误态。健康 episode 的冻结窗口最短 1 秒,真实推进立即结束 episode;后台、暂停、VOD、初始化、事务和退避期间禁用丢帧降档,手动锁定/最低档冻结由 Player 同源恢复。


class AuthError extends Error {
name = 'AuthError'
statusCode?: number // HTTP / 业务码
}

mount() 认证失败抛 AuthError 并 emit auth.error,在 mount().catch() 捕获。SDK 仅导出此一个错误类。


子路径 内容
we-livesdk LiveSDK、app 模块、SDK_EVENTSAuthErrorPollingFallbackBrowserTransportbridgeLapsEventsDefinitionPlugin(+ 类型 DefinitionPluginOptions)、浮层组件 Dialog/Drawer/Toaster/Empty/ActionSheet + 类型 DialogProps/DrawerProps/EmptyProps/ActionSheetProps@zan/laps 转出(LapsAdapter LAPS_CMD ROOM_STATUS WATCH_EVENT 等)
we-livesdk/legacy 宿主嵌入安全 ESM:单文件、无 CSS 副作用、首字节 iOS 12 polyfill;需另引 we-livesdk/embed.css
we-livesdk/embed.css 完整宿主嵌入样式:无 preflight;包含 Tailwind utilities、Svelte scoped/TCPlayer 组件样式,构建期统一命名空间到 .livesdk-container
we-livesdk/components Svelte 组件(含 Dialog/Drawer/Toaster/Empty/ActionSheet
we-livesdk/stores Store 工厂
we-livesdk/plugins 插件类
we-livesdk/types 仅类型(SDKConfig SDKEventPayloads DialogProps DrawerProps EmptyProps 等)
we-livesdk/styles 样式(Tailwind + --live-* 默认)
we-livesdk/tailwind Tailwind 配置

UMD:入口 src/lib/umd-entry.ts(含样式)→ dist-umd/livesdk.{umd,iife,esm}.js,全局 LiveSDK,目标 ES2015 / Safari 12 / iOS 12。bundle 首部注入 iOS12 polyfill banner(globalThis + Array.prototype.at + Object.fromEntries),保证 bits-ui Dialog 在 iOS12.0/12.1 模块求值期不崩。

标准 pnpm build / pnpm package 会生成 Svelte package、dist-umd/livesdk.legacy.js、完整 dist/embed.css 并运行 publint;clean checkout 不需要预先存在的 dist-umdpnpm build:umd 额外生成 UMD/IIFE/ESM 演示产物,并同步重建 legacy 入口。发布或宿主构建必须使用标准 build,禁止依赖工作区残留产物。

live-app 启动开发服务(pnpm dev)与测试环境构建(pnpm build:test)均先通过 workspace filter 执行 LiveSDK build:test,确保宿主加载的 legacy/embed 产物固化测试环境端点。


区块 状态
核心:mount/destroy、认证、事件、服务端时钟、主题、i18n、弹框
宿主嵌入:runtime api.baseUrl、严格 host-cache bootstrap、legacy + 完整 embed.css ✅(iOS 12 / Android 7 真机 ⚠️)
播放器(直播 + VOD 回放) ✅(清晰度双槽位预加载切换;iOS 12 / Android 7 真机 ⚠️ 待验证)
IM 聊天、敏感词、禁言/封禁、欢迎语、历史
互动 app 模块(viewerCount/like/gift/goods/security)+ 观看时长
业务特性配置 features(UI 可见性)+ 入口数字 badge
商品列表 / 营销弹框(命令式流程)
房间营销 roomMarketing(签到/福袋/券 + HTTP 79952 首屏 prime + 重连 resync) ✅(79952 响应 shape ⚠️ 待服务端验证)
左上角营销互动浮窗 image-text-float + 签到面板 ⚠️ 已被 roomMarketing 取代(旧 imageTextFloat/checkIn entry 废止)
WS 运营推送 payload(lottery/task/commentary/goods 推送;coupon 推送已归 ws.room_activity ⚠️ 待服务端验证
core marketing / core security 模块方法 🚧 占位
Danmu / Watermark 插件 🚧 占位 · Definition ✅

本手册是 SDK 对外契约的产品级真源,改动对外使用面必须同步:SDKConfig(及嵌套)字段、LiveSDK 公开方法、SDK_EVENTS/SDKEventPayloads 事件、构造/mount/destroy 行为、主题/i18n/modal/插件契约、src/lib/index.ts 导出、UMD 全局与构建产物。占位能力落地后须移除对应 🚧 标记。

日期 版本 变更
2026-07-15 1.2.0 修复观看上报端点后置配置:认证会话就绪即建立 ordinary/Range channel;宿主在 mount 后调用 setEndpoints({ watchReportBaseUrl }) 会刷新任务配置并重新校准,上报无需重新挂载 SDK。
2026-07-15 1.2.0 观看时长与任务奖励链路完成并修复应用层装配:新增 WatchClock、getWatchProgress()watch.*、可信 watchSession、ordinary/Range 独立校准/outbox/retry/final ACK;TaskRewardEntry 从主包导出,真实映射 watchCondition/interactiveCondition/awardSet/awardReceiveType,支持动态端点、任务时间窗、普通手动领奖与 Range 累计;修复 entry 创建早于 WatchClock、在途 ACK 吞 final、destroy 中断终态、跨用户 scope 串时长。服务端 fence/finalAck 仍标 ⚠️;集成示例见 GUIDE-APP-LAYER-MARKETING.md
2026-07-14 1.2.0 商品兑换券按 scoreGoodsInfo.useCouponType 对齐 live-app(无 SDKConfig/方法/事件签名变化,纯数据模型与 section 语义补充):① useCouponType 枚举驱动分流——0/空=不使用(不显兑换券胶囊/弹窗)、1=商品券(分页「可用兑换券」+需要/已有)、2=普通券+万能券(内联「商品所需兑换券」+万能券提示);② GoodsCardItem 新增可选 supportUniversalCoupon?: boolean(商品项顶层,仅 type2 消费,缺失→false);③ scoreGoodsInfo.couponList[] 项形状补齐 {couponNum,couponName,couponId,code?,consumeNum?,count?,name?}(numIid 1954756 实测 type2 内联);④ ExchangeCouponSectionData 语义明确:新增 couponType:1|2 驱动渲染分支,count = 商品所需兑换券总数(type1=couponNum / type2=sum(couponList)非券种数),mine(仅 type1,mySelfCouponNum),isSupportUniversalCoupon(仅 type2),hasMore/pageNo/loadingMore/loadMoreError(仅 type1);⑤ 缓存/single-flight 键 + Entry 竞态守卫扩展到 numIid + scoreGoods + couponType;⑥ 向后兼容:商品不在列表(found=false)且 scoreGoods=true 时程序式打开回退 type1 分页分支。goods.list payload 项字段扩展、goods.marketing.showMarketingDetail.sectionsexchangeCoupon section 语义如上;满减/满赠 chip 维持纯展示不开弹框
2026-07-13 1.2.0 兑换券胶囊新增兼容型 SDK 自开:SDKOptions.goodsMarketing.autoOpenExchangeCoupon 默认 false,显式 true 时 SDK 打开 GoodsMarketingPanel 并继续发送 goods.promotion.click;修复真实请求失败被伪装为空态、重试丢失 scoreGoods、营销缓存未区分普通/积分分支及陈旧请求覆盖。marketing Store 新增 scoreGoodssetOpening 签名同步更新
2026-07-13 1.2.0 清晰度预加载评审与回归修复(无新增配置/API/事件):所有平台及声音状态统一使用 standby 预加载,回滚已开声触发的 active 直接换源;开声不销毁 standby,旧 active 停止后才向新 active 继承缓存音量/静音;同时完成 pause/detach、媒体/UI 层级、重复 Danmu 输入框与逐次成功提示修复。
2026-07-13 1.2.0 清晰度切换体验优化(内部播放机制,无新增配置/API/事件):运行时切档由“当前 video 立即换源”改为 active/standby 双槽位;目标源隐藏静音预加载,取得 loadstart → playing → progress 后原子交换画面并迁移音量/静音。失败、超时、取消或快速改选只释放 standby,旧源持续播放,避免目标源缓冲期间 1~5 秒空白。首次起播、VOD、自愈与公开切流事件契约不变。
2026-07-13 1.2.0 新增实例级服务端时间校准与公开方法 getServerTime():首屏 config/detail.serverTime、LAPS serverTime / ws.room_config.serverTime、营销 HTTP timestamp 汇入同一 ServerClock;以 performance.now() 单调增量推进,设备日期/时区修改不影响结果,重复/乱序锚点不回拨;live.setRoomConfig({serverTime}) 同步更新统一时钟,签到活动先到时显示 00:00 并在校时后立即重算
2026-07-13 1.2.0 互动工具聚合抽屉:FloatMoreDrawer 改读 interactiveItems 时间轴(60% contained 抽屉、打开即静默刷新、详情 z=1200 覆盖可返回);Store 新增 interactiveItems/refreshing/reconcilePrime;Entry 三路径共用 generation 门控。_refreshInteractiveTools 为 SDK 内部委托,非公开 API
2026-07-13 1.2.0 底部聊天输入框中文默认 placeholder(chat.input.placeholder)由“说点什么…”调整为“快来和大家聊聊吧~”;i18n key 与覆盖方式不变,无 SDKConfig/API/事件/数据模型变化
2026-07-13 1.2.0 补全遥测 v3 解析契约:14/14 事件逐 payload 字段定义,覆盖 batch/ctx/stats/sidecars,新增严格导出日志解析器与语义基线门禁;统一漏斗枚举为 goods=1、coupon=2,修复采集数据 type=1 被旧表误解为 coupon。
2026-07-13 1.2.0 遥测 v3 的 ctx.userKey 改为明文用户标识(去首尾空白),deviceKey 保持哈希;diagnostic.userKey 改为匹配明文,identityMode/plaintextIdentity 仅兼容保留。
2026-07-12 1.2.0 修复单播放器切流评审缺口:接通首次 101 原子起播与 108→101 VOD teardown/真实手动档恢复;完成门改为 source-applied + playing + 相对进度,隔离中间错误并收紧健康采样/同源恢复。
2026-07-12 1.2.0 收口遥测 v3 评审:真实事件接线、60 秒/5 窗口预算、生产诊断闸门、可靠退避熔断、sidecar 重试、APM/白屏与 contract 门禁。
2026-07-12 1.2.0 遥测升级 v3:新增 profile、Transport、SHA-256 身份、批次上下文、聚合/漏斗/APM 与有界队列;同步事件参考、zan-mini 同构规范及宿主环境验证清单。
2026-07-12 1.2.0 清晰度自适应升级为健康 episode + 单播放器 generation 切流事务:新增 switching/switched/switch-failed/switch-cancelled 事件,首次选流与预告/回放转直播原子提交,提示绑定真实出帧终态。
2026-07-11 1.2.0 修复终态 Modal 在 sdk.destroy() 后 Tailwind/embed 样式失效:Modal target 自带样式边界,留屏期间保持 py-7 等完整视觉;修复 TCPlayer 已 playing/canplay、画面正常时前台恢复复判误发 foreground recovery failed: still stalled
2026-07-11 1.2.0 新增统一 EndpointConfigsetEndpoints/getEndpoints,支持 HTTP、LAPS WS、观看上报端点按环境构建、宿主初始化覆盖与运行时换址;观看上报改为独立 base URL;live-app 开发启动与测试构建统一前置 LiveSDK build:test
2026-07-10 1.2.0 LiveSDK 接入契约补齐:新增运行时 api.baseUrl、严格 host-cache 房间详情 bootstrap、storeId 与红包 handlers;公开 we-livesdk/legacy / we-livesdk/embed.css,标准 build 产出嵌入资源;移除 API/WS 测试地址兜底并同步状态切换请求地址。
2026-07-13 1.3.2 「更多」面板补齐小程序 more-popup 五项业务入口(增量,不改既有清晰度/字体/清屏):新增 features.more 5 个 FeatureKey(more.redPacket/more.score/more.coupon/more.order/more.feedback,默认 true)+ 5 个 more.* 事件;MorePanel 追加「我的红包/积分/券码/订单/意见反馈」入口(52×52 白底圆 + 渐变背景,既有 3 项样式不变);红包点击 emit 后 openRedPacket(),反馈 emit 后转发 topbar.feedback,积分/券码/订单纯外抛由宿主导航。新增组件 MoreEntryButton + 5 个 i18n key。详见 docs/superpowers/plans/2026-07-13-livesdk-more-panel-business-items.md
2026-07-11 1.2.0 商品营销面板(GoodsMarketingPanel)视觉+功能对齐主应用 coupon-detail 弹窗(新增 1 个实例方法):①兑换券合并——相同 couponId/code 的兑换券累加计数、过滤 0 计数条目,标识键使用 id:/code: 独立命名空间(对齐 detail-popup mergedList);②计数回退链 couponNum→consumeNum→count→0(对齐 DetailItem getConsumeNum);③「已获得」标签(对齐 goods-coupon-popup showSubText=true);④万能券提示横幅 isSupportUniversalCoupon(对齐 detail-popup);⑤分页加载更多——新增实例方法 loadMoreMarketingCoupons()marketingApi.fetchExchangeCouponPage 分页拉取 + marketingStore.appendExchangeCoupons 合并追加,section 保存服务端 pageNo 并按分页元数据判定 hasMore,避免合并后重复请求;section 内「加载更多/加载中/加载失败」三态 UI(对齐 goods-coupon-popup loadMore);⑥pageSize 20→10 对齐 goods-coupon-popupExchangeCouponSectionData 新增 consumeNum/count/isSupportUniversalCoupon/hasMore/pageNo/loadingMore/loadMoreError 字段。SectionComponent props 新增 onLoadMore/loadingMore/loadMoreError(可选)
2026-07-10 1.2.0 营销浮标展示细节对齐(内部 UI/store 行为,无 SDKConfig/公开 API/事件/数据模型变化):横竖屏统一位于顶部横向左侧,超出容器可横向滚动;每项增加 × 关闭,关闭仅写入 store 本地隐藏标记、不删除原始活动,同 ID 数据刷新/upsert 不会令其复活,仍可从「更多」重新打开;页面刷新、store 重建或 reset() 会清空关闭集合并重新显示活动。文案规则:coupon 恒为「领券」、checkin 恒为「签到」;lucky active 且 openType=2 显示倒计时,active 手动开启显示「等待开启」,attended 显示「开启中」,其余显示「福袋」。定时福袋以 Math.floor(openTime / 1000) 得到 deadlineSec,再减 serverNowSec;服务端时钟未锚定时稳定显示 00:00。相关 store 方法仅供内部组件使用
2026-07-10 1.3.1 营销浮标样式对齐火山小程序 image-text-float(纯视觉 + 新增溢出交互,无 SDKConfig/API/事件变更):① FloatBar 图标由 lucide 线性图标改为本地 PNG(assets/image-text-float/float-coupon|checkin|luckymoney.png,Vite 内联 base64),容器 44×44px 圆角方块 + 底部文字条(券「领券」/签到「签到」/福袋「福袋」,对齐小程序 statusRules);lucky(积分/红包福袋)用 float-luckymoney.png。② 新增 floatIcons.ts(kind→图标/文案映射)+ FloatIconButton(单图标单元,portrait 深色 / landscape 浅色主题)+ FloatMoreDrawer(基于 Drawer 的聚合抽屉)。③ 溢出折叠:浮标最多 3 个,超出折叠为「更多」方块,点击打开聚合抽屉列出全部(对齐小程序 floatIconNum=3)。④ 横屏(liveStore.isLandscape)浮标横向靠右 + 浅色主题。数据源 roomMarketing.floatItems、点击 store.show(id)、清屏门控不变;CouponStack 仍保留导出(DEPRECATED)
2026-07-10 1.3.1 修复房间营销浮标被遮挡不显示的 bug(纯内部视觉,无 SDKConfig/API/事件/导出变更)+ 我的红包全功能(有 SDKConfig/API/事件/导出变更):FloatBar(签到/福袋/券入口)改为迁入 TopBar 第二行作为流式子元素;简化版:…① SDKConfig.handlers.redPacketwithdraw/confirmReceipt,微信 JSAPI 写操作整体抛宿主,返回归一化结果 {status:'success'|'cancelled'|'fail'|'pending', message?});② 实例方法 openRedPacket()(等价点击 topbar 按钮);③ AppEntryModuleId'redPacket',新增入口模块 RedPacketEntry + 新事件 redPacket.open;④ 新增 store sdk.stores.redPacket;⑤ SDK 自调账户域 HTTP;⑥ 三个组件 RedPacketPopup/RedPacketRecordPopup/RedPacketRecordList;⑦ 命令式挂载基建 mountOverlay + RedPacketHost 接线;⑧ 金额规则:<0.03 拦截、>200 裁剪;⑨ 24 个 i18n key
2026-07-10 1.3.2 商品橱窗卡新增预售/海淘/跨境标签:GoodsCardItem 新增 isPresell?:number(0=非预售 1=全款 2=定金 3=混合)+ goodsType?:number(1=普通 2=视频号 3=海淘 4=跨境),goodsMapper.mapGoodsData 防御性数值透传(缺省→undefined 不入对象、null→undefined、非数字→toNum 兜底 0);GoodsListPanel 商品名前内嵌语义色 chip(预售=emerald-500 / 海淘=amber-500 / 跨境=red-500;预售粗粒度 isPresell!==0 即显,海淘/跨境互斥仅 goodsType===3/4,可叠加),与一方 goods.svelte 对齐。新增 3 个 i18n key(goods.tag_presale/goods.tag_oversea/goods.tag_crossborder,zh-CN:预售/海淘/跨境)。无新 SDKConfig/API/事件/方法;3 个 i18n 键扩展 I18nMessages 公共面(宿主可经 SDKOptions.i18n 覆盖),非破坏性增量。字段下发 NEEDS-SERVER-VERIFY:@zan/laps cmd 7000 / goodsCard 路径是否携带 isPresell/goodsType 待抓包复核(防御式 mapper 不崩,未下发则标签不显示)
2026-07-09 1.2.0 房间营销统一为 roomMarketing 域(SPEC-ROOM-MARKETING Phase F 收尾):① AppEntryModuleIdcoupon/checkIn/imageTextFloat → 统一 'roomMarketing'(签到/福袋/券合流);② 新增实例方法 claimCoupon(packetId) / joinCheckIn(id?) / joinLuckyPacket(id);③ 新增事件族 ws.room_activity(判别联合 RoomActivityOp)+ ws.server_time / ws.reconnect废止 activity.change/result/participate / coupon.show/open/close / ws.coupon_dispatch;④ 新增 Store sdk.stores.roomMarketingcards/currentCard/currentModalId/floatItems/serverNowSec + dispatch/show/dismiss/primeDispatch/primeShow/setServerTime/reset),下线 liveStore.couponscheckIn store;⑤ CouponPopupLayer 改名搬入 room-marketing/CouponLayer.svelte,删 ActivityPanel。废弃旧文档 SPEC-MARKETING/PLAN-MARKETING/SPEC-MARKETING-REVIEW(加 deprecated 抬头)。详见 SPEC-ROOM-MARKETING.md
2026-07-09 1.3.1 修复大字体模式下 IM 消息部分元素不缩放的问题:更多面板「字体大小」改为全场景同档联动——评论(im.comment.content 正文 / im.comment.nickname 昵称 / im.comment.level 等级 / im.comment.avatar 头像)+ 温馨提示(im.welcome.content)+ 进场消息(im.enter.content)+ 快捷评论(im.shortcut.content)+ 新增下单消息(im.order.content)八场景统一 setUiTextSize 批量写入(非单场景 setUiTextSizeScene)。新增场景 im.comment.avatar(头像尺寸 18/20/22px)与 im.order.content(下单消息文案,default text-sm / large text-base / xlarge text-lg);im.comment.nicknameim.comment.level 补全 xlarge 档。ChatMessage 头像由硬编码 h-[18px] w-[18px] 改为响应式 avatarSizeClass;BuyingFeed 下单消息容器/按钮由固定 text-sm 改为消费 orderTextClass。对外契约:UiTextSizeScene 新增 im.comment.avatarim.order.content,更多面板行为变更(昵称/头像/温馨提示/进场/下单消息随正文同比放大);单场景 setUiTextSizeScene('im.comment.content') 路径不受影响、其余场景回退 default。手册「配置 SDKConfig」/「字号档位」/本表同步
2026-07-09 1.2.0 「更多」面板业务特性可见性:features.more 命名空间 + 3 个 FeatureKey(more.quality/more.fontSize/more.cleanScreen,默认 true;清晰度仍 AND hasMultiQuality && DefinitionPlugin)。入口点击先 emit 对应 more.* 再执行既有业务逻辑。复用 setFeature/updateFeatures/getFeatures不改 featureStore。零配置 = 今日行为。不含底栏 interact.more。详见 PLAN-MORE-PANEL-FEATURES.md
2026-07-09 1.3.0 商品营销满减/满赠摘要级渲染(v2):GoodsCardItem 新增 marketingActivities(goodsCard/get 商品项内联,仅摘要 actId/actType/actName,无档位/赠品明细,YApi 67205 实测;推翻旧 activityList+activityDetail 富结构假设——商城详情页端点形状不适用直播商品卡);marketingApi 新增 buildFullReduction 本地归一(零 HTTP)+ getMarketingActivities 窄回调注入(依赖倒置;goodsListStore 新增 getByNumIid 方法);新增 FullReductionSection.svelte + registry 注册 fullReduction kind(满赠合一不拆 kind);goodsMapperMarketingEntryHint 多源派生(兑换券 + actName,普通商品满减现也能出 chip 入口)。actType 码表未知期全量摘要 + 单点过滤钩子 FULL_REDUCTION_ACT_TYPES(抓包确认 2026-07-09:0=满减/1=满赠;保持 null 全量渲染),section 标题「促销活动」。无新事件/方法/SDKConfiggoods.list payload 项新增可选 marketingActivitiesgoods.marketing.showMarketingDetail.sections 可含 fullReduction kind
2026-07-08 1.3.0 DefinitionPlugin 公开导出(补清晰度重构遗漏):① ESM 主路径 + UMD 全局 LiveSDK.DefinitionPlugin 导出(src/lib/index.ts re-export,DefinitionPluginOptions 类型一并导出;Danmu/Watermark 仍 🚧 占位不固化);② html-demo 装配补 sdk.use(new LiveSDK.DefinitionPlugin())(构造后、mount 前注册)+ 代码集成展示框同步插件注册示例;③ 手册「插件」章节注明 opt-in 装配(ESM/UMD 两式)与「更多」面板清晰度入口门控依赖插件存在(hasMultiQuality && getPlugin('definition'))。契约LiveSDK.DefinitionPlugin / DefinitionPluginOptions 命名固化为对外公开 API 面。修复:预览站(UMD)「更多」面板缺失清晰度入口(根因 = 插件未导出 + demo 未注册,见 REVIEW-DEFINITION-PREVIEW-MISSING.md)。非破坏性(纯增量导出)
2026-07-09 1.3.1 商品营销满减/满赠摘要级渲染(v2):GoodsCardItem 新增 marketingActivities(goodsCard/get 商品项内联,仅摘要 actId/actType/actName,无档位/赠品明细,YApi 67205 实测;推翻旧 activityList+activityDetail 富结构假设——商城详情页端点形状不适用直播商品卡);marketingApi 新增 buildFullReduction 本地归一(零 HTTP)+ getMarketingActivities 窄回调注入(依赖倒置;goodsListStore 新增 getByNumIid 方法);新增 FullReductionSection.svelte + registry 注册 fullReduction kind(满赠合一不拆 kind);goodsMapperMarketingEntryHint 多源派生(兑换券 + actName,普通商品满减现也能出 chip 入口)。actType 码表未知期全量摘要 + 单点过滤钩子 FULL_REDUCTION_ACT_TYPES(抓包确认 2026-07-09:0=满减/1=满赠;保持 null 全量渲染),section 标题「促销活动」。无新事件/方法/SDKConfiggoods.list payload 项新增可选 marketingActivitiesgoods.marketing.showMarketingDetail.sections 可含 fullReduction kind
2026-07-08 1.3.0 更多面板字体大小设置:SDKConfig.uiTextSize(场景级 UI 字号默认值,static 层,类型 Partial<Record<'im.comment.content', 'default' | 'large' | 'xlarge'>>)+ 实例方法 setUiTextSizeScene(scene, mode) / getUiTextSize()(链式、mount 前可用、运行时同步持久化到 localStorage key livesdk:uiTextSize,刷新/重进自动恢复)。新增 xlarge 档(text-lg/7 = 18px),三档显示「默认/中/大」对应 mode default/large/xlarge(mode 值为公开契约不可改名,文案经 i18n 解耦)。作用范围:聊天评论内容文字(im.comment.content)。优先级 runtime(持久化) > SDKConfig.uiTextSize(static) > default。MorePanel 更多面板新增字体大小入口(ActionSheet 三档选择 + 高亮 + xlarge badge)。新增 5 个 i18n key(more.font_size/.default/.large/.xlarge + common.cancelActionSheet cancelTextcommon.cancel)。SDKConfig/方法/事件 契约同步见本表上方「配置 SDKConfig」「实例方法」「字号档位」「国际化」
2026-07-08 1.3.0 清晰度切换重构(FR-DEF-RW,PLAN-DEFINITION-REWORK):① defaultQuality 默认 auto→preset(破坏性:低端机起播失去设备分级降档保护,宿主需显式 defaultQuality:'auto' 保留);② manualOverrideMs 废弃(60s 静默→手动永久锁定,依赖自动恢复的宿主须自行 setTimeout+setManualMode(false) 重建);③ 解码错误硬路径(player.error 同档≥2→降档,豁免手动锁定,最低档 emit player.quality.failed);④ 手动 UI 迁移:移除 PlayerControls 清晰度入口+删 QualityMenu/QualityToast,新增「更多」Drawer(MorePanel)+ActionSheet(Drawer contained 薄封装);⑤ 新增 LiveSDK.getPlugin<T> 公共方法、playerStore.manualMode 响应式、player.quality.failed 事件、ActionSheet 三落点导出(we-livesdk/+components/+types)、6 个 i18n key;⑥ quality toast 收归 plugin 直接调 sdk.toast(手动 success/软降级 warning/解码 warning/不流畅 warning/终态 error)。DefinitionPlugin 🚧→✅。存量宿主迁移:低端机占比高→显式 defaultQuality:'auto';依赖 60s 自动恢复→自行重建。详见 PLAN-DEFINITION-REWORK.md/-TASKS.md
2026-07-08 1.2.0 新增左上角营销互动浮窗 imageTextFloat 与签到面板 checkIn:支持 CHECKIN/LUCKYMONEY/COUPON 三类 LAPS 映射、10 张本地图标、图标关闭/更多抽屉、签到详情/提交/6010 上报/踢出;新增 SDKOptions.floatingInteractionIconsimagetext.* / checkin.* 事件
2026-07-08 1.2.0 新增清屏态 API:实例方法 setCleanScreen(active) / getCleanScreen()(链式、mount 前可用,emit ui.cleanscreen.changed {active})+ 新事件 ui.cleanscreen.changed + 新 store sdk.stores.cleanScreenget() / set(v),构造期即建、进房默认 false、不持久)。active=true 进入清屏(隐全部业务 UI),false 退出。UI 入口:「更多」面板(MorePanel)新增恒显清屏入口(EyeOff 图标,点击 setCleanScreen(true) 并关闭面板);清屏态 ExitCleanScreen 根级浮动退出按钮(z-[80]、右侧垂直居中、Eye 图标,点击 setCleanScreen(false))。门控:竖屏 PortraitLayout 卸载 z-[60] 业务层 + Interact + ActivityPanel + 根级弹窗,保留 Player/MilestoneToast/MorePanel;横屏 LandscapeLayout 卸载评论区模块 + Interact/TopBar + 根级弹窗,观看区高度 h-[45%]h-full 切换 + 视频容器 absolute inset-0 使清屏态仅留视频铺满整屏,保留 Player/MilestoneToast/StatusOverlay/MorePanel{#if !clean} 卸载(非 CSS 隐藏)→ 隐藏元素无 DOM/监听/焦点,彻底不可触发。新增 2 个 i18n key(more.cleanScreen / player.cleanScreen.exit)。setCleanScreen/getCleanScreen/ui.cleanscreen.changed/stores.cleanScreen 契约同步见本表上方「实例方法」「事件」「Store」
2026-07-07 1.2.0 IM 场景字号扩展:UiTextSizeSceneim.comment.content 扩展为 6 个场景,新增昵称、等级徽标、温馨提示、进场消息浮条、快捷评论按钮文案;config.uiTextSize 与运行时 setUiTextSize / setUiTextSizeScene / getUiTextSize 文档化,playground 字号切换同步覆盖全部 IM 场景。无新增 SDK API,沿用既有场景字号契约
2026-07-06 1.2.0 商品橱窗底部安全区位置优化(纯内部视觉,无 SDKConfig/API/事件变更):GoodsListPanel<Drawer>safeAreaBottom={false} 关闭其固定底部安全区条,改在滚动列表(drawer-content)末尾自加 data-testid="goods-list-safe-area"height:env(safe-area-inset-bottom)bg-white)占位——安全区随列表一起滚动、列表滚到底时才出现,避免固定白条截断滚动列表底部(列表无法从最底部滚出)。Drawer 组件与 safeAreaBottom 契约不变;营销面板仍用默认固定安全区。需宿主 viewport-fit=cover
2026-07-06 1.2.0 横屏布局重构:LandscapeLayout 改上下 50/50 均分(观看区 / 评论模块各 flex-1);观看区内占位容器把 16:9 视频向下推(与顶部保持距离),16:9 改用 aspect-ratio 实现(移除原 padding-bottom:56.25% iOS12 兼容占位);横屏 playerFit 缺省由 covercontain(对齐 SPEC AC-L-01,等比留黑边不裁切);根 data-testid="landscape-layout"bg-black/70 backdrop-blur-xl,移除子元素背景色、视频容器自带 bg-black;TopBar / 跑马灯改为观看区直接子元素(锚定布局顶部、不随视频下沉,--livesdk-top-offset 偏移逻辑不变);底部新增专属安全区固定条 data-testid="landscape-safe-area-bar"height:env(safe-area-inset-bottom)shrink-0,参考 Drawer/商品橱窗),底部栏内边距改基础值避免重复安全区。需宿主 viewport-fit=cover 才生效
2026-07-06 1.2.0 对齐 LAPS CMD 梳理补齐营销判断:6000commandType 分流 check.in.start/endactivity.change(type=1),分流 lucky.packet.create/display/finishactivity.change(type=2)6020 lucky.packet.user.result 统一按当前 agentId 过滤,命中本人时派发 activity.result / ws.coupon_dispatch / coupon.result,他人结果不再透出;未知 commandType 仍保留 ws.coupon_dispatch 回落且不抛错
2026-07-05 1.2.0 新增顶部安全偏移:LayoutConfigtopOffset?: number | string(默认 0px,App 沉浸式嵌入避让系统状态栏;number 按 px,string 允许 CSS length/calc/env);实例方法 setTopOffset(value) / getTopOffset()(链式、mount 前可用,emit topOffset.update {value});LiveRoom 根写 --livesdk-top-offset CSS 变量,TopBar / 公告跑马灯 / 营销活动面板顶部由 top-0 改为 var(--livesdk-top-offset) 定位。新增 topOffset store(sdk.stores.topOffset,runtime > static > 0px,构造期即建)、新事件 topOffset.update。同步新增 activity.change / activity.result / activity.participate 事件(ActivityPanel 签到 / 福袋面板,原 as never 内联 emit 收敛为类型安全)
2026-07-03 1.2.0 播放器填充选项:LayoutConfig 加 `playerFit?:‘cover’
2026-07-03 1.1.0 新增进场消息浮条:liveWatch.enterMsgSwitch===1 门控,IM user.join 单源驱动,enterMessage store FIFO 单条展示,NotificationMessage 在 IM 消息列表上方 3s 滑入滑出;chat.enterNotice 旧聊天流内进场态移除
2026-07-01 1.2.0 新增商品橱窗入口数字 badge:FeatureItemOptionsbadge?: number(静态初值,构造期 config.features.<key>.badge 播种)+ 专用运行时 API setBadge(key,n)/getBadge(key)(链式、mount 前可用、emit badge.update {key,value}n<=0 清空)+ 新事件 badge.update;覆盖 2 个 BadgeKey(goods.cart.open/goods.order.open,购物车·订单入口图标右上角标,n>99 显示 99+)。新增类型 BadgeKey(顶层导出)+ badgeStoresdk.stores.badge,双层 runtime > static,镜像 featureStore)。badge 动态只走 setBadge,不走 setFeature({badge})(职责分离)。GoodsListPanel 购物车/订单入口渲染角标
2026-07-02 1.1.0 调整直播预告态交互:liveStatus=102/not_started 保留预告封面、文案与倒计时,同时 IM 聊天面板和输入栏继续展示并可聊天;结束/禁播/异常等阻断态行为不变
2026-06-30 1.1.0 新增业务功能配置系统:SDKConfig.features: FeatureConfig(业务 UI 可见性,与 appModules 正交)+ 运行时方法 updateFeatures(partial)/setFeature(key,opts)/getFeatures()(链式、mount 前可用)+ 事件 features.update {partial,key?};覆盖 5 个 FeatureKey(topbar.userCenter/topbar.businessInfo/goods.cart.open/goods.cart.add/goods.order.open,键 = 对应事件键);三源优先级 runtime > 构造 > 服务端兜底,零配置 = 今日行为。新增类型 FeatureConfig/FeatureItemOptions/FeatureKey(顶层导出)+ featureStoresdk.stores.features)。RightButtons/GoodsListPanel 可见性改由 featureStore.resolve 驱动
2026-06-26 1.0.0 初版:全量配置/方法/事件/模块/Store 覆盖;标注未实现(marketing/security core、3 插件 🚧)与待验证推送 payload(⚠️);以代码为真源,修正 README 旧示例
2026-06-27 1.0.1 ready 事件 payload 由 undefined 改为 {detail: RoomDetailBody}(直播详情对象:title/liveStatus/coverImg/planBeginDate 等),host 可于 ready 读直播间名称等;弹框(modal/AuthError)改容器内呈现 + 黑色 blur overlay + 失败时容器封面底图(roomDetail 复用不二次请求详情接口)
2026-06-28 1.0.1 新增全局 loading:showLoading(text?)/hideLoading() 方法 + sdk.stores.loading;进房默认展示、首帧可见自动收起、颜色跟随主题色;全局唯一 overlay,移除播放器内旧初始 spinner(统一由全局 loading 接管)
2026-06-29 1.0.1 新增浮层三件套:声明式组件 Dialog(bits-ui)/Drawer(原生)/Toaster(svelte-sonner) 顶层导出 + 类型 DialogProps/DrawerProps;命令式 sdk.dialog(=modal 别名) 与 sdk.toast/.success/.error/.warning;商品橱窗+营销面板收敛为 <Drawer contained>(z 1090/1100 不变)。依赖对齐 live-app(bits-ui/svelte-sonner/clsx/tailwind-merge/tailwind-variants)。UMD 首部 iOS12 polyfill banner(globalThis/Array.at/Object.fromEntries)。SDKConfig 无变化
2026-06-29 1.0.1 浮层公共组件 bug 修复:① Drawer overlay 与 panel 同 z(嵌套时后开 overlay 不再被先开 panel 盖住);Dialog overlay/content 钉 z-[1200](高于 drawer 带、低于命令式 modal)。② Drawer 下拖关闭改由顶部 grip(把手+标题区,touch-action:none)承载,与可滚动 body 隔离,修复「下滑无法关闭」。③ 新增 goodsList.loaded getter,商品橱窗加载态渲染骨架;Drawer 内容高度 min 30% / max 80%(--vh,content-driven),消除「空内容闪现→撑到最大高度」卡顿
2026-06-29 1.0.1 新增公共组件 Empty(通用空态:居中 + 通用 lucide Inbox 图标,text/description/icon/iconSize/class/testid/children 可配)+ 类型 EmptyProps,顶层//components//types 导出;商品橱窗(暂无商品)、营销面板(暂无优惠券)空态统一复用(全量空态场景排查后仅此两处面向用户)
2026-06-29 1.0.1 商品橱窗/商品卡片交互事件补齐:新增 goods.card.click(卡片整体点击,列表卡+浮窗卡)、goods.promotion.click(促销标签,纯外抛、移除 SDK 自开营销面板、host 可回调 openGoodsMarketing)、goods.cart.add(加入购物车按钮,非积分商品)、goods.cart.open/goods.order.open(橱窗标题栏购物车/订单入口,纯外抛);Drawer 新增 headerRight snippet 槽承载标题栏入口。i18n:新增 15 个 goods.* key(title/loading/empty/cart_entry/order_entry/add_to_cart/explaining/sold_out/promotion/buy_now_full/exchange/price_pending/price_hidden/go_check/close),GoodsListPanel/HotSellCard 全量用户可见文案走 sdk.t()(共 50 key)。⚠️ 破坏性:浮窗卡(HotSellCard)购买按钮由 interact.cart 统一为 goods.buy,旧宿主需迁移
2026-06-30 1.0.1 主题变量统一 shadcn token:移除 --live-*/--livesdk-* 前缀,全量改用 bg-primary/text-primary/bg-secondary 等工具类(/10 透明生效);--primary 改珊瑚 10 100% 63%、新增 --secondary330 81% 60%(:root+.dark);SDKTheme 颜色字段映射到 shadcn HSL 通道(primaryColor→--primary 等,hex 自动转通道,applySDKThemetoHslChannels);移除 dead legacy token + tailwind colors.live.* + 已退役导出 applyTheme/DEFAULT_THEME/ThemeConfig/CSS_VAR_MAP。⚠️ 破坏性:旧 --live-primary-color/--livesdk-* 变量与 applyTheme API 删除,自定义主题样式需迁 shadcn token
2026-06-29 1.0.1 Drawer 公共组件优化:① 移除手势下拖关闭——删 draggable/showHandle 字段、grip 把手及全部触摸拖拽逻辑(仅保留遮罩点击 / × 按钮关闭);② 新增 safeAreaBottom(默认 true),panel 容器加 env(safe-area-inset-bottom),footer(确认按钮)/body 均避开 home indicator,原 body 内 env 内边距移除避免重复间距。破坏性DrawerPropsdraggable/showHandle(无内部消费方,仅类型层)
2026-06-30 1.0.1 新增轻量 toast(小程序 wx.showToast 风格,独立于 svelte-sonner 的 sdk.toast):实例方法 sdk.showToast({ content, duration?, mask? }) / sdk.hideToast()(链式 this)。全局单例——再次 showToast 仅替换内容并重置计时(不堆叠);默认 5s 自动关(duration<=0 不自动关);mask=true 透明蒙层拦截底层点击(默认 false 穿透);≤2 行 / ≤90% 宽 / 顶层 z=100000。SDK 内部核心层可经 this.showToast() 调用,destroy()/直播结束自动清场。SDKConfig 无变化
2026-06-30 1.0.1 播放错误提示「直播信号加载失败,请稍后重试」由 Player 内自建遮罩层(player-error-overlay/player-error-prompt,z-100 黑底胶囊)改为走 SDK 统一 sdk.showToast(顶层轻量 toast):Player.svelteshowErrorPrompt effect 在 hasError && (isPlayable|isReplay) 跳变 true 时弹一次(保留封面/已结束态不提示的守卫)。原 player-error-overlay/player-error-prompt testid 移除。视觉上提示由播放区内胶囊变为顶层 toast
2026-06-30 1.0.1 轻量 toast 改为容器内渲染<LightToast> 由挂 document.body(fixed 整屏)改为挂 SDK 容器内(absolute inset-0仅覆盖 SDK 容器,非整屏),随 mount()/destroy() 挂卸(替换原 acquire/release 引用计数 + body root 方案)。容器内顶层 z=100000 不变。SDK 挂载容器新增 livesdk-container class 标识(与 LiveRoom 内 .livesdk-root 房间盒子区分,供宿主/CSS 定位 SDK 挂载根),destroy() 移除
2026-07-05 1.2.0 起播视觉与「取消静音播放」CTA 优化(纯内部行为,无 SDKConfig/API/事件变更):① 全局 loading 收起时机由 player.playing(‘play’ 意图)改为 player.firstframe(真首帧),并令 <video> 起播前透明、首帧后 0.3s 淡入(Player 容器 video-pending 类),消除「loading 提前收起→黑底闪一下→出帧」的画面闪烁;② CTA 显示时机收敛为「真首帧后且仍静音」(playerStore.hasFirstFrame 门控),不再在缓冲/loading 期提前显示——浏览器与微信同逻辑;③ 微信桥接:bridgeUnlockPending 默认 true 杜绝「先显后隐」闪烁,回调兜底窗口 5s→10s,新增 bridgeUnlockTimedOut 让桥接失败(无首帧)时仍兜底显 CTA
2026-07-08 1.2.0 HotSellCard 价格三态对齐 GoodsListPanel(隐价 待开价 gray-400、积分商品 {price}元 + CTA 立即兑换、正常 ¥{price} + CTA 抢购;卖光由 goods-sellout-mask 遮罩表达,删除价格区 去看看 死代码分支;判定顺序 priceHidden > scoreGoods > 正常)。i18n:删除 goods.price_hidden / goods.go_check 两个 key(改用既有 goods.price_pending)。⚠️ 破坏性:类型化 i18n 覆盖方(config.options.i18n: Partial<I18nMessages>)传入已删 key 编译期报错。无 SDKConfig/API/事件/主题/导出/UMD 全局变更
2026-07-08 1.2.0 商品列表排序与讲解置顶:goodsListStore.list getter 由「Map 插入序」改为集中排序——讲解品(explainStatus===1)置顶、其余按 seq 升序、numIid 字典序确定性 tiebreak(规避旧 WebView Array.sort 不稳定)。goods.list 事件 payload 顺序随之变更(影响面 = 首屏 HTTP 拉取那次 emit,GoodsListFetcher.doFetch 全局唯一 emit 点;WS 增量更新不重发该事件)。GoodsListPanel 讲解中卡片整体高亮(bg-primary/5 浅底 + rounded-xl + 去分隔线 + transition-all,与置顶同源;保留底部「讲解中」角标双重强调)。讲解结束自动回 seq 原位、抢光仍置顶。无 SDKConfig/API/事件名变更
2026-07-08 1.2.0 商品橱窗空态/加载态/错误兜底三态分离:① 首开骨架 loading(既有,loaded=false 渲染 6 条 animate-pulse 占位,避免空内容闪现 + 高度跳变);② 拉取失败重试入口(新增)——GoodsListFetcher HTTP 失败不再静默返空导致骨架永久转圈,改为 store.markError() 标记错误 + emit goods.list.error {message?};橱窗在「无任何成功数据」(error && !loaded) 时渲染错误态(CloudAlert 图标 + goods.load_failed/goods.load_failed_desc 文案 + 「重新加载」按钮),点按钮 emit goods.list.retryProductListEntry 触发 fetcher 重新拉取(发起即 clearError 回骨架态 → 出结果);③ 空态区分——loaded=true && list=[] 显「暂无商品」(真的空),与「拉取失败」错误态严格区分;已有数据后 refetch 失败(loaded=true && error) 不夺走列表(错误为瞬时)。新增事件 goods.list.error / goods.list.retry;新增 i18n key goods.load_failed / goods.load_failed_desc / goods.retrygoodsListStore 新增 error getter + markError() / clearError()。无 SDKConfig/API/主题/导出/UMD 全局变更