Skip to content

上架与分发

皮肤有两条分发路径:内置(打包进客户端,随版本发布)和商城远端(上传到皮肤市场,用户购买/领取后应用)。本篇讲两者的差异与远端皮肤的字段约定。

内置皮肤

适合官方维护、随客户端分发的皮肤。做法见快速开始:把 Skin 对象(用 css 字符串)加进对应组件的内置数组——

  • 加班机:src/assets/data/skins/overtime-machine.ts
  • 礼物菜单:src/assets/data/skins/gift-menu.ts

src/assets/data/skins/index.tsskinsList 自动汇总,启动时 injectAllBuiltinSkins() 一次性注入。内置皮肤对所有用户恒为已拥有price 仅展示,不接支付)。

新增一类组件的内置皮肤时,记得在 skin-css.tsWRAPPER_CLASS_MAP 里登记它的包裹层类名,否则作用域注入拿不到前缀。

商城远端皮肤

适合第三方作者上传、可售卖的皮肤。客户端不打包它的 CSS,而是按需从服务端拉取。

数据流

商城列表 getSkins({ elementType })      → 只返回展示字段(无 CSS)
点皮肤卡 → 详情 getSkin(serverId)        → 返回 cssUrl / cssContent / skinData
应用前 ensureMarketplaceSkinReady()      → 每次都拉最新详情 + injectSkinCss()
应用 applyElementSkin()                  → 合并 skinData + 写 element.skinId

客户端皮肤 id 是字符串,远端 id 是数字,落到 element.skinId 时统一加 remote: 前缀(buildRemoteSkinId),不与内置 id 冲突。

后端响应到 Skin 的字段映射

toSkin()src/utils/marketplace-skin.ts)把后端响应映射成客户端 Skin

后端字段客户端 Skin 字段说明
id(number)id = "remote:<id>" / marketplaceId应用/购买/查已购都用它
titlename显示名
elementTypeelementType适用组件,必须是合法 ElementType
previewImage[0]thumbnail选择器/卡片缩略图
previewImage[]详情主图 gallery详情弹窗轮播
detailImages[]详情长图详情弹窗正文图
detailText / descriptiondescription商品详情正文
tagstags标签 chip
price / originalPriceprice / originalPrice价格(元),0 = 免费
memberDiscounts / appliedMemberDiscount同名会员折扣展示
authorauthor作者信息
hasPurchasedhasPurchased是否已购
cssContentcss内联 CSS(与 cssUrl 二选一)
cssUrlcssUrlCSS 链接(推荐)
skinDatadata应用时合并进元素的字段

列表接口没有 cssUrl/cssContent/skinData,只有详情接口才有。ensureMarketplaceSkinReady 每次都拉最新详情、不复用缓存——后台改了字体/CSS,客户端能立刻拿到新值。

cssUrl 的写法约定

  • 加班机 / 礼物菜单:上传的 CSS 可以省略作用域前缀——客户端 ensureScoped 会自动把裸 .desc { ... } 包成 .wrapper[data-skin-id="remote:123"] .desc { ... }。当然写全前缀也兼容。
  • 弹幕姬:CSS 是整张 blivechat 主题,用顶层 yt-live-chat-* 选择器,不要加作用域前缀(弹幕姬走 <link> 整表加载,不经 ensureScoped)。

skinData 要放什么

组件skinData 必填说明
礼物菜单一般不需要纯视觉
加班机{ displayMode, width: 280 }绑定版式;不要写 height(autoSize)
弹幕姬{ versionType, fonts? }版本决定 DOM;fonts: [{family,url}] 注册自带字体

资源可达性(重要)

cssUrl、缩略图、字体文件都要用公网可达的地址,且在编辑 / 预览 / 虚拟摄像头三种窗口都能加载——预览窗与推流窗无鉴权、不会走详情接口(弹幕姬把 skinCssUrl 持久化到元素上正是为此)。字体 / CSS 所在 OSS 需配好 CORS。

自测清单

上架前在客户端里逐项确认:

  • [ ] 皮肤出现在对应组件的「样式 → 皮肤 → 我的皮肤」列表里,且类型匹配。
  • [ ] 套用后外观正确:背景 / 颜色 / 描边 / 阴影 / 动效都生效,无需 !important 也能盖过默认。
  • [ ] 没有把别的皮肤或编辑器 UI 染色(作用域前缀写对、@keyframes 名带前缀没撞名)。
  • [ ] 加班机:版式与 displayMode 一致,高度自适应正常,不闪。
  • [ ] 弹幕姬:versionType 与主题匹配,自带字体能下载(CORS 正常),切回「默认」能干净恢复。
  • [ ] 切到「预览」窗口,皮肤照常显示(资源可达,无鉴权依赖)。