Skip to content

Commit

Permalink
Feat: custom subtitle
Browse files Browse the repository at this point in the history
  • Loading branch information
LazyCreeper committed Dec 10, 2023
1 parent 216604f commit 7320d4a
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 1 deletion.
1 change: 1 addition & 0 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ declare module 'vue' {
BilibiliParse: typeof import('./src/components/dialogs/bilibiliParse.vue')['default']
CopyButton: typeof import('./src/components/CopyButton.vue')['default']
CustomHeaders: typeof import('./src/components/dialogs/customHeaders.vue')['default']
CustomSubtitles: typeof import('./src/components/dialogs/customSubtitles.vue')['default']
DarkModeSwitcher: typeof import('./src/components/DarkModeSwitcher.vue')['default']
Edit: typeof import('./src/components/icons/Edit.vue')['default']
ElButton: typeof import('element-plus/es')['ElButton']
Expand Down
32 changes: 31 additions & 1 deletion src/components/MoviePush.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import { strLengthLimit } from "@/utils";
import { pushMovieApi } from "@/services/apis/movie";
import { getVendorBackends as biliBiliBackends } from "@/services/apis/vendor";
import customHeaders from "@/components/dialogs/customHeaders.vue";
import customSubtitles from "@/components/dialogs/customSubtitles.vue";
import bilibiliParse from "@/components/dialogs/bilibiliParse.vue";
const Emits = defineEmits(["getMovies"]);
const customHeadersDialog = ref<InstanceType<typeof customHeaders>>();
const customSubtitlesDialog = ref<InstanceType<typeof customSubtitles>>();
const bilibiliParseDialog = ref<InstanceType<typeof bilibiliParse>>();
const Props = defineProps<{
Expand Down Expand Up @@ -218,6 +220,18 @@ const updateHeaders = (header: { [key: string]: string }) => {
newMovieInfo.value.headers = header;
};
const updateSubtitles = (
subtitles: Record<
string,
{
url: string;
type: string;
}
>
) => {
newMovieInfo.value.subtitles = subtitles;
};
const biliParse = () => {
bilibiliParseDialog.value?.openDialog();
};
Expand Down Expand Up @@ -375,6 +389,15 @@ const getBiliBiliVendors = async () => {
<span class="text-sm min-w-fit"> 自定义 header </span>
</div>
</Transition>
<Transition name="fade">
<div
class="more-option-list cursor-pointer"
v-if="!newMovieInfo.live"
@click="customSubtitlesDialog?.openDialog()"
>
<span class="text-sm min-w-fit"> 添加字幕</span>
</div>
</Transition>
</el-collapse-item>
</el-collapse>
</div>
Expand Down Expand Up @@ -403,10 +426,17 @@ const getBiliBiliVendors = async () => {
<!-- 自定义Header对话框 -->
<customHeaders
ref="customHeadersDialog"
:customHeader="newMovieInfo.headers"
:custom-header="newMovieInfo.headers"
@updateHeaders="updateHeaders"
/>

<!-- 自定义字幕列表对话框 -->
<customSubtitles
ref="customSubtitlesDialog"
:custom-subtitles="newMovieInfo.subtitles ?? {}"
@updateSubtitles="updateSubtitles"
/>

<!-- B站视频解析对话框 -->
<bilibiliParse
ref="bilibiliParseDialog"
Expand Down
139 changes: 139 additions & 0 deletions src/components/dialogs/customSubtitles.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { ElNotification } from "element-plus";
import _ from "lodash";
interface SubtitleList {
name: string;
type: string;
url: string;
}
const props = defineProps<{
customSubtitles: Record<
string,
{
url: string;
type: string;
}
>;
}>();
const subtitleList = ref<SubtitleList[]>([]);
const removeItem = (item: SubtitleList) => {
subtitleList.value.splice(subtitleList.value.indexOf(item), 1);
if (subtitleList.value.length === 0) addItem();
};
const addItem = () => {
subtitleList.value.push({
name: "",
type: "",
url: ""
});
};
const isLastItem = (item: SubtitleList) => {
const index = subtitleList.value.indexOf(item);
return index === subtitleList.value.length - 1;
};
const emit = defineEmits(["updateSubtitles"]);
const submit = async () => {
try {
const merged = subtitleList.value.reduce(
(
acc: Record<
string,
{
url: string;
type: string;
}
>,
subtitle: SubtitleList
) => {
acc[subtitle.name] = {
url: subtitle.url,
type: subtitle.type
};
return acc;
},
{}
);
emit("updateSubtitles", merged);
open.value = false;
return ElNotification({
type: "success",
title: "设置成功"
});
} catch (err: any) {
console.error(err.message);
return ElNotification({
type: "error",
title: "错误",
message: err.message
});
}
};
const open = ref(false);
const openDialog = () => {
open.value = true;
};
defineExpose({
openDialog
});
onMounted(() => {});
onMounted(() => {
subtitleList.value = Object.entries(props.customSubtitles).map(([name, subtitle]) => ({
name,
...subtitle
}));
if (subtitleList.value.length === 0) addItem();
});
</script>

<template>
<el-dialog
v-model="open"
title="字幕列表"
class="rounded-lg dark:bg-zinc-800 w-3/7 max-sm:w-full"
>
<div class="grid grid-cols-7 gap-4 mb-2 text-center">
<div class="col-span-2">名称</div>
<div class="col-span-2">URL</div>
<div class="col-span-2">类型</div>
<div>操作</div>
</div>
<div v-for="(item, i) in subtitleList" :key="i" class="grid grid-cols-7 gap-4 mb-2">
<div class="col-span-2">
<input type="text" class="l-input py-1 m-0 px-2 w-full" v-model="item.name" />
</div>
<div class="col-span-2">
<input type="text" class="l-input py-1 m-0 px-2 w-full" v-model="item.url" />
</div>
<div class="col-span-2">
<input
type="text"
class="l-input py-1 m-0 px-2 w-full"
v-model="item.type"
placeholder="仅支持 vtt, srt, ass"
/>
</div>
<div class="text-center">
<button v-if="isLastItem(item)" class="btn btn-dense mr-2" @click="addItem()">添加</button>

<button class="btn btn-dense btn-error" @click="removeItem(item)">移除</button>
</div>
</div>

<template #footer>
<button class="btn mr-4" @click="open = false">取消</button>
<button class="btn btn-success" @click="submit()">保存</button>
</template>
</el-dialog>
</template>

0 comments on commit 7320d4a

Please sign in to comment.