# hxh-dev-docs
**Repository Path**: yawntee/hxh-dev-docs
## Basic Information
- **Project Name**: hxh-dev-docs
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 1
- **Created**: 2024-01-24
- **Last Updated**: 2025-09-18
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 彗星号创意工坊开发文档
创意工坊的每个插件均为一个静态网页,既可以使用原生静态网页技术进行开发,也可以使用任意可编译为静态网页的语言开发,网页之间通过`window.postMessage`进行跨域交互
[全屏特效示例](全屏特效.html)
**若需使用彗星号内置字体,可在`
`中添加以下代码,然后根据option更新事件提供的`fontFamily`修改字体**
```html
```
## 环境判断
```javascript
const query = new URLSearchParams(location.search)
// 是否处于配置状态
const isSetup = query.get('env') === '1'
if(isSetup) {
//配置时使用模拟数据展示效果
}
```
## 共用类型
* 彗星号事件
```typescript
export interface ApiMessage {
category: string
type: string
args: any[]
}
```
* 创意工坊插件事件
```typescript
export interface PlugMessage{
fun: string
args: any[]
}
```
## API
* ##### 控制插件
```typescript
export interface Attr{
x: number; //与左侧横向距离
y: number; //与顶部纵向距离
w: number; //宽度
h: number; //高度
}
```
```javascript
//全屏
const args = {
x: 0,
y: 0,
w: 1920,
h: 1080,
}
parent.postMessage({
fun: 'attr',
args,
}, '*')
```
* 更新配置
```javascript
/*
假设插件配置结构为
{
a: {
b: 1,
c: 2,
}
}
*/
//只修改b的值
const newOptio = {
a: {
b: 111
}
}
parent.postMessage({
fun: 'option',
args: newOption,
}, '*')
```
> 每个插件的当前配置结构可通过上传index.html并使用console.log输出到控制台获取
## 更新事件(update)
**所有更新事件将于页面加载完成之后触发一次,以便初始化数据**
> 用户信息(user)
* 示例
```typescript
window.addEventListener('message', e => {
const { category, type, args:[userInfoList] } = e.data
if(category === 'update' && type === 'user'){
console.log('用户信息更新了', userInfoList)
}
})
```
* 参数
```typescript
interface PlatformUserInfo {
room_id: number; //房间号
name: string; //昵称
}
type UserInfoList = PlatformUserInfo[]
```
> 插件配置(option)
* 示例
```typescript
window.addEventListener('message', e => {
const { category, type, args:[option] } = e.data
if(category === 'update' && type === 'option'){
console.log('插件配置更新了', option)
}
})
```
* 全屏特效
```typescript
export enum Guard {
NOTHING = 0, //普通观众
GOVERNOR = 1, //总督
SUPERVISOR = 2, //提督
CAPTAIN = 3, //舰长
}
export interface Option {
// 蒙层颜色
maskColor: string,
// 上舰特效
guard: {
/* 感谢文案
{
1:"感谢老板开通总督",
2:"感谢老板开通提督",
3:"感谢老板开通舰长"
}
*/
banner: { [T in Exclude]: string }
// 是否启用
enable: boolean
}
// 送礼特效
gift: {
// 最低显示价格(RMB)
min: number
// 感谢文案
banner: string
// 是否启用
enable: boolean
}
// 醒目留言特效
superChat: {
// 感谢文案
banner: string
// 是否启用
enable: boolean
}
}
```
# 直播间事件('event')
插件可以通过此API获取直播间的各种事件,执行对应的变化:
```javascript
//监听事件
window.addEventListener('message', e => {
const { category, type, args:[dm] } = e.data
if(category === 'event' && type === 'LIVE_OPEN_PLATFORM_DM') console.log(dm.message)
})
// 订阅直播间事件
parent.postMessage({
fun: 'subscribe',
args: 'LIVE_OPEN_PLATFORM_DM' //使用数组可同时订阅多个事件
}, '*')
```
**`type`请参考[哔哩哔哩直播开放文档 (bilibili.com)](https://open-live.bilibili.com/document/f9ce25be-312e-1f4a-85fd-fef21f1637f8)中的`CMD`字段**
> 通用
| 字段名 | 类型 | 描述 |
| -------- | ---- | ---------- |
| isAnchor | bool | 是否为主播 |
> 弹幕
| 字段名 | 类型 | 描述 |
| ---------------------- | ------ | ---------------------------------- |
| id | string | 消息唯一id |
| type | string | 事件类型 |
| uname | string | 用户昵称 |
| uid | int64 | 用户UID |
| face | string | 用户头像 |
| timestamp | int64 | 弹幕发送时间秒级时间戳 |
| message | string | 弹幕内容 |
| fansMedalWearingStatus | bool | 该房间粉丝勋章佩戴情况 |
| fansMedalName | string | 粉丝勋章名 |
| fansMedalLevel | int64 | 对应房间勋章信息 |
| gloryLevel | int | 直播荣耀等级 |
| emojiImgUrl | string | 表情包图片地址 |
| dmType | int64 | 弹幕类型 0:普通弹幕 1:表情包弹幕 |
| isModerator | bool | 是否为房管 |
> 礼物
| 字段名 | 类型 | 描述 |
| ---------------------- | ---------------- | --------------------------------------- |
| id | int64 | 消息唯一id |
| type | string | 事件类型 |
| uid | int64 | 送礼用户UID |
| uname | string | 送礼用户昵称 |
| face | string | 送礼用户头像 |
| giftId | int64 | 道具id(盲盒:爆出道具id) |
| giftName | string | 道具名(盲盒:爆出道具名) |
| giftNum | int64 | 赠送道具数量 |
| price | int64 | 礼物单价(单位:RMB),盲盒:爆出道具的价值 |
| paid | bool | 是否是付费道具 |
| fansMedalLevel | int64 | 实际送礼人的勋章信息 |
| fansMedalName | string | 粉丝勋章名 |
| fansMedalWearingStatus | bool | 该房间粉丝勋章佩戴情况 |
| guardLevel | int64 | 大航海等级 |
| timestamp | int64 | 收礼时间秒级时间戳 |
| giftIcon | string | 道具图标 |
| comboGift | bool | 是否是combo道具 |
| comboInfo | combo_info结构体 | 连击信息 |
| combo_info | 类型 | 描述 |
| :------------- | :----- | :--------------------- |
| combo_base_num | int64 | 每次连击赠送的道具数量 |
| combo_count | int64 | 连击次数 |
| combo_id | string | 连击id |
| combo_timeout | int64 | 连击有效期秒 |
> 付费留言
| 字段名 | 类型 | 描述 |
| ---------------------- | ------ | ---------------------- |
| id | string | 消息唯一id |
| type | string | 事件类型 |
| uid | int64 | 购买用户UID |
| uname | string | 购买的用户昵称 |
| face | string | 购买用户头像 |
| message | string | 留言内容 |
| rmb | int64 | 支付金额(元) |
| timestamp | int64 | 赠送时间秒级 |
| startTime | int64 | 生效开始时间 |
| endTime | int64 | 生效结束时间 |
| guardLevel | int64 | 对应房间大航海等级 |
| fansMedalLevel | int64 | 对应房间勋章信息 |
| fansMedalName | string | 对应房间勋章名字 |
| fansMedalWearingStatus | bool | 该房间粉丝勋章佩戴情况 |
> 大航海
| 字段名 | 类型 | 描述 |
| ---------------------- | ------ | ---------------------- |
| id | string | 消息唯一id |
| type | string | 事件类型 |
| uid | int64 | 购买用户UID |
| uname | string | 购买的用户昵称 |
| face | string | 购买用户头像 |
| guardLevel | int64 | 大航海等级 |
| guardNum | int64 | 大航海数量 |
| guardUnit | string | 大航海单位 |
| fansMedalLevel | int64 | 粉丝勋章等级 |
| fansMedalName | string | 粉丝勋章名 |
| fansMedalWearingStatus | bool | 该房间粉丝勋章佩戴情况 |
| timestamp | int64 | 上舰时间秒级时间戳 |
> 进房
| 字段名 | 类型 | 描述 |
| --------- | ------ | ----------- |
| uid | int64 | 送礼用户UID |
| face | string | 用户头像 |
| uname | string | 用户昵称 |
| timestamp | int64 | 秒级时间戳 |
> 点赞
| 字段名 | 类型 | 描述 |
| ---------------------- | ------ | ---------------------- |
| uid | int64 | 点赞用户UID |
| face | string | 用户头像 |
| uname | string | 用户昵称 |
| likeText | string | 点赞文案 |
| likeCount | int64 | 点赞次数 |
| fansMedalLevel | int64 | 粉丝勋章等级 |
| fansMedalName | string | 粉丝勋章名 |
| fansMedalWearingStatus | bool | 该房间粉丝勋章佩戴情况 |
| timestamp | int64 | 秒级时间戳 |
> 重置插件
* 事件名:`CLEAR_DATA`
* 作用:点击配置中的清空数据按钮后,通知直播间中的插件清空数据
* **收到此事件后,若此插件有数据,则应重置插件状态**
# 自定义作品配置
如果作品有额外配置参数需求,可以通过指定的json格式,在画布右侧配置栏创建额外的选项
## 基本格式
| 字段名 | 类型 | 必须 | 描述 |
| ------ | ------------------------------------ | ---- | ------------------------ |
| key | string | 是 | ID (不能重复) |
| name | string | 是 | 标题 |
| type | string | 是 | 类型 (输入框、下拉框...) |
| value | string \| number \| boolean \| array | 是 | 默认值 |
```json
{
"settings": [
{
"key": "foo",
"name": "自定义颜色",
"type": "color",
"value": "#ffffff"
}
]
}
```
## CSS中使用
变量格式:`--worshop-`
```css
.foo{
color: var(--workshop-color)
}
```
## 模板中使用
```javascript
const handlers = {
update: {
option(newValue) {
//控制台输出自定义配置color的值
console.log(newValue._.color)
},
}
}
//监听事件
window.addEventListener('message', e => {
const { category, type, args } = e.data
handlers[category]?.[type]?.apply(e, args)
})
// 订阅事件
parent.postMessage({
fun: 'subscribe',
args: Object.keys(handlers.event)
}, '*')
```
## 组件库
* 输入框(text, textarea)
| 字段 | 类型 | 必须 | 描述 |
| ----------- | ------ | ---- | -------------------- |
| placeholder | string | 否 | 无内容时的提示 |
| prefix | string | 否 | 前缀文本 |
| suffix | string | 否 | 后缀文本 |
| maxlength | number | 否 | 限制内容最大字符长度 |
| rows | number | 否 | 输入框展示行数 |
```json
{
"settings": [
{
"key": "text",
"name": "输入框",
"type": "text",
"value": "默认内容",
"prefix": "前缀内容",
"suffix": "后缀内容"
},
{
"key": "textarea",
"name": "多行输入框",
"type": "textarea",
"value": "默认内容",
"placeholder": "请输入xxx",
"maxlength": 30,
"rows": 5
}
]
}
```
* 数字输入框(decimal)
| 字段 | 类型 | 必须 | 描述 |
| ---- | ------ | ---- | ------------ |
| step | number | 否 | 每次加减的值 |
| min | number | 否 | 最小值 |
| max | number | 否 | 最大值 |
```json
{
"settings": [
{
"key": "interger",
"name": "整数输入框",
"type": "decimal",
"value": 0
},
{
"key": "decimal",
"name": "小数输入框",
"type": "decimal",
"value": 0,
"placeholder": "请输入xxx",
"prefix": "前缀内容",
"suffix": "后缀内容",
"precision": 2,
"step": 0.01,
"min": -999.99,
"max": 999.99
}
]
}
```
* 滑动选择(slider)
| 字段 | 类型 | 必须 | 描述 |
| ----------- | ------ | ---- | -------------- |
| placeholder | string | 否 | 无内容时的提示 |
| prefix | string | 否 | 前缀文本 |
| suffix | string | 否 | 后缀文本 |
| precision | number | 否 | 小数位数 |
| step | number | 否 | 每次加减的值 |
| min | number | 否 | 最小值 |
| max | number | 否 | 最大值 |
```json
{
"settings": [
{
"key": "interger",
"name": "整数滑块",
"type": "slider",
"value": 0
},
{
"key": "decimal",
"name": "小数滑块",
"type": "slider",
"value": 0,
"step": 0.01,
"min": -1,
"max": 1
}
]
}
```
* 复选框(checkbox)
| 字段 | 类型 | 必须 | 描述 |
| ---- | ---- | ---- | ---- |
| | | | |
```json
{
"settings": [
{
"key": "checkbox",
"name": "复选框",
"type": "checkbox",
"value": true
}
]
}
```
* 开关(switch)
| 字段 | 类型 | 必须 | 描述 |
| ---- | ---- | ---- | ---- |
| | | | |
```json
{
"settings": [
{
"key": "switch",
"name": "开关",
"type": "switch",
"value": true
}
]
}
```
* 选择器(select)
| 字段 | 类型 | 必须 | 描述 |
| -------- | -------------------------------- | ---- | ---------- |
| options | {label: string, value: string}[] | 是 | 选项组 |
| multiple | boolean | 否 | 是否可多选 |
```json
{
"settings": [
{
"key": "select",
"name": "选择器",
"type": "select",
"options": [
{
"label": "我选A",
"value": "A"
},
{
"label": "我选B",
"value": "B"
}
],
"value": "B"
},
{
"key": "multipleSelect",
"name": "多项选择器",
"type": "select",
"multiple": true,
"options": [
{
"label": "我选A",
"value": "A"
},
{
"label": "我选B",
"value": "B"
}
],
"value": [
"A",
"B"
]
}
]
}
```
* 颜色选择器(color)
| 字段 | 类型 | 必须 | 描述 |
| ---- | ---- | ---- | ---- |
| | | | |
```json
{
"settings": [
{
"key": "color",
"name": "颜色选择",
"type": "color",
"value": "#ffffffff"
}
]
}
```
* 图片上传(image)
| 字段 | 类型 | 必须 | 描述 |
| ---- | ---- | ---- | ---- |
| | | | |
```json
{
"settings": [
{
"key": "background",
"name": "背景图片",
"type": "image",
"value": ""
}
]
}
```