feat: 重构弹幕组件和工具以改进结构和性能

- 更新 `useWebFetcher.ts`:将事件监听器从 `onEvent` 更改为 `on`,并修改了断开连接处理逻辑,增加了 30 秒后自动重连的功能。
- 增强 `MessageRender.vue`:为 `paidMessages` 使用 v-model,并将生命周期钩子更新为 `beforeUnmount`。
- 引入新组件 `ClientDanmakuItem.vue`:用于渲染具有卡片和文本样式的弹幕条目。
- 创建 `BaseDanmakuItem.vue`:封装弹幕条目的通用逻辑,包括表情符号解析和显示逻辑。
- 添加 `CardStyleDanmakuItem.vue` 和 `TextStyleDanmakuItem.vue`:用于实现不同显示样式的弹幕消息。
- 开发 `danmakuUtils.ts`:提供用于弹幕条目属性和样式的工具函数。
- 改进弹幕组件的 CSS 样式:确保外观统一和响应式布局。
This commit is contained in:
2025-04-15 22:18:47 +08:00
parent ff755afd99
commit 1ea4404307
18 changed files with 1898 additions and 433 deletions

View File

@@ -1,23 +1,11 @@
<script setup lang="ts">
import { useDanmakuWindow } from './store/useDanmakuWindow';
import { NAlert, NButton, NCard, NCheckbox, NCheckboxGroup, NColorPicker, NDivider, NFlex, NForm, NFormItem, NGi, NGrid, NIcon, NInputNumber, NRadioButton, NRadioGroup, NSelect, NSlider, NSpace, NSwitch, NTabPane, NTabs, NText, useMessage } from 'naive-ui';
import { ref } from 'vue';
import { useRoute } from 'vue-router';
import { EventDataTypes } from '@/api/api-models';
import { useMessage } from 'naive-ui';
import { ref, computed } from 'vue';
import {
NButton, NCard, NSpace, NSlider, NSwitch, NSelect, NInputNumber,
NColorPicker, NDivider, NGrid, NGi, NFlex, NCheckbox, NCheckboxGroup,
NIcon, NTooltip, NSpin, NText, NAlert, NTabs, NTabPane, NForm, NFormItem
} from 'naive-ui';
import { useDanmakuWindow } from './store/useDanmakuWindow';
import {
DesktopMac24Regular,
TextFont24Regular,
ColorFill24Regular,
AppsList24Regular,
DesignIdeas24Regular,
CheckmarkCircle24Regular,
ResizeTable24Filled,
ResizeTable24Filled
} from '@vicons/fluent';
const danmakuWindow = useDanmakuWindow();
@@ -55,6 +43,16 @@ const presets = {
}
};
// 自动消失时间选项
const autoDisappearOptions = [
{ label: '不自动消失', value: 0 },
{ label: '10秒', value: 10 },
{ label: '30秒', value: 30 },
{ label: '1分钟', value: 60 },
{ label: '3分钟', value: 180 },
{ label: '5分钟', value: 300 },
];
// 应用预设
function applyPreset(preset: 'dark' | 'light' | 'transparent') {
const presetData = presets[preset];
@@ -65,10 +63,27 @@ function applyPreset(preset: 'dark' | 'light' | 'transparent') {
}
// 重置位置到屏幕中央
async function resetPosition() {
async function resetPosition() {
console.log(danmakuWindow.danmakuWindowSetting.height)
danmakuWindow.setDanmakuWindowPosition(0, 0);
message.success('窗口位置已重置');
}
// 新增:弹幕展示风格选项
const displayStyleOptions = [
{ label: '卡片风格', value: 'card' },
{ label: '纯文本风格', value: 'text' }
];
// 新增:分隔符选项
const separatorOptions = [
{ label: ': (冒号+空格)', value: ': ' },
{ label: '(中文冒号)', value: '' },
{ label: '> ', value: '> ' },
{ label: '| ', value: '| ' },
{ label: '- ', value: '- ' },
{ label: '→ ', value: '→ ' },
];
</script>
<template>
@@ -192,7 +207,6 @@ async function resetPosition() {
<NGrid
:cols="2"
:x-gap="12"
:y-gap="12"
>
<NGi>
<NFormItem label="背景颜色">
@@ -256,23 +270,6 @@ async function resetPosition() {
justify="space-between"
align="center"
>
<NSpace>
<NFormItem label="启用阴影">
<NSwitch
v-model:value="danmakuWindow.danmakuWindowSetting.enableShadow"
/>
</NFormItem>
<NFormItem
v-if="danmakuWindow.danmakuWindowSetting.enableShadow"
label="阴影颜色"
>
<NColorPicker
v-model:value="danmakuWindow.danmakuWindowSetting.shadowColor"
:show-alpha="true"
/>
</NFormItem>
</NSpace>
<NSpace>
<NButton @click="applyPreset('dark')">
暗色主题
@@ -294,8 +291,25 @@ async function resetPosition() {
>
<NGrid
:cols="1"
:y-gap="12"
>
<!-- 新增弹幕展示风格 -->
<NGi>
<NFormItem label="展示风格">
<NRadioGroup v-model:value="danmakuWindow.danmakuWindowSetting.displayStyle">
<NSpace>
<NRadioButton
v-for="option in displayStyleOptions"
:key="option.value"
:value="option.value"
>
{{ option.label }}
</NRadioButton>
</NSpace>
</NRadioGroup>
</NFormItem>
</NGi>
<!-- 其他内容设置 -->
<NGi>
<NFormItem label="信息显示">
<NCheckboxGroup v-model:value="danmakuWindow.danmakuWindowSetting.filterTypes">
@@ -315,22 +329,22 @@ async function resetPosition() {
<NFormItem label="显示选项">
<NSpace>
<NCheckbox
:checked="danmakuWindow.danmakuWindowSetting.showAvatar"
v-model:checked="danmakuWindow.danmakuWindowSetting.showAvatar"
>
显示头像
</NCheckbox>
<NCheckbox
:checked="danmakuWindow.danmakuWindowSetting.showUsername"
v-model:checked="danmakuWindow.danmakuWindowSetting.showUsername"
>
显示用户名
</NCheckbox>
<NCheckbox
:checked="danmakuWindow.danmakuWindowSetting.showFansMedal"
v-model:checked="danmakuWindow.danmakuWindowSetting.showFansMedal"
>
显示粉丝牌
</NCheckbox>
<NCheckbox
:checked="danmakuWindow.danmakuWindowSetting.showGuardIcon"
v-model:checked="danmakuWindow.danmakuWindowSetting.showGuardIcon"
>
显示舰长图标
</NCheckbox>
@@ -338,6 +352,44 @@ async function resetPosition() {
</NFormItem>
</NGi>
<!-- 新增纯文本风格特定设置 -->
<NGi v-if="danmakuWindow.danmakuWindowSetting.displayStyle === 'text'">
<NDivider>纯文本风格设置</NDivider>
<NSpace vertical>
<NFormItem label="紧凑布局">
<NSwitch v-model:value="danmakuWindow.danmakuWindowSetting.textStyleCompact" />
<NText
depth="3"
style="margin-left: 8px"
>
启用后减少边距适合小窗口
</NText>
</NFormItem>
<NFormItem label="显示消息类型">
<NSwitch v-model:value="danmakuWindow.danmakuWindowSetting.textStyleShowType" />
<NText
depth="3"
style="margin-left: 8px"
>
显示礼物SC等类型标签
</NText>
</NFormItem>
<NFormItem label="用户名分隔符">
<NSelect
v-model:value="danmakuWindow.danmakuWindowSetting.textStyleNameSeparator"
:options="separatorOptions"
style="width: 160px"
/>
</NFormItem>
</NSpace>
</NGi>
<NGi>
<NDivider>弹幕行为</NDivider>
</NGi>
<NGi>
<NFormItem label="弹幕方向">
<NSpace align="center">
@@ -374,6 +426,95 @@ async function resetPosition() {
</NInputNumber>
</NFormItem>
</NGi>
<NGi>
<NFormItem label="自动消失时间">
<NSpace vertical>
<NSlider
v-model:value="danmakuWindow.danmakuWindowSetting.autoDisappearTime"
:min="0"
:max="300"
:step="5"
:marks="{
0: '不消失',
60: '1分钟',
300: '5分钟'
}"
/>
<NSpace justify="space-between">
<NButton
v-for="option in autoDisappearOptions"
:key="option.value"
size="small"
:type="danmakuWindow.danmakuWindowSetting.autoDisappearTime === option.value ? 'primary' : 'default'"
@click="danmakuWindow.danmakuWindowSetting.autoDisappearTime = option.value"
>
{{ option.label }}
</NButton>
</NSpace>
<NText
v-if="danmakuWindow.danmakuWindowSetting.autoDisappearTime > 0"
depth="3"
>
弹幕将在 {{ danmakuWindow.danmakuWindowSetting.autoDisappearTime }} 秒后自动消失
</NText>
<NText
v-else
depth="3"
>
弹幕不会自动消失
</NText>
</NSpace>
</NFormItem>
</NGi>
</NGrid>
</NTabPane>
<!-- 添加新的设置选项卡高级设置 -->
<NTabPane
name="advanced"
tab="高级设置"
>
<NGrid
:cols="1"
:y-gap="4"
>
<NGi>
<NDivider>调试选项</NDivider>
<NSpace vertical>
<NButton
type="info"
@click="danmakuWindow.sendTestDanmaku && danmakuWindow.sendTestDanmaku()"
>
发送测试弹幕
</NButton>
<NButton
type="warning"
@click="danmakuWindow.clearAllDanmaku && danmakuWindow.clearAllDanmaku()"
>
清空弹幕
</NButton>
<NFlex>
<NText>
当前表情数据:
Inline: {{ Object.keys(danmakuWindow.emojiData.data.inline).length }}
<br>
Plain: {{ Object.keys(danmakuWindow.emojiData.data.plain).length }}
</NText>
<NButton
@click="async () => {
await danmakuWindow.getEmojiData()
message.success('表情数据已重新加载')
}"
>
<template #icon>
<NIcon :component="ResizeTable24Filled" />
</template>
重新加载表情数据
</NButton>
</NFlex>
</NSpace>
</NGi>
</NGrid>
</NTabPane>
</NTabs>
@@ -393,4 +534,22 @@ async function resetPosition() {
z-index: 9999;
background-color: rgba(245, 108, 108, 0.1);
}
/* 添加一些美化样式 */
:deep(.n-tabs-tab) {
padding: 12px 20px;
}
:deep(.n-divider) {
margin: 12px 0;
}
.n-alert {
margin-bottom: 16px;
}
:deep(.n-slider) {
width: 100%;
max-width: 500px;
}
</style>