Files
aiclientpureui/src/components/subtitle/TitleSubtitleSettings.vue
949036910@qq.com 16b9a007a6 11111
2026-05-30 18:45:08 +08:00

159 lines
5.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup>
import { computed, ref, watch } from "vue";
import TitleLineStyleEditor from "./TitleLineStyleEditor.vue";
import { syncTitleLinesFromReference } from "../../utils/subtitleTemplateDraft.js";
const config = defineModel("config", { type: Object, required: true });
const props = defineProps({
referenceTitle: { type: String, default: "" },
});
const titleConfig = computed({
get: () => config.value.titleSubtitleConfig,
set: (v) => {
config.value.titleSubtitleConfig = v;
},
});
const enabled = computed({
get: () => titleConfig.value?.enabled !== false,
set: (v) => {
titleConfig.value.enabled = v;
},
});
const openLineIndex = ref(0);
const displayTitle = computed(
() => props.referenceTitle?.trim() || titleConfig.value?.sourceTitle || "(暂无标题,请先在步骤 04 生成)",
);
function reloadFromReference() {
syncTitleLinesFromReference(
{ config: config.value },
props.referenceTitle || titleConfig.value?.sourceTitle,
);
}
const linePreviews = computed(() => titleConfig.value?.lines || []);
const maxCharMarks = [8, 12, 15, 20];
function markLeft(value) {
return `${((value - 8) / (20 - 8)) * 100}%`;
}
watch(
() => titleConfig.value?.maxCharsPerLine,
() => {
reloadFromReference();
},
);
</script>
<template>
<div class="title-subtitle-settings space-y-4 rounded-lg border border-slate-600/40 bg-slate-800/30 p-4">
<div class="flex items-center gap-3">
<Checkbox v-model="enabled" binary />
<span class="font-medium text-slate-100">标题字幕</span>
</div>
<div v-if="enabled" class="space-y-4">
<div>
<div class="mb-2 text-xs text-slate-400">
当前标题自动读取步骤 04标题标签关键词生成结果
</div>
<div class="flex flex-wrap items-center gap-2 rounded bg-slate-900/50 p-3">
<div class="flex-1 text-sm text-slate-200">{{ displayTitle }}</div>
<Button label="重新加载" size="small" severity="secondary" @click="reloadFromReference" />
</div>
</div>
<div class="space-y-4">
<div class="flex items-center gap-3">
<div class="w-28 shrink-0 text-sm text-slate-300">每行最大字符数</div>
<div class="relative flex-1 pb-5">
<Slider
v-model="titleConfig.maxCharsPerLine"
:min="8"
:max="20"
:step="1"
class="w-full"
/>
<div class="pointer-events-none absolute inset-x-0 top-6 text-xs text-slate-500">
<span
v-for="mark in maxCharMarks"
:key="mark"
class="absolute -translate-x-1/2"
:style="{ left: markLeft(mark) }"
>
{{ mark }}
</span>
</div>
</div>
</div>
<div class="flex items-center gap-3">
<div class="w-28 shrink-0 text-sm text-slate-300">行间距%</div>
<InputNumber
v-model="titleConfig.lineSpacingPercent"
:min="3"
:max="15"
class="w-32"
/>
<span class="text-xs text-slate-500">相对于视频高度</span>
</div>
<div class="flex items-center gap-3">
<div class="w-28 shrink-0 text-sm text-slate-300">顶部边距%</div>
<InputNumber
v-model="titleConfig.topMarginPercent"
:min="2"
:max="20"
class="w-32"
/>
<span class="text-xs text-slate-500">相对于视频高度</span>
</div>
</div>
<div v-if="linePreviews.length">
<div class="mb-2 text-xs text-slate-400">分行预览 {{ linePreviews.length }} </div>
<div class="space-y-1">
<div
v-for="(line, i) in linePreviews"
:key="i"
class="rounded bg-slate-900/40 px-2 py-1 text-sm text-slate-300"
>
<span class="text-slate-500">{{ i + 1 }}</span>{{ line.text }}
</div>
</div>
</div>
<div>
<div class="mb-2 text-sm font-medium text-slate-200">每行样式配置</div>
<div class="space-y-2">
<div
v-for="(line, index) in titleConfig.lines"
:key="index"
class="overflow-hidden rounded-lg border border-slate-600/50"
>
<button
type="button"
class="flex w-full items-center justify-between bg-slate-900/50 px-3 py-2 text-left text-sm text-slate-200 hover:bg-slate-900/70"
@click="openLineIndex = openLineIndex === index ? -1 : index"
>
<span>{{ index + 1 }}{{ line.text || "(空)" }}</span>
<i
class="pi text-xs"
:class="openLineIndex === index ? 'pi-chevron-up' : 'pi-chevron-down'"
/>
</button>
<div v-show="openLineIndex === index" class="border-t border-slate-600/40 bg-white p-3">
<TitleLineStyleEditor v-model:line="titleConfig.lines[index]" />
</div>
</div>
</div>
</div>
</div>
</div>
</template>