feat: 更新项目配置和组件,增强功能和用户体验

- 在 .gitignore 中添加了 .specstory 文件的忽略规则。
- 更新 tsconfig.json,修正了 vue-vine/types/macros 的引用路径。
- 在组件声明中新增了 NInput 组件的类型支持。
- 优化了 EventModel 接口,调整了 guard_level 的类型为 GuardLevel。
- 增加了 Follow 事件类型到 EventDataTypes 枚举中。
- 在 ClientAutoAction.vue 中引入了新的 store 和组件,增强了功能。
- 更新了多个设置组件,添加了关键词匹配类型和过滤模式的支持。
- 改进了模板编辑器和测试器的功能,支持更灵活的模板管理。
- 在弹幕客户端中新增了关注事件的处理逻辑,提升了事件响应能力。
This commit is contained in:
2025-04-22 02:30:09 +08:00
parent 2fc8f7fcf8
commit 77cf0c5edc
39 changed files with 3955 additions and 1959 deletions

View File

@@ -33,6 +33,7 @@ export default abstract class BaseDanmakuClient {
enter: ((arg1: EventModel, arg2?: any) => void)[]; // 新增: 用户进入事件
scDel: ((arg1: EventModel, arg2?: any) => void)[]; // 新增: SC 删除事件
all: ((arg1: any) => void)[]; // 'all' 事件监听器接收原始消息或特定事件包
follow: ((arg1: EventModel, arg2?: any) => void)[]; // 新增: 关注事件
};
// --- 事件系统 2: 使用原始数据类型 ---
@@ -45,6 +46,7 @@ export default abstract class BaseDanmakuClient {
enter: ((arg1: any, arg2?: any) => void)[]; // 新增: 用户进入事件
scDel: ((arg1: any, arg2?: any) => void)[]; // 新增: SC 删除事件
all: ((arg1: any) => void)[]; // 'all' 事件监听器接收原始消息或特定事件包
follow: ((arg1: any, arg2?: any) => void)[]; // 新增: 关注事件
};
// 创建空的 EventModel 监听器对象
@@ -57,6 +59,7 @@ export default abstract class BaseDanmakuClient {
enter: [],
scDel: [],
all: [],
follow: [], // 初始化 follow 事件
};
}
@@ -70,6 +73,7 @@ export default abstract class BaseDanmakuClient {
enter: [],
scDel: [],
all: [],
follow: [], // 初始化 follow 事件
};
}
@@ -296,6 +300,7 @@ export default abstract class BaseDanmakuClient {
public onEvent(eventName: 'enter', listener: (arg1: EventModel, arg2?: any) => void): this; // 新增
public onEvent(eventName: 'scDel', listener: (arg1: EventModel, arg2?: any) => void): this; // 新增
public onEvent(eventName: 'all', listener: (arg1: any) => void): this;
public onEvent(eventName: 'follow', listener: (arg1: EventModel, arg2?: any) => void): this; // 新增
public onEvent(eventName: keyof BaseDanmakuClient['eventsAsModel'], listener: (...args: any[]) => void): this {
if (!this.eventsAsModel[eventName]) {
// @ts-ignore
@@ -327,6 +332,7 @@ export default abstract class BaseDanmakuClient {
public on(eventName: 'enter', listener: (arg1: any, arg2?: any) => void): this; // 新增
public on(eventName: 'scDel', listener: (arg1: any, arg2?: any) => void): this; // 新增
public on(eventName: 'all', listener: (arg1: any) => void): this;
public on(eventName: 'follow', listener: (arg1: any, arg2?: any) => void): this; // 新增
public on(eventName: keyof BaseDanmakuClient['eventsRaw'], listener: (...args: any[]) => void): this {
if (!this.eventsRaw[eventName]) {
// @ts-ignore

View File

@@ -1,6 +1,6 @@
import { KeepLiveWS } from 'bilibili-live-ws/browser';
import BaseDanmakuClient from './BaseDanmakuClient';
import { EventDataTypes } from '@/api/api-models';
import { EventDataTypes, GuardLevel } from '@/api/api-models';
import { getUserAvatarUrl, GuidUtils } from '@/Utils';
import { AVATAR_URL } from '../constants';
export type DirectClientAuthInfo = {
@@ -155,28 +155,56 @@ export default class DirectClient extends BaseDanmakuClient {
}
public onEnter(command: any): void {
const data = command.data;
this.eventsRaw?.enter?.forEach((d) => { d(data, command); });
this.eventsAsModel.enter?.forEach((d) => {
d(
{
type: EventDataTypes.Enter,
uname: data.uname,
uid: data.uid,
msg: '',
price: 0,
num: 1,
time: Date.now(),
guard_level: 0,
fans_medal_level: data.fans_medal?.medal_level || 0,
fans_medal_name: data.fans_medal?.medal_name || '',
fans_medal_wearing_status: false,
uface: AVATAR_URL + data.uid,
open_id: '',
ouid: GuidUtils.numToGuid(data.uid)
},
command
);
});
const msgType = data.msg_type;
if (msgType === 1) {
this.eventsRaw?.enter?.forEach((d) => { d(data, command); });
this.eventsAsModel.enter?.forEach((d) => {
d(
{
type: EventDataTypes.Enter,
uname: data.uname,
uid: data.uid,
msg: '',
price: 0,
num: 1,
time: data.timestamp ? data.timestamp * 1000 : Date.now(),
guard_level: data.privilege_type || GuardLevel.None,
fans_medal_level: data.fans_medal?.medal_level || 0,
fans_medal_name: data.fans_medal?.medal_name || '',
fans_medal_wearing_status: data.fans_medal?.is_lighted === 1,
uface: data.face?.replace("http://", "https://") || (AVATAR_URL + data.uid),
open_id: '',
ouid: GuidUtils.numToGuid(data.uid)
},
command
);
});
}
else if (msgType === 2) {
this.eventsRaw?.follow?.forEach((d) => { d(data, command); });
this.eventsAsModel.follow?.forEach((d) => {
d(
{
type: EventDataTypes.Follow,
uname: data.uname,
uid: data.uid,
msg: '关注了主播',
price: 0,
num: 1,
time: data.timestamp ? data.timestamp * 1000 : Date.now(),
guard_level: data.privilege_type || GuardLevel.None,
fans_medal_level: data.fans_medal?.medal_level || 0,
fans_medal_name: data.fans_medal?.medal_name || '',
fans_medal_wearing_status: data.fans_medal?.is_lighted === 1,
uface: data.face?.replace("http://", "https://") || (AVATAR_URL + data.uid),
open_id: '',
ouid: GuidUtils.numToGuid(data.uid)
},
command
);
});
}
}
public onScDel(command: any): void {
const data = command.data;