mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-10 20:36:55 +08:00
feat: 更新项目配置和依赖,增强功能和用户体验
- 完成弹幕机功能 - 在 .editorconfig 中新增对 vine.ts 文件的支持。 - 更新 package.json 中多个依赖的版本,提升稳定性和性能。 - 在 vite.config.mts 中引入 @guolao/vue-monaco-editor 插件,增强代码编辑功能。 - 在 App.vue 中调整内容填充的样式,优化界面布局。 - 新增获取配置文件哈希的 API 方法,提升配置管理能力。 - 在多个组件中优化了样式和逻辑,提升用户交互体验。
This commit is contained in:
@@ -508,8 +508,26 @@ onMounted(() => {
|
||||
v-for="(label, type) in typeMap"
|
||||
:key="type"
|
||||
:name="type"
|
||||
:tab="label"
|
||||
>
|
||||
<template #tab>
|
||||
<NSpace
|
||||
align="center"
|
||||
size="small"
|
||||
inline
|
||||
>
|
||||
{{ label }}
|
||||
<span
|
||||
:style="{
|
||||
color: enabledTriggerTypes && enabledTriggerTypes[type] ? '#18a058' : '#d03050',
|
||||
fontSize: '14px', // Adjust size as needed
|
||||
verticalAlign: 'middle'
|
||||
}"
|
||||
:title="enabledTriggerTypes && enabledTriggerTypes[type] ? '已启用' : '已禁用'"
|
||||
>
|
||||
●
|
||||
</span>
|
||||
</NSpace>
|
||||
</template>
|
||||
<NSpace vertical>
|
||||
<NSpace
|
||||
v-if="enabledTriggerTypes"
|
||||
|
||||
@@ -30,6 +30,7 @@ export function filterValidActions(
|
||||
options?: {
|
||||
actionType?: ActionType; // 特定操作类型
|
||||
customFilter?: (action: AutoActionItem) => boolean; // 自定义过滤器
|
||||
enabledTriggerTypes?: Ref<Record<TriggerType, boolean>> // 触发类型启用状态
|
||||
}
|
||||
): AutoActionItem[] {
|
||||
return actions.filter(action => {
|
||||
@@ -38,6 +39,11 @@ export function filterValidActions(
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查触发类型是否启用
|
||||
if (options?.enabledTriggerTypes && !options.enabledTriggerTypes.value[triggerType]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 直播状态过滤
|
||||
if (action.triggerConfig.onlyDuringLive && !isLive.value) {
|
||||
return false;
|
||||
@@ -146,6 +152,38 @@ export function processTemplate(
|
||||
}
|
||||
}
|
||||
|
||||
// 辅助函数:发送弹幕并记录日志
|
||||
async function sendAndLogDanmaku(
|
||||
sendHandler: (roomId: number, message: string) => Promise<boolean>,
|
||||
action: AutoActionItem,
|
||||
roomId: number,
|
||||
message: string
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
const success = await sendHandler(roomId, message);
|
||||
logDanmakuHistory(
|
||||
action.id,
|
||||
action.name || '未命名操作',
|
||||
message,
|
||||
roomId,
|
||||
success,
|
||||
success ? undefined : '发送失败'
|
||||
).catch(err => console.error('记录弹幕历史失败:', err));
|
||||
return success;
|
||||
} catch (err) {
|
||||
console.error(`[AutoAction] 发送弹幕失败 (${action.name || action.id}):`, err);
|
||||
logDanmakuHistory(
|
||||
action.id,
|
||||
action.name || '未命名操作',
|
||||
message,
|
||||
roomId,
|
||||
false,
|
||||
err instanceof Error ? err.toString() : String(err) // 确保err是字符串
|
||||
).catch(e => console.error('记录弹幕历史失败:', e));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行操作的通用函数
|
||||
* @param actions 过滤后的操作列表
|
||||
@@ -220,61 +258,13 @@ export function executeActions(
|
||||
// 更新冷却时间
|
||||
runtimeState.lastExecutionTime[action.id] = Date.now();
|
||||
|
||||
const sendAction = () => sendAndLogDanmaku(handlers.sendLiveDanmaku!, action, roomId, message);
|
||||
|
||||
// 延迟发送
|
||||
if (action.actionConfig.delaySeconds && action.actionConfig.delaySeconds > 0) {
|
||||
setTimeout(() => {
|
||||
handlers.sendLiveDanmaku!(roomId, message)
|
||||
.then(success => {
|
||||
// 记录弹幕发送历史
|
||||
logDanmakuHistory(
|
||||
action.id,
|
||||
action.name || '未命名操作',
|
||||
message,
|
||||
roomId,
|
||||
success,
|
||||
success ? undefined : '发送失败'
|
||||
).catch(err => console.error('记录弹幕历史失败:', err));
|
||||
return success;
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(`[AutoAction] 发送弹幕失败 (${action.name || action.id}):`, err);
|
||||
// 记录失败的发送
|
||||
logDanmakuHistory(
|
||||
action.id,
|
||||
action.name || '未命名操作',
|
||||
message,
|
||||
roomId,
|
||||
false,
|
||||
err.toString()
|
||||
).catch(e => console.error('记录弹幕历史失败:', e));
|
||||
});
|
||||
}, action.actionConfig.delaySeconds * 1000);
|
||||
setTimeout(sendAction, action.actionConfig.delaySeconds * 1000);
|
||||
} else {
|
||||
handlers.sendLiveDanmaku(roomId, message)
|
||||
.then(success => {
|
||||
// 记录弹幕发送历史
|
||||
logDanmakuHistory(
|
||||
action.id,
|
||||
action.name || '未命名操作',
|
||||
message,
|
||||
roomId,
|
||||
success,
|
||||
success ? undefined : '发送失败'
|
||||
).catch(err => console.error('记录弹幕历史失败:', err));
|
||||
return success;
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(`[AutoAction] 发送弹幕失败 (${action.name || action.id}):`, err);
|
||||
// 记录失败的发送
|
||||
logDanmakuHistory(
|
||||
action.id,
|
||||
action.name || '未命名操作',
|
||||
message,
|
||||
roomId,
|
||||
false,
|
||||
err.toString()
|
||||
).catch(e => console.error('记录弹幕历史失败:', e));
|
||||
});
|
||||
sendAction();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -321,7 +311,7 @@ export function executeActions(
|
||||
msg,
|
||||
uid,
|
||||
false,
|
||||
err.toString()
|
||||
err instanceof Error ? err.toString() : String(err) // 确保err是字符串
|
||||
).catch(e => console.error('记录私信历史失败:', e));
|
||||
return false; // 明确返回 false 表示失败
|
||||
});
|
||||
|
||||
@@ -28,19 +28,21 @@ import {
|
||||
createDefaultRuntimeState
|
||||
} from './autoAction/utils';
|
||||
import { evaluateTemplateExpressions } from './autoAction/expressionEvaluator';
|
||||
// 导入 actionUtils 工具函数
|
||||
import { filterValidActions, checkUserFilters, checkCooldown, processTemplate, executeActions } from './autoAction/actionUtils';
|
||||
// 导入 nanoid 用于生成唯一 ID
|
||||
import { nanoid } from 'nanoid';
|
||||
// 导入开发环境判断标志
|
||||
import { isDev } from '@/data/constants.js';
|
||||
|
||||
// 导入所有自动操作子模块
|
||||
import { useGiftThank } from './autoAction/modules/giftThank.js';
|
||||
import { useGuardPm } from './autoAction/modules/guardPm.js';
|
||||
import { useFollowThank } from './autoAction/modules/followThank.js';
|
||||
import { useEntryWelcome } from './autoAction/modules/entryWelcome.js';
|
||||
import { useAutoReply } from './autoAction/modules/autoReply.js';
|
||||
import { useScheduledDanmaku } from './autoAction/modules/scheduledDanmaku.js';
|
||||
import { useSuperChatThank } from './autoAction/modules/superChatThank.js';
|
||||
import { useGiftThank } from './autoAction/modules/giftThank';
|
||||
import { useGuardPm } from './autoAction/modules/guardPm';
|
||||
import { useFollowThank } from './autoAction/modules/followThank';
|
||||
import { useEntryWelcome } from './autoAction/modules/entryWelcome';
|
||||
import { useAutoReply } from './autoAction/modules/autoReply';
|
||||
import { useScheduledDanmaku } from './autoAction/modules/scheduledDanmaku';
|
||||
import { useSuperChatThank } from './autoAction/modules/superChatThank';
|
||||
|
||||
// 定义名为 'autoAction' 的 Pinia store
|
||||
export const useAutoAction = defineStore('autoAction', () => {
|
||||
@@ -540,38 +542,6 @@ export const useAutoAction = defineStore('autoAction', () => {
|
||||
// 定时检查天选状态 (每5分钟)
|
||||
const tianXuanTimer = setInterval(checkTianXuanStatus, 5 * 60 * 1000);
|
||||
|
||||
/**
|
||||
* 判断是否应处理某个操作项 (基于事件和配置)
|
||||
* @param action 操作项配置
|
||||
* @param event 可选的事件数据
|
||||
* @returns 是否应该处理
|
||||
*/
|
||||
function shouldProcessAction(action: AutoActionItem, event?: EventModel | null): boolean {
|
||||
if (!action.enabled) return false; // 未启用则跳过
|
||||
if (!enabledTriggerTypes.value[action.triggerType]) return false; // 触发类型未启用则跳过
|
||||
|
||||
// 检查模板是否为空 (添加新的检查)
|
||||
if (!action.template || action.template.trim() === '') {
|
||||
console.warn(`[AutoAction] 跳过操作 "${action.name}":未设置有效模板`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 根据配置检查条件
|
||||
if (action.triggerConfig.onlyDuringLive && !isLive.value) return false; // 仅直播时
|
||||
if (action.triggerConfig.ignoreTianXuan && isTianXuanActive.value) return false; // 忽略天选时
|
||||
// 用户过滤条件
|
||||
if (event && action.triggerConfig.userFilterEnabled) {
|
||||
if (action.triggerConfig.requireMedal && !event.fans_medal_wearing_status) return false; // 要求粉丝牌
|
||||
if (action.triggerConfig.requireCaptain && event.guard_level === GuardLevel.None) return false; // 要求舰长
|
||||
}
|
||||
// 逻辑表达式判断
|
||||
if (action.logicalExpression && event) {
|
||||
const context = buildExecutionContext(event, roomId.value, action.triggerType);
|
||||
if (!evaluateExpression(action.logicalExpression, context)) return false; // 表达式不满足
|
||||
}
|
||||
return true; // 所有条件满足
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理接收到的事件
|
||||
* @param event 事件数据
|
||||
@@ -579,10 +549,8 @@ export const useAutoAction = defineStore('autoAction', () => {
|
||||
*/
|
||||
function processEvent(event: EventModel, triggerType: TriggerType) {
|
||||
if (!roomId.value) return; // 房间 ID 无效则跳过
|
||||
|
||||
// 检查触发类型是否启用
|
||||
if (!enabledTriggerTypes.value[triggerType]) return;
|
||||
|
||||
// 根据触发类型调用相应模块的处理函数
|
||||
switch (triggerType) {
|
||||
case TriggerType.DANMAKU:
|
||||
|
||||
Reference in New Issue
Block a user