feat: 更新依赖项和配置,添加新通知类型

- 在 package.json 中添加了 @types/md5 和 @vueuse/integrations 依赖。
- 更新了 tsconfig.json 中的模块解析方式为 bundler。
- 在组件声明中移除了不再使用的 Naive UI 组件。
- 在弹幕窗口和设置中添加了启用动画的选项,并更新了相关样式。
- 实现了私信发送失败的通知功能,增强了用户体验。
This commit is contained in:
2025-04-19 22:29:09 +08:00
parent 521cd1eddf
commit 630fe45b47
51 changed files with 5067 additions and 1690 deletions

View File

@@ -0,0 +1,196 @@
<script setup lang="ts">
import { NSpace, NSwitch, NInputNumber, NInput, NCollapseItem } from 'naive-ui';
import { AutoActionItem, TriggerType } from '@/client/store/useAutoAction';
import { computed } from 'vue';
const props = defineProps({
action: {
type: Object as () => AutoActionItem,
required: true
}
});
// 根据触发类型判断是否显示用户过滤选项
const showUserFilter = computed(() => {
return ![TriggerType.SCHEDULED].includes(props.action.triggerType);
});
</script>
<template>
<NCollapse>
<NCollapseItem
v-if="showUserFilter"
key="user-filter"
title="用户过滤"
class="settings-section"
>
<div>
<NSpace
key="user-filter-enabled"
vertical
class="settings-subsection"
>
<NSpace
align="center"
justify="space-between"
style="width: 100%"
class="setting-item"
>
<span>启用用户过滤:</span>
<NSwitch v-model:value="action.triggerConfig.userFilterEnabled" />
</NSpace>
<template v-if="action.triggerConfig.userFilterEnabled">
<NSpace
key="require-medal"
align="center"
justify="space-between"
style="width: 100%"
class="setting-item"
>
<span>要求本房间勋章:</span>
<NSwitch v-model:value="action.triggerConfig.requireMedal" />
</NSpace>
<NSpace
key="require-captain"
align="center"
justify="space-between"
style="width: 100%"
class="setting-item"
>
<span>要求任意舰长:</span>
<NSwitch v-model:value="action.triggerConfig.requireCaptain" />
</NSpace>
</template>
</NSpace>
</div>
</NCollapseItem>
<NCollapseItem
key="cooldown"
title="冷却控制"
class="settings-section"
>
<div>
<NSpace
key="ignore-cooldown"
align="center"
justify="space-between"
style="width: 100%"
class="setting-item"
>
<span>忽略全局冷却:</span>
<NSwitch v-model:value="action.ignoreCooldown" />
</NSpace>
<NSpace
key="delay-seconds"
align="center"
justify="space-between"
style="width: 100%"
class="setting-item"
>
<span>延迟执行():</span>
<NInputNumber
v-model:value="action.actionConfig.delaySeconds"
:min="0"
:max="600"
style="width: 120px"
/>
</NSpace>
<NSpace
key="cooldown-seconds"
align="center"
justify="space-between"
style="width: 100%"
class="setting-item"
>
<span>冷却时间():</span>
<NInputNumber
v-model:value="action.actionConfig.cooldownSeconds"
:min="0"
:max="3600"
style="width: 120px"
/>
</NSpace>
</div>
</NCollapseItem>
<NCollapseItem
key="logical-expression"
title="逻辑条件表达式"
class="settings-section"
>
<div>
<NSpace vertical>
<p class="description">
当表达式为真时才会执行此操作可使用JS语法例如: <code>user.guardLevel > 0 || gift.price > 10</code>
</p>
<NInput
v-model:value="action.logicalExpression"
type="textarea"
placeholder="输入表达式,留空则始终为真"
:autosize="{ minRows: 2, maxRows: 5 }"
/>
</NSpace>
</div>
</NCollapseItem>
<NCollapseItem
key="custom-js"
title="自定义JS执行"
class="settings-section"
>
<div>
<NSpace vertical>
<p class="description">
可访问 context, event, biliFunc, roomId 等变量
</p>
<NInput
v-model:value="action.executeCommand"
type="textarea"
placeholder="输入要执行的JS代码"
:autosize="{ minRows: 3, maxRows: 8 }"
/>
</NSpace>
</div>
</NCollapseItem>
</NCollapse>
</template>
<style scoped>
.settings-section {
margin-bottom: 12px;
position: relative;
}
.settings-subsection {
position: relative;
}
.setting-item {
padding: 4px 8px;
border-radius: 4px;
}
.setting-item:hover {
background-color: rgba(0, 0, 0, 0.02);
}
.description {
margin-top: 8px;
font-size: 13px;
color: #999;
}
code {
background-color: rgba(0, 0, 0, 0.06);
padding: 2px 4px;
border-radius: 4px;
font-family: monospace;
}
/* 已移除所有动画相关样式 */
</style>

View File

@@ -0,0 +1,143 @@
<script setup lang="ts">
import { NSpace, NInput, NSwitch, NSelect } from 'naive-ui';
import { AutoActionItem, TriggerType, ActionType, Priority } from '@/client/store/useAutoAction';
const props = defineProps({
action: {
type: Object as () => AutoActionItem,
required: true
}
});
// 触发类型选项
const triggerTypeOptions = [
{ label: '弹幕触发', value: TriggerType.DANMAKU },
{ label: '礼物感谢', value: TriggerType.GIFT },
{ label: '上舰感谢', value: TriggerType.GUARD },
{ label: '关注感谢', value: TriggerType.FOLLOW },
{ label: '入场欢迎', value: TriggerType.ENTER },
{ label: '定时发送', value: TriggerType.SCHEDULED },
{ label: 'SC感谢', value: TriggerType.SUPER_CHAT },
];
// 操作类型选项
const actionTypeOptions = [
{ label: '发送弹幕', value: ActionType.SEND_DANMAKU },
{ label: '发送私信', value: ActionType.SEND_PRIVATE_MSG },
{ label: '执行命令', value: ActionType.EXECUTE_COMMAND },
];
// 优先级选项
const priorityOptions = [
{ label: '最高', value: Priority.HIGHEST },
{ label: '高', value: Priority.HIGH },
{ label: '普通', value: Priority.NORMAL },
{ label: '低', value: Priority.LOW },
{ label: '最低', value: Priority.LOWEST },
];
</script>
<template>
<div class="basic-settings-container">
<NSpace
vertical
class="basic-settings"
>
<NSpace
key="name"
align="center"
justify="space-between"
style="width: 100%"
class="setting-item"
>
<span>名称:</span>
<NInput
v-model:value="action.name"
style="width: 300px"
/>
</NSpace>
<NSpace
key="enabled"
align="center"
justify="space-between"
style="width: 100%"
class="setting-item"
>
<span>启用:</span>
<NSwitch v-model:value="action.enabled" />
</NSpace>
<NSpace
key="only-during-live"
align="center"
justify="space-between"
style="width: 100%"
class="setting-item"
>
<span>仅直播中启用:</span>
<NSwitch v-model:value="action.triggerConfig.onlyDuringLive" />
</NSpace>
<NSpace
key="ignore-tianxuan"
align="center"
justify="space-between"
style="width: 100%"
class="setting-item"
>
<span>天选时刻忽略:</span>
<NSwitch v-model:value="action.triggerConfig.ignoreTianXuan" />
</NSpace>
<NSpace
key="triggerType"
align="center"
justify="space-between"
style="width: 100%"
class="setting-item"
>
<span>触发类型:</span>
<NSelect
v-model:value="action.triggerType"
style="width: 300px"
:options="triggerTypeOptions"
disabled
/>
</NSpace>
<NSpace
key="actionType"
align="center"
justify="space-between"
style="width: 100%"
class="setting-item"
>
<span>操作类型:</span>
<NSelect
v-model:value="action.actionType"
style="width: 300px"
:options="actionTypeOptions"
/>
</NSpace>
<NSpace
key="priority"
align="center"
justify="space-between"
style="width: 100%"
class="setting-item"
>
<span>优先级:</span>
<NSelect
v-model:value="action.priority"
style="width: 300px"
:options="priorityOptions"
/>
</NSpace>
</NSpace>
</div>
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,137 @@
<script setup lang="ts">
import { ref } from 'vue';
import { NSpace, NInput, NButton, NTag, NDivider, NCollapseItem, useMessage } from 'naive-ui';
import { AutoActionItem, TriggerType } from '@/client/store/useAutoAction';
const props = defineProps({
action: {
type: Object as () => AutoActionItem,
required: true
}
});
const message = useMessage();
// 弹幕关键词相关
const tempKeyword = ref('');
const tempBlockword = ref('');
// 添加关键词
function addKeyword() {
if (!tempKeyword.value.trim()) return;
if (!props.action.triggerConfig.keywords) {
props.action.triggerConfig.keywords = [];
}
if (!props.action.triggerConfig.keywords.includes(tempKeyword.value.trim())) {
props.action.triggerConfig.keywords.push(tempKeyword.value.trim());
tempKeyword.value = '';
} else {
message.warning('此关键词已存在');
}
}
// 移除关键词
function removeKeyword(index: number) {
if (props.action.triggerConfig.keywords) {
props.action.triggerConfig.keywords.splice(index, 1);
}
}
// 添加屏蔽词
function addBlockword() {
if (!tempBlockword.value.trim()) return;
if (!props.action.triggerConfig.blockwords) {
props.action.triggerConfig.blockwords = [];
}
if (!props.action.triggerConfig.blockwords.includes(tempBlockword.value.trim())) {
props.action.triggerConfig.blockwords.push(tempBlockword.value.trim());
tempBlockword.value = '';
} else {
message.warning('此屏蔽词已存在');
}
}
// 移除屏蔽词
function removeBlockword(index: number) {
if (props.action.triggerConfig.blockwords) {
props.action.triggerConfig.blockwords.splice(index, 1);
}
}
</script>
<template>
<NCollapseItem
v-if="action.triggerType === TriggerType.DANMAKU"
title="自动回复设置"
>
<NSpace vertical>
<div class="section-title">
触发关键词:
</div>
<NSpace>
<NInput
v-model:value="tempKeyword"
placeholder="输入关键词"
@keyup.enter="addKeyword"
/>
<NButton @click="addKeyword">
添加
</NButton>
</NSpace>
<NSpace>
<template v-if="action.triggerConfig.keywords">
<NTag
v-for="(keyword, index) in action.triggerConfig.keywords"
:key="index"
closable
@close="removeKeyword(index)"
>
{{ keyword }}
</NTag>
</template>
</NSpace>
<NDivider />
<div class="section-title">
屏蔽词:
</div>
<NSpace>
<NInput
v-model:value="tempBlockword"
placeholder="输入屏蔽词"
@keyup.enter="addBlockword"
/>
<NButton @click="addBlockword">
添加
</NButton>
</NSpace>
<NSpace>
<template v-if="action.triggerConfig.blockwords">
<NTag
v-for="(blockword, index) in action.triggerConfig.blockwords"
:key="index"
closable
type="warning"
@close="removeBlockword(index)"
>
{{ blockword }}
</NTag>
</template>
</NSpace>
</NSpace>
</NCollapseItem>
</template>
<style scoped>
.section-title {
font-weight: bold;
margin: 8px 0;
}
</style>

View File

@@ -0,0 +1,65 @@
<script setup lang="ts">
import { NSpace, NSwitch, NInputNumber, NSelect, NCollapseItem } from 'naive-ui';
import { AutoActionItem, TriggerType } from '@/client/store/useAutoAction';
const props = defineProps({
action: {
type: Object as () => AutoActionItem,
required: true
}
});
// 入场过滤模式选项
const enterFilterModeOptions = [
{ label: '不过滤', value: 'none' },
{ label: '用户黑名单', value: 'blacklist' },
{ label: '用户白名单', value: 'whitelist' },
{ label: '仅舰长', value: 'guard' },
{ label: '仅勋章', value: 'medal' }
];
</script>
<template>
<NCollapseItem
v-if="action.triggerType === TriggerType.ENTER"
title="入场触发设置"
>
<NSpace vertical>
<NSpace
align="center"
justify="space-between"
style="width: 100%"
>
<span>入场过滤模式:</span>
<NSelect
v-model:value="action.triggerConfig.enterFilterMode"
style="width: 200px"
:options="enterFilterModeOptions"
/>
</NSpace>
<NSpace
align="center"
justify="space-between"
style="width: 100%"
>
<span>防止重复发送:</span>
<NSwitch v-model:value="action.triggerConfig.preventRepeat" />
</NSpace>
<NSpace
align="center"
justify="space-between"
style="width: 100%"
>
<span>每次处理的最大用户数:</span>
<NInputNumber
v-model:value="action.actionConfig.maxUsersPerMsg"
:min="1"
:max="20"
style="width: 120px"
/>
</NSpace>
</NSpace>
</NCollapseItem>
</template>

View File

@@ -0,0 +1,43 @@
<script setup lang="ts">
import { NSpace, NSwitch, NInputNumber, NCollapseItem } from 'naive-ui';
import { AutoActionItem, TriggerType } from '@/client/store/useAutoAction';
const props = defineProps({
action: {
type: Object as () => AutoActionItem,
required: true
}
});
</script>
<template>
<NCollapseItem
v-if="action.triggerType === TriggerType.FOLLOW"
title="关注触发设置"
>
<NSpace vertical>
<NSpace
align="center"
justify="space-between"
style="width: 100%"
>
<span>防止重复发送:</span>
<NSwitch v-model:value="action.triggerConfig.preventRepeat" />
</NSpace>
<NSpace
align="center"
justify="space-between"
style="width: 100%"
>
<span>每次处理的最大用户数:</span>
<NInputNumber
v-model:value="action.actionConfig.maxUsersPerMsg"
:min="1"
:max="20"
style="width: 120px"
/>
</NSpace>
</NSpace>
</NCollapseItem>
</template>

View File

@@ -0,0 +1,149 @@
<script setup lang="ts">
import { ref } from 'vue';
import { NSpace, NInput, NButton, NTag, NSelect, NInputNumber, NSwitch, NCollapseItem, useMessage } from 'naive-ui';
import { AutoActionItem, TriggerType } from '@/client/store/useAutoAction';
const props = defineProps({
action: {
type: Object as () => AutoActionItem,
required: true
}
});
const message = useMessage();
// 礼物过滤模式选项
const giftFilterModeOptions = [
{ label: '不过滤', value: 'none' },
{ label: '礼物黑名单', value: 'blacklist' },
{ label: '礼物白名单', value: 'whitelist' },
{ label: '最低价值', value: 'value' },
{ label: '过滤免费礼物', value: 'free' }
];
// 礼物名称相关
const tempGiftName = ref('');
// 添加礼物名称到过滤列表
function addGiftName() {
if (!tempGiftName.value.trim()) return;
if (!props.action.triggerConfig.filterGiftNames) {
props.action.triggerConfig.filterGiftNames = [];
}
if (!props.action.triggerConfig.filterGiftNames.includes(tempGiftName.value.trim())) {
props.action.triggerConfig.filterGiftNames.push(tempGiftName.value.trim());
tempGiftName.value = '';
} else {
message.warning('此礼物名称已存在');
}
}
// 移除礼物名称
function removeGiftName(index: number) {
if (props.action.triggerConfig.filterGiftNames) {
props.action.triggerConfig.filterGiftNames.splice(index, 1);
}
}
</script>
<template>
<NCollapseItem
v-if="action.triggerType === TriggerType.GIFT"
title="礼物触发设置"
>
<NSpace vertical>
<NSpace
align="center"
justify="space-between"
style="width: 100%"
>
<span>礼物过滤模式:</span>
<NSelect
v-model:value="action.triggerConfig.giftFilterMode"
style="width: 200px"
:options="giftFilterModeOptions"
/>
</NSpace>
<template v-if="action.triggerConfig.giftFilterMode === 'blacklist' || action.triggerConfig.giftFilterMode === 'whitelist'">
<NSpace>
<NInput
v-model:value="tempGiftName"
placeholder="输入礼物名称"
@keyup.enter="addGiftName"
/>
<NButton @click="addGiftName">
添加
</NButton>
</NSpace>
<NSpace>
<template v-if="action.triggerConfig.filterGiftNames">
<NTag
v-for="(giftName, index) in action.triggerConfig.filterGiftNames"
:key="index"
closable
@close="removeGiftName(index)"
>
{{ giftName }}
</NTag>
</template>
</NSpace>
</template>
<template v-if="action.triggerConfig.giftFilterMode === 'value'">
<NSpace
align="center"
justify="space-between"
style="width: 100%"
>
<span>最低价值 ():</span>
<NInputNumber
v-model:value="action.triggerConfig.minValue"
:min="0"
style="width: 120px"
/>
</NSpace>
</template>
<NSpace
align="center"
justify="space-between"
style="width: 100%"
>
<span>包含礼物数量:</span>
<NSwitch v-model:value="action.triggerConfig.includeQuantity" />
</NSpace>
<NSpace
align="center"
justify="space-between"
style="width: 100%"
>
<span>每次处理的最大用户数:</span>
<NInputNumber
v-model:value="action.actionConfig.maxUsersPerMsg"
:min="1"
:max="20"
style="width: 120px"
/>
</NSpace>
<NSpace
align="center"
justify="space-between"
style="width: 100%"
>
<span>每用户最大礼物种类数:</span>
<NInputNumber
v-model:value="action.actionConfig.maxItemsPerUser"
:min="1"
:max="10"
style="width: 120px"
/>
</NSpace>
</NSpace>
</NCollapseItem>
</template>

View File

@@ -0,0 +1,152 @@
<script setup lang="ts">
import { ref } from 'vue';
import { NSpace, NInput, NButton, NTag, NSelect, NSwitch, NDivider, NCollapseItem, useMessage } from 'naive-ui';
import { AutoActionItem, TriggerType, ActionType } from '@/client/store/useAutoAction';
const props = defineProps({
action: {
type: Object as () => AutoActionItem,
required: true
}
});
const message = useMessage();
// 舰长礼品码相关
const tempGiftCodeLevel = ref(3); // 默认为舰长等级
const tempGiftCode = ref('');
// 添加礼品码
function addGiftCode() {
if (!tempGiftCode.value.trim()) return;
if (!props.action.triggerConfig.giftCodes) {
props.action.triggerConfig.giftCodes = [];
}
// 查找对应等级的礼品码数组
let levelCodes = props.action.triggerConfig.giftCodes.find(gc => gc.level === tempGiftCodeLevel.value);
if (!levelCodes) {
// 如果没有此等级的礼品码数组,创建一个
levelCodes = { level: tempGiftCodeLevel.value, codes: [] };
props.action.triggerConfig.giftCodes.push(levelCodes);
}
// 添加礼品码
if (!levelCodes.codes.includes(tempGiftCode.value.trim())) {
levelCodes.codes.push(tempGiftCode.value.trim());
tempGiftCode.value = '';
} else {
message.warning('此礼品码已存在');
}
}
// 移除礼品码
function removeGiftCode(levelIndex: number, codeIndex: number) {
if (props.action.triggerConfig.giftCodes &&
props.action.triggerConfig.giftCodes[levelIndex] &&
props.action.triggerConfig.giftCodes[levelIndex].codes) {
props.action.triggerConfig.giftCodes[levelIndex].codes.splice(codeIndex, 1);
// 如果该等级没有礼品码了,移除这个等级
if (props.action.triggerConfig.giftCodes[levelIndex].codes.length === 0) {
props.action.triggerConfig.giftCodes.splice(levelIndex, 1);
}
}
}
// 舰长等级名称映射
function getGuardLevelName(level: number): string {
switch (level) {
case 1: return '总督';
case 2: return '提督';
case 3: return '舰长';
default: return '通用';
}
}
</script>
<template>
<NCollapseItem
v-if="action.triggerType === TriggerType.GUARD"
title="上舰触发设置"
>
<NSpace vertical>
<NSpace
align="center"
justify="space-between"
style="width: 100%"
>
<span>防止重复发送:</span>
<NSwitch v-model:value="action.triggerConfig.preventRepeat" />
</NSpace>
<template v-if="action.actionType === ActionType.SEND_PRIVATE_MSG">
<NDivider title-placement="left">
礼品码设置
</NDivider>
<NSpace>
<NSelect
v-model:value="tempGiftCodeLevel"
style="width: 120px"
:options="[
{ label: '总督', value: 1 },
{ label: '提督', value: 2 },
{ label: '舰长', value: 3 },
{ label: '通用', value: 0 }
]"
/>
<NInput
v-model:value="tempGiftCode"
placeholder="输入礼品码"
@keyup.enter="addGiftCode"
/>
<NButton @click="addGiftCode">
添加
</NButton>
</NSpace>
<div v-if="action.triggerConfig.giftCodes && action.triggerConfig.giftCodes.length > 0">
<div
v-for="(levelCodes, levelIndex) in action.triggerConfig.giftCodes"
:key="levelIndex"
class="gift-code-section"
>
<div class="gift-code-level">
{{ getGuardLevelName(levelCodes.level) }}礼品码:
</div>
<div class="gift-code-list">
<NTag
v-for="(code, codeIndex) in levelCodes.codes"
:key="codeIndex"
closable
@close="removeGiftCode(levelIndex, codeIndex)"
>
{{ code }}
</NTag>
</div>
</div>
</div>
</template>
</NSpace>
</NCollapseItem>
</template>
<style scoped>
.gift-code-section {
margin: 10px 0;
}
.gift-code-level {
font-weight: bold;
margin-bottom: 5px;
}
.gift-code-list {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
</style>

View File

@@ -0,0 +1,60 @@
<script setup lang="ts">
import { NSpace, NInputNumber, NRadioGroup, NRadio, NCollapseItem } from 'naive-ui';
import { AutoActionItem, TriggerType } from '@/client/store/useAutoAction';
import { computed, ref } from 'vue';
const props = defineProps({
action: {
type: Object as () => AutoActionItem,
required: true
}
});
// 定时模式选项
const schedulingModeOptions = [
{ label: '随机模式', value: 'random' },
{ label: '顺序模式', value: 'sequential' }
];
</script>
<template>
<NCollapseItem
v-if="action.triggerType === TriggerType.SCHEDULED"
title="定时触发设置"
>
<NSpace vertical>
<NSpace
align="center"
justify="space-between"
style="width: 100%"
>
<span>发送间隔 ():</span>
<NInputNumber
v-model:value="action.triggerConfig.intervalSeconds"
:min="60"
:max="3600"
style="width: 120px"
/>
</NSpace>
<NSpace
align="center"
justify="space-between"
style="width: 100%"
>
<span>发送模式:</span>
<NRadioGroup v-model:value="action.triggerConfig.schedulingMode">
<NSpace>
<NRadio
v-for="option in schedulingModeOptions"
:key="option.value"
:value="option.value"
>
{{ option.label }}
</NRadio>
</NSpace>
</NRadioGroup>
</NSpace>
</NSpace>
</NCollapseItem>
</template>

View File

@@ -0,0 +1,77 @@
<script setup lang="ts">
import { NSpace, NSwitch, NInputNumber, NSelect, NCollapseItem } from 'naive-ui';
import { AutoActionItem, TriggerType } from '@/client/store/useAutoAction';
const props = defineProps({
action: {
type: Object as () => AutoActionItem,
required: true
}
});
// SC过滤模式选项
const scFilterModeOptions = [
{ label: '不过滤', value: 'none' },
{ label: '最低价格', value: 'price' }
];
</script>
<template>
<NCollapseItem
v-if="action.triggerType === TriggerType.SUPER_CHAT"
title="SC触发设置"
>
<NSpace vertical>
<NSpace
align="center"
justify="space-between"
style="width: 100%"
>
<span>SC过滤模式:</span>
<NSelect
v-model:value="action.triggerConfig.scFilterMode"
style="width: 200px"
:options="scFilterModeOptions"
/>
</NSpace>
<template v-if="action.triggerConfig.scFilterMode === 'price'">
<NSpace
align="center"
justify="space-between"
style="width: 100%"
>
<span>最低价格 ():</span>
<NInputNumber
v-model:value="action.triggerConfig.minPrice"
:min="0"
style="width: 120px"
/>
</NSpace>
</template>
<NSpace
align="center"
justify="space-between"
style="width: 100%"
>
<span>防止重复发送:</span>
<NSwitch v-model:value="action.triggerConfig.preventRepeat" />
</NSpace>
<NSpace
align="center"
justify="space-between"
style="width: 100%"
>
<span>每次处理的最大用户数:</span>
<NInputNumber
v-model:value="action.actionConfig.maxUsersPerMsg"
:min="1"
:max="20"
style="width: 120px"
/>
</NSpace>
</NSpace>
</NCollapseItem>
</template>

View File

@@ -0,0 +1,136 @@
<script setup lang="ts">
import { computed } from 'vue';
import { NDivider } from 'naive-ui';
import TemplateEditor from '../TemplateEditor.vue';
import { AutoActionItem, TriggerType, ActionType } from '@/client/store/useAutoAction';
const props = defineProps({
action: {
type: Object as () => AutoActionItem,
required: true
}
});
// 模板变量占位符选项,根据触发类型动态生成
const placeholders = computed(() => {
const commonPlaceholders = [
{ name: '{{user.name}}', description: '用户名称' },
{ name: '{{user.uid}}', description: '用户ID' },
{ name: '{{date.formatted}}', description: '当前日期时间' },
{ name: '{{timeOfDay()}}', description: '当前时段(早上/下午/晚上)' },
];
let specificPlaceholders: { name: string, description: string }[] = [];
switch (props.action.triggerType) {
case TriggerType.GIFT:
specificPlaceholders = [
{ name: '{{gift.name}}', description: '礼物名称' },
{ name: '{{gift.count}}', description: '礼物数量' },
{ name: '{{gift.price}}', description: '礼物单价' },
{ name: '{{gift.totalPrice}}', description: '礼物总价值' },
{ name: '{{gift.summary}}', description: '礼物摘要5个辣条' },
];
break;
case TriggerType.GUARD:
specificPlaceholders = [
{ name: '{{guard.level}}', description: '舰长等级' },
{ name: '{{guard.levelName}}', description: '舰长等级名称' },
{ name: '{{guard.giftCode}}', description: '礼品码(如已配置)' },
];
break;
case TriggerType.SUPER_CHAT:
specificPlaceholders = [
{ name: '{{sc.message}}', description: 'SC消息内容' },
{ name: '{{sc.price}}', description: 'SC价格' },
];
break;
case TriggerType.FOLLOW:
specificPlaceholders = [
{ name: '{{follow.time}}', description: '关注时间' },
{ name: '{{follow.isNew}}', description: '是否新关注' },
];
break;
case TriggerType.ENTER:
specificPlaceholders = [
{ name: '{{enter.time}}', description: '入场时间' },
{ name: '{{enter.guardLevel}}', description: '舰长等级' },
{ name: '{{enter.medalName}}', description: '勋章名称' },
{ name: '{{enter.medalLevel}}', description: '勋章等级' },
];
break;
}
return [...commonPlaceholders, ...specificPlaceholders];
});
// 根据操作类型获取模板标题
const templateTitle = computed(() => {
switch (props.action.actionType) {
case ActionType.SEND_DANMAKU:
return '弹幕模板';
case ActionType.SEND_PRIVATE_MSG:
return '私信模板';
case ActionType.EXECUTE_COMMAND:
return '命令模板';
default:
return '消息模板';
}
});
// 根据操作类型获取模板描述
const templateDescription = computed(() => {
switch (props.action.actionType) {
case ActionType.SEND_DANMAKU:
return '发送到直播间的弹幕内容';
case ActionType.SEND_PRIVATE_MSG:
return '发送给用户的私信内容';
case ActionType.EXECUTE_COMMAND:
return '执行的命令模板';
default:
return '消息内容模板';
}
});
</script>
<template>
<div class="template-settings">
<transition
name="fade-scale"
appear
>
<TemplateEditor
:templates="action.templates"
:placeholders="placeholders"
:title="templateTitle"
:description="templateDescription"
class="template-editor"
/>
</transition>
</div>
</template>
<style scoped>
.template-settings {
position: relative;
}
.settings-divider {
transition: all 0.3s ease;
}
.template-editor {
transition: all 0.3s ease;
}
/* 淡入缩放效果 */
.fade-scale-enter-active,
.fade-scale-leave-active {
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.fade-scale-enter-from,
.fade-scale-leave-to {
opacity: 0;
transform: scale(0.95);
}
</style>