mirror of
https://github.com/lanyeeee/bilibili-video-downloader.git
synced 2026-09-06 08:07:26 +08:00
feat: 配置Dialog
This commit is contained in:
+18
-6
@@ -2,11 +2,11 @@
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useStore } from './store.ts'
|
||||
import LogDialog from './dialogs/LogDialog.vue'
|
||||
import { PhClockCounterClockwise, PhInfo } from '@phosphor-icons/vue'
|
||||
import { commands } from './bindings.ts'
|
||||
import { PhClockCounterClockwise, PhInfo, PhGearSix } from '@phosphor-icons/vue'
|
||||
import AboutDialog from './dialogs/AboutDialog.vue'
|
||||
import { platform } from '@tauri-apps/plugin-os'
|
||||
import TitleBar from './components/TitleBar.vue'
|
||||
import SettingsDialog from './dialogs/SettingsDialog/SettingsDialog.vue'
|
||||
|
||||
const currentPlatform = platform()
|
||||
|
||||
@@ -14,28 +14,39 @@ const store = useStore()
|
||||
|
||||
const logDialogShowing = ref<boolean>(false)
|
||||
const aboutDialogShowing = ref<boolean>(false)
|
||||
const settingsDialogShowing = ref<boolean>(false)
|
||||
|
||||
onMounted(async () => {
|
||||
onMounted(() => {
|
||||
// 屏蔽浏览器右键菜单
|
||||
document.oncontextmenu = (event) => {
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
store.config = await commands.getConfig()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
:class="[
|
||||
:class="[
|
||||
'h-screen flex flex-col',
|
||||
{
|
||||
'box-border border border-solid border-gray-3': currentPlatform === 'linux',
|
||||
},
|
||||
]">
|
||||
<TitleBar />
|
||||
|
||||
<div v-if="store.config !== undefined" class="h-full w-full flex overflow-hidden select-none">
|
||||
<div class="flex flex-col box-border p-1 border-r-solid border-r-1 border-r-[#DADADA] bg-[#F9F9F9] flex-shrink-0">
|
||||
<n-tooltip placement="right" trigger="hover" :show-arrow="false">
|
||||
配置
|
||||
<template #trigger>
|
||||
<n-button text class="mt-auto py-1 px-2" @click="settingsDialogShowing = true">
|
||||
<n-icon size="28">
|
||||
<PhGearSix />
|
||||
</n-icon>
|
||||
</n-button>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
|
||||
<n-tooltip placement="right" trigger="hover" :show-arrow="false">
|
||||
日志
|
||||
<template #trigger>
|
||||
@@ -60,6 +71,7 @@ onMounted(async () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SettingsDialog v-model:showing="settingsDialogShowing" />
|
||||
<LogDialog v-model:showing="logDialogShowing" />
|
||||
<AboutDialog v-model:showing="aboutDialogShowing" />
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, watch } from 'vue'
|
||||
import { commands } from '../../bindings.ts'
|
||||
import { path } from '@tauri-apps/api'
|
||||
import { appDataDir } from '@tauri-apps/api/path'
|
||||
import { useStore } from '../../store.ts'
|
||||
import DownloadSettings from './components/DownloadSettings.vue'
|
||||
import ProxySettings from './components/ProxySettings.vue'
|
||||
import FmtSettings from './components/FmtSettings.vue'
|
||||
import DownloadSpeedSettings from './components/DownloadSpeedSettings.vue'
|
||||
import AssDanmakuSettings from './components/AssDanmakuSettings.vue'
|
||||
import { useMessage } from 'naive-ui'
|
||||
|
||||
const store = useStore()
|
||||
|
||||
const message = useMessage()
|
||||
|
||||
const showing = defineModel<boolean>('showing', { required: true })
|
||||
|
||||
onMounted(async () => {
|
||||
store.config = await commands.getConfig()
|
||||
})
|
||||
|
||||
watch(
|
||||
() => store.config,
|
||||
async () => {
|
||||
if (store.config === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
const result = await commands.saveConfig(store.config)
|
||||
if (result.status === 'error') {
|
||||
console.error(result.error)
|
||||
return
|
||||
}
|
||||
message.success('保存配置成功')
|
||||
},
|
||||
{ deep: true },
|
||||
)
|
||||
|
||||
const currentTabName = ref<string>('download_settings')
|
||||
|
||||
async function showConfigInFileManager() {
|
||||
const configName = 'config.json'
|
||||
const configPath = await path.join(await appDataDir(), configName)
|
||||
const result = await commands.showPathInFileManager(configPath)
|
||||
if (result.status === 'error') {
|
||||
console.error(result.error)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-modal v-if="store.config !== undefined" v-model:show="showing">
|
||||
<n-dialog :showIcon="false" title="配置" content-style="" @close="showing = false">
|
||||
<div class="flex flex-col gap-row-2">
|
||||
<n-tabs class="h-full" v-model:value="currentTabName" type="line" size="small" animated>
|
||||
<n-tab-pane name="download_settings" tab="下载内容">
|
||||
<DownloadSettings />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="fmt_settings" tab="命名格式">
|
||||
<FmtSettings />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="ass_danmaku_settings" tab="ass弹幕">
|
||||
<AssDanmakuSettings />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="download_speed_settings" tab="下载速度">
|
||||
<DownloadSpeedSettings />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="proxy_settings" tab="代理">
|
||||
<ProxySettings />
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
|
||||
<n-button class="ml-auto mt-2" size="small" @click="showConfigInFileManager">打开配置目录</n-button>
|
||||
</div>
|
||||
</n-dialog>
|
||||
</n-modal>
|
||||
</template>
|
||||
@@ -0,0 +1,204 @@
|
||||
<script setup lang="ts">
|
||||
import { useStore } from '../../../store.ts'
|
||||
|
||||
const store = useStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="store.config !== undefined" class="flex flex-col gap-row-2">
|
||||
<n-tooltip placement="left" trigger="hover">
|
||||
弹幕使用的字体名称
|
||||
<template #trigger>
|
||||
<n-input-group class="box-border">
|
||||
<n-input-group-label size="small">字体</n-input-group-label>
|
||||
<n-input class="w-full" v-model:value="store.config.danmaku_config.font" size="small" />
|
||||
</n-input-group>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
|
||||
<div class="flex items-center gap-2 whitespace-nowrap">
|
||||
<n-tooltip placement="left" trigger="hover">
|
||||
弹幕字体大小
|
||||
<template #trigger>
|
||||
<n-input-group class="box-border">
|
||||
<n-input-group-label size="small">字体大小</n-input-group-label>
|
||||
<n-input-number
|
||||
class="w-full"
|
||||
v-model:value="store.config.danmaku_config.font_size"
|
||||
size="small"
|
||||
:min="0"
|
||||
:parse="(x: string) => Number(x)"
|
||||
:show-button="false" />
|
||||
</n-input-group>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
|
||||
<n-checkbox v-model:checked="store.config.danmaku_config.bold">加粗</n-checkbox>
|
||||
</div>
|
||||
|
||||
<n-tooltip placement="left" trigger="hover" class="w-20vw">
|
||||
弹幕的描边宽度,单位为像素
|
||||
<template #trigger>
|
||||
<n-input-group class="box-border">
|
||||
<n-input-group-label size="small">描边宽度</n-input-group-label>
|
||||
<n-input-number
|
||||
class="w-full"
|
||||
v-model:value="store.config.danmaku_config.outline"
|
||||
size="small"
|
||||
:min="0"
|
||||
:parse="(x: string) => Number(x)"
|
||||
:show-button="false" />
|
||||
</n-input-group>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
|
||||
<n-tooltip placement="left" trigger="hover" class="w-20vw">
|
||||
弹幕的不透明度,越小越透明,越大越不透明
|
||||
<template #trigger>
|
||||
<n-input-group class="box-border">
|
||||
<n-input-group-label size="small">不透明度</n-input-group-label>
|
||||
<n-input-number
|
||||
class="w-full"
|
||||
v-model:value="store.config.danmaku_config.alpha"
|
||||
size="small"
|
||||
:min="0"
|
||||
:max="1"
|
||||
:parse="(x: string) => Number(x)"
|
||||
:show-button="false" />
|
||||
</n-input-group>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
|
||||
<n-tooltip placement="left" trigger="hover" class="w-20vw">
|
||||
弹幕在屏幕上的【持续时间】,单位为秒,可以有小数
|
||||
<template #trigger>
|
||||
<n-input-group class="box-border">
|
||||
<n-input-group-label size="small">在屏幕上的持续时间</n-input-group-label>
|
||||
<n-input-number
|
||||
class="w-full"
|
||||
v-model:value="store.config.danmaku_config.duration"
|
||||
size="small"
|
||||
:min="0"
|
||||
:parse="(x: string) => Number(x)"
|
||||
:show-button="false" />
|
||||
</n-input-group>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
|
||||
<n-tooltip placement="left" trigger="hover" class="w-20vw">
|
||||
【正常弹幕的屏幕填充占比】,默认为 0.5,即半个屏幕
|
||||
<template #trigger>
|
||||
<n-input-group class="box-border">
|
||||
<n-input-group-label size="small">显示区域</n-input-group-label>
|
||||
<n-input-number
|
||||
class="w-full"
|
||||
v-model:value="store.config.danmaku_config.float_percentage"
|
||||
size="small"
|
||||
:min="0"
|
||||
:max="1"
|
||||
:parse="(x: string) => Number(x)"
|
||||
:show-button="false" />
|
||||
</n-input-group>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
|
||||
<n-tooltip placement="left" trigger="hover" class="w-20vw">
|
||||
<div>是一个比例数,用来计算平衡不同字体的宽度</div>
|
||||
<div>有的字体比较粗、比较宽,可以适当调大(如 1.4、1.6)</div>
|
||||
<div>有的字体比较细、比较窄,可以适当调小(如 1.0、1.2)</div>
|
||||
<template #trigger>
|
||||
<n-input-group class="box-border">
|
||||
<n-input-group-label size="small">宽度乘子</n-input-group-label>
|
||||
<n-input-number
|
||||
class="w-full"
|
||||
v-model:value="store.config.danmaku_config.width_ratio"
|
||||
size="small"
|
||||
:min="0"
|
||||
:parse="(x: string) => Number(x)"
|
||||
:show-button="false" />
|
||||
</n-input-group>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
|
||||
<n-tooltip placement="left" trigger="hover" class="w-20vw">
|
||||
用来调整弹幕时间的水平距离,单位是像素,如果想拉开弹幕之间的距离,可以调大
|
||||
<template #trigger>
|
||||
<n-input-group class="box-border">
|
||||
<n-input-group-label size="small">最小水平间距</n-input-group-label>
|
||||
<n-input-number
|
||||
class="w-full"
|
||||
v-model:value="store.config.danmaku_config.horizontal_gap"
|
||||
size="small"
|
||||
:min="0"
|
||||
:parse="(x: string) => Number(x)"
|
||||
:show-button="false" />
|
||||
</n-input-group>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
|
||||
<n-tooltip placement="left" trigger="hover" class="w-20vw">
|
||||
计算弹幕高度的数值,即【行高度/行间距】。数值越大,弹幕的垂直距离越大
|
||||
<template #trigger>
|
||||
<n-input-group class="box-border">
|
||||
<n-input-group-label size="small">行高</n-input-group-label>
|
||||
<n-input-number
|
||||
class="w-full"
|
||||
v-model:value="store.config.danmaku_config.lane_size"
|
||||
size="small"
|
||||
:min="0"
|
||||
:parse="(x: string) => Number(x)"
|
||||
:show-button="false" />
|
||||
</n-input-group>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
|
||||
<n-tooltip placement="left" trigger="hover" class="w-20vw">
|
||||
弹幕时间轴偏移,大于0 会让弹幕延后,小于0 会让弹幕提前,单位为秒
|
||||
<template #trigger>
|
||||
<n-input-group class="box-border">
|
||||
<n-input-group-label size="small">延后</n-input-group-label>
|
||||
<n-input-number
|
||||
class="w-full"
|
||||
v-model:value="store.config.danmaku_config.time_offset"
|
||||
size="small"
|
||||
:parse="(x: string) => Number(x)"
|
||||
:show-button="false" />
|
||||
</n-input-group>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
|
||||
<n-tooltip placement="left" trigger="hover" class="w-20vw">
|
||||
渲染的屏幕分辨率,这个并不会影响渲染区域的大小,只影响字体的相对大小,
|
||||
<span class="text-blue">没有特殊原因不用改</span>
|
||||
<template #trigger>
|
||||
<n-input-group class="box-border">
|
||||
<n-input-group-label size="small">屏幕宽度</n-input-group-label>
|
||||
<n-input-number
|
||||
class="w-full"
|
||||
v-model:value="store.config.danmaku_config.width"
|
||||
size="small"
|
||||
:min="0"
|
||||
:parse="(x: string) => Number(x)"
|
||||
:show-button="false" />
|
||||
</n-input-group>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
|
||||
<n-tooltip placement="left" trigger="hover" class="w-20vw">
|
||||
渲染的屏幕分辨率,这个并不会影响渲染区域的大小,只影响字体的相对大小,
|
||||
<span class="text-blue">没有特殊原因不用改</span>
|
||||
<template #trigger>
|
||||
<n-input-group class="box-border">
|
||||
<n-input-group-label size="small">屏幕高度</n-input-group-label>
|
||||
<n-input-number
|
||||
class="w-full"
|
||||
v-model:value="store.config.danmaku_config.height"
|
||||
size="small"
|
||||
:min="0"
|
||||
:parse="(x: string) => Number(x)"
|
||||
:show-button="false" />
|
||||
</n-input-group>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,112 @@
|
||||
<script setup lang="ts">
|
||||
import { SelectBaseOption } from 'naive-ui/es/select/src/interface'
|
||||
import { PreferAudioQuality, PreferVideoQuality } from '../../../bindings.ts'
|
||||
import { useStore } from '../../../store.ts'
|
||||
|
||||
const store = useStore()
|
||||
|
||||
const videoQualitySelectOptions: SelectBaseOption<PreferVideoQuality>[] = [
|
||||
{ label: '最高', value: 'Best' },
|
||||
{ label: '240P', value: '240P' },
|
||||
{ label: '360P', value: '360P' },
|
||||
{ label: '480P', value: '480P' },
|
||||
{ label: '720P', value: '720P' },
|
||||
{ label: '720P 60帧', value: '720P60' },
|
||||
{ label: '1080P', value: '1080P' },
|
||||
{ label: '智能修复', value: 'AiRepair' },
|
||||
{ label: '1080P 高码率', value: '1080P+' },
|
||||
{ label: '1080P 60帧', value: '1080P60' },
|
||||
{ label: '4K', value: '4K' },
|
||||
{ label: 'HDR', value: 'HDR' },
|
||||
{ label: '杜比视界', value: 'Dolby' },
|
||||
{ label: '8K', value: '8K' },
|
||||
]
|
||||
const audioQualitySelectOptions: SelectBaseOption<PreferAudioQuality>[] = [
|
||||
{ label: '最高', value: 'Best' },
|
||||
{ label: '64K', value: '64K' },
|
||||
{ label: '132K', value: '132K' },
|
||||
{ label: '192K', value: '192K' },
|
||||
{ label: '杜比全景声', value: 'Dolby' },
|
||||
{ label: 'Hi-Res', value: 'HiRes' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="store.config !== undefined" class="flex flex-col gap-row-2">
|
||||
<div class="flex gap-2">
|
||||
<span class="font-bold">主要内容</span>
|
||||
<n-checkbox v-model:checked="store.config.download_video">下载视频</n-checkbox>
|
||||
<n-checkbox v-model:checked="store.config.download_audio">下载音频</n-checkbox>
|
||||
<n-tooltip placement="top" trigger="hover">
|
||||
<div>自动合并音频和视频</div>
|
||||
<template #trigger>
|
||||
<n-checkbox v-model:checked="store.config.auto_merge">自动合并</n-checkbox>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2">
|
||||
<span class="font-bold">附加内容</span>
|
||||
<n-checkbox v-model:checked="store.config.download_subtitle">下载字幕</n-checkbox>
|
||||
<n-checkbox v-model:checked="store.config.download_cover">下载封面</n-checkbox>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2">
|
||||
<span class="font-bold">下载弹幕</span>
|
||||
<n-checkbox class="w-22" v-model:checked="store.config.download_xml_danmaku">xml弹幕</n-checkbox>
|
||||
<n-checkbox class="w-22" v-model:checked="store.config.download_ass_danmaku">ass弹幕</n-checkbox>
|
||||
<n-checkbox class="w-22" v-model:checked="store.config.download_json_danmaku">json弹幕</n-checkbox>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2">
|
||||
<span class="w-14 font-bold">元数据</span>
|
||||
<n-tooltip placement="top" trigger="hover">
|
||||
<div>还会顺便下载poster和fanart(如果有的话)</div>
|
||||
<template #trigger>
|
||||
<n-checkbox class="w-22" v-model:checked="store.config.download_nfo">nfo文件</n-checkbox>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
<n-checkbox class="w-22" v-model:checked="store.config.download_json">json文件</n-checkbox>
|
||||
</div>
|
||||
|
||||
<n-tooltip placement="left" trigger="hover" class="w-20vw">
|
||||
<div>如果视频有对应的画质,则使用对应的画质,否则选择最高画质</div>
|
||||
<template #trigger>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-2 whitespace-nowrap font-bold">优先画质</span>
|
||||
<n-select
|
||||
size="small"
|
||||
v-model:value="store.config.prefer_video_quality"
|
||||
:options="videoQualitySelectOptions" />
|
||||
</div>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
|
||||
<n-tooltip placement="left" trigger="hover" class="w-20vw">
|
||||
<div>如果视频有对应的音质,则使用对应的音质,否则选择最高音质</div>
|
||||
<template #trigger>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-2 whitespace-nowrap font-bold">优先音质</span>
|
||||
<n-select
|
||||
size="small"
|
||||
v-model:value="store.config.prefer_audio_quality"
|
||||
:options="audioQualitySelectOptions" />
|
||||
</div>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
|
||||
<n-tooltip placement="left" trigger="hover" class="w-20vw">
|
||||
<div>如果视频有对应的编码,则使用对应的编码,否则按照 AVC > HEVC > AV1 的顺序选择编码</div>
|
||||
<template #trigger>
|
||||
<div>
|
||||
<span class="mr-2 font-bold">优先编码</span>
|
||||
<n-radio-group v-model:value="store.config.prefer_codec_type" size="small">
|
||||
<n-radio-button value="AVC">AVC</n-radio-button>
|
||||
<n-radio-button value="HEVC">HEVC</n-radio-button>
|
||||
<n-radio-button value="AV1">AV1</n-radio-button>
|
||||
</n-radio-group>
|
||||
</div>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,77 @@
|
||||
<script setup lang="ts">
|
||||
import { useStore } from '../../../store.ts'
|
||||
import { useMessage } from 'naive-ui'
|
||||
|
||||
const message = useMessage()
|
||||
const store = useStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="store.config !== undefined" class="flex flex-col gap-row-2">
|
||||
<div class="flex gap-1">
|
||||
<n-tooltip placement="top" trigger="hover">
|
||||
<div>最多有多少个任务同时下载</div>
|
||||
<template #trigger>
|
||||
<n-input-group class="w-40%">
|
||||
<n-input-group-label size="small">任务并发</n-input-group-label>
|
||||
<n-input-number
|
||||
class="w-full"
|
||||
v-model:value="store.config.task_concurrency"
|
||||
size="small"
|
||||
@update:value="message.warning('对任务并发的修改需要重启才能生效')"
|
||||
:min="1"
|
||||
:parse="(x: string) => Number(x)" />
|
||||
</n-input-group>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
<n-tooltip placement="top" trigger="hover">
|
||||
<div>每个任务下载完成后休息多久</div>
|
||||
<template #trigger>
|
||||
<n-input-group class="w-60%">
|
||||
<n-input-group-label size="small">任务下载间隔</n-input-group-label>
|
||||
<n-input-number
|
||||
class="w-full"
|
||||
v-model:value="store.config.task_download_interval_sec"
|
||||
size="small"
|
||||
:min="0"
|
||||
:parse="(x: string) => Number(x)" />
|
||||
<n-input-group-label size="small">秒</n-input-group-label>
|
||||
</n-input-group>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-1">
|
||||
<n-tooltip placement="top" trigger="hover">
|
||||
<div>最多有多少个分片同时下载</div>
|
||||
<template #trigger>
|
||||
<n-input-group class="w-40%">
|
||||
<n-input-group-label size="small">分片并发</n-input-group-label>
|
||||
<n-input-number
|
||||
class="w-full"
|
||||
v-model:value="store.config.chunk_concurrency"
|
||||
size="small"
|
||||
@update-value="message.warning('对分片并发的修改需要重启才能生效')"
|
||||
:min="1"
|
||||
:parse="(x: string) => Number(x)" />
|
||||
</n-input-group>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
<n-tooltip placement="top" trigger="hover">
|
||||
<div>每个分片下载完成后休息多久</div>
|
||||
<template #trigger>
|
||||
<n-input-group class="w-60%">
|
||||
<n-input-group-label size="small">分片下载间隔</n-input-group-label>
|
||||
<n-input-number
|
||||
class="w-full"
|
||||
v-model:value="store.config.chunk_download_interval_sec"
|
||||
size="small"
|
||||
:min="0"
|
||||
:parse="(x: string) => Number(x)" />
|
||||
<n-input-group-label size="small">秒</n-input-group-label>
|
||||
</n-input-group>
|
||||
</template>
|
||||
</n-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,177 @@
|
||||
<script setup lang="tsx">
|
||||
import { ref } from 'vue'
|
||||
import { useStore } from '../../../store.ts'
|
||||
|
||||
const store = useStore()
|
||||
|
||||
const dirFmt = ref<string>(store.config?.dir_fmt ?? '')
|
||||
const dirFmtForPart = ref<string>(store.config?.dir_fmt_for_part ?? '')
|
||||
const timeFmt = ref<string>(store.config?.time_fmt ?? '')
|
||||
|
||||
function AvailableFmtFields() {
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
可以用斜杠
|
||||
<span class="rounded bg-gray-500 px-1 select-all text-white">/</span>
|
||||
来分隔目录层级
|
||||
</div>
|
||||
<div class="text-blue">注意:最后一个层级是下载内容的文件名</div>
|
||||
<div class="font-semibold mt-2">
|
||||
<span>可用字段:</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="rounded bg-gray-500 px-1 select-all">task_id</span>
|
||||
<span class="ml-2">下载任务ID</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="rounded bg-gray-500 px-1 select-all">episode_type</span>
|
||||
<span class="ml-2">视频类型(Normal / Bangumi / Cheese)</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="rounded bg-gray-500 px-1 select-all">aid</span>
|
||||
<span class="ml-2">av号</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="rounded bg-gray-500 px-1 select-all">bvid</span>
|
||||
<span class="ml-2">bv号</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="rounded bg-gray-500 px-1 select-all">cid</span>
|
||||
<span class="ml-2">cid</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="rounded bg-gray-500 px-1 select-all">ep_id</span>
|
||||
<span class="ml-2">番剧/课程的章节号</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="rounded bg-gray-500 px-1 select-all">duration</span>
|
||||
<span class="ml-2">视频时长,单位为秒</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="rounded bg-gray-500 px-1 select-all">pub_ts</span>
|
||||
<span class="ml-2">视频发布的时间</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="rounded bg-gray-500 px-1 select-all">collection_title</span>
|
||||
<span class="ml-2">
|
||||
合集名称,
|
||||
<span class="text-blue">对于单独(没有合集)的视频,合集名称就是视频名称</span>
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="rounded bg-gray-500 px-1 select-all">episode_title</span>
|
||||
<span class="ml-2">视频名称</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="rounded bg-gray-500 px-1 select-all">episode_order</span>
|
||||
<span class="ml-2">在合集里的序号(从1起)</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="rounded bg-gray-500 px-1 select-all">part_title</span>
|
||||
<span class="ml-2">分P名称</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="rounded bg-gray-500 px-1 select-all">part_order</span>
|
||||
<span class="ml-2">分P序号</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="rounded bg-gray-500 px-1 select-all">up_name</span>
|
||||
<span class="ml-2">up昵称</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="rounded bg-gray-500 px-1 select-all">up_uid</span>
|
||||
<span class="ml-2">up的uid</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="rounded bg-gray-500 px-1 select-all">create_ts</span>
|
||||
<span class="ml-2">下载任务创建的时间</span>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="store.config !== undefined" class="flex flex-col">
|
||||
<n-config-provider
|
||||
:theme-overrides="{ Scrollbar: { color: 'rgba(255, 255, 255, 0.25)', colorHover: 'rgba(255, 255, 255, 0.3)' } }">
|
||||
<div class="font-bold">目录格式</div>
|
||||
<n-tooltip placement="top" trigger="hover" class="w-68vw max-h-35vh" :scrollable="true">
|
||||
<div>目录的命名格式,只作用于没分P的视频</div>
|
||||
<available-fmt-fields />
|
||||
<div class="font-semibold mt-2">例如格式</div>
|
||||
<div class="bg-gray-200 rounded-md p-1 text-black w-fit">{collection_title}/{episode_title}</div>
|
||||
<div class="font-semibold">
|
||||
<span>下载</span>
|
||||
<span class="text-blue mx-0.5">BV1eg411A7qd</span>
|
||||
<span>会产生一个文件夹</span>
|
||||
</div>
|
||||
<div class="bg-gray-200 rounded-md px-1 w-fit text-black">galgame纯音乐</div>
|
||||
<div class="font-semibold">文件夹内下载内容的文件名为</div>
|
||||
<div class="bg-gray-200 rounded-md px-1 w-fit text-black">【galgame纯音乐】 夜の向日葵</div>
|
||||
<template #trigger>
|
||||
<n-input
|
||||
v-model:value="dirFmt"
|
||||
size="small"
|
||||
@blur="store.config.dir_fmt = dirFmt"
|
||||
@keydown.enter="store.config.dir_fmt = dirFmt" />
|
||||
</template>
|
||||
</n-tooltip>
|
||||
|
||||
<div class="mt-2 font-bold">目录格式(分P)</div>
|
||||
<n-tooltip placement="top" trigger="hover" class="w-68vw max-h-45vh" :scrollable="true">
|
||||
<div>有分P的视频用这个格式,而不是上面那个</div>
|
||||
<available-fmt-fields />
|
||||
<div class="font-semibold mt-2">例如格式</div>
|
||||
<div class="bg-gray-200 rounded-md p-1 text-black w-fit">
|
||||
{collection_title}/{episode_title}/{episode_title}-P{part_order} {part_title}
|
||||
</div>
|
||||
<div class="font-semibold">
|
||||
<span>下载</span>
|
||||
<span class="text-blue mx-0.5">BV1NMaXecEsv</span>
|
||||
<span>的</span>
|
||||
<span class="text-blue mx-0.5">P30</span>
|
||||
<span>会创建</span>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1 text-black">
|
||||
<div class="bg-gray-200 rounded-md px-1 w-fit">动画、游戏专辑</div>
|
||||
<div class="bg-gray-200 rounded-md px-1 w-fit">【高音质】樱之诗OST</div>
|
||||
</div>
|
||||
<div class="font-semibold">两层文件夹,里面的下载内容的文件名为</div>
|
||||
<div class="bg-gray-200 rounded-md px-1 w-fit text-black">【高音质】樱之诗OST-P30 30.夢の歩みを見上げて</div>
|
||||
<template #trigger>
|
||||
<n-input
|
||||
v-model:value="dirFmtForPart"
|
||||
size="small"
|
||||
@blur="store.config.dir_fmt_for_part = dirFmtForPart"
|
||||
@keydown.enter="store.config.dir_fmt_for_part = dirFmtForPart" />
|
||||
</template>
|
||||
</n-tooltip>
|
||||
|
||||
<div class="mt-2 font-bold">时间格式</div>
|
||||
<n-tooltip placement="top" trigger="hover">
|
||||
<div>
|
||||
影响字段
|
||||
<span class="rounded bg-gray-500 px-1 select-all">pub_ts</span>
|
||||
和
|
||||
<span class="rounded bg-gray-500 px-1 select-all">created_ts</span>
|
||||
的格式
|
||||
</div>
|
||||
<div>
|
||||
详细用法请看
|
||||
<n-a href="https://docs.rs/chrono/latest/chrono/format/strftime/index.html" target="_blank">
|
||||
https://docs.rs/chrono/latest/chrono/format/strftime/index.html
|
||||
</n-a>
|
||||
</div>
|
||||
<template #trigger>
|
||||
<n-input
|
||||
v-model:value="timeFmt"
|
||||
size="small"
|
||||
@blur="store.config.time_fmt = timeFmt"
|
||||
@keydown.enter="store.config.time_fmt = timeFmt" />
|
||||
</template>
|
||||
</n-tooltip>
|
||||
</n-config-provider>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,38 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { useStore } from '../../../store.ts'
|
||||
|
||||
const store = useStore()
|
||||
|
||||
const proxyHost = ref<string>(store.config?.proxy_host ?? '')
|
||||
|
||||
const disableProxyHostAndPort = computed(() => store.config?.proxy_mode !== 'Custom')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="store.config !== undefined" class="flex flex-col gap-row-2">
|
||||
<n-radio-group v-model:value="store.config.proxy_mode" size="small">
|
||||
<n-radio-button value="NoProxy">直连</n-radio-button>
|
||||
<n-radio-button value="System">系统代理</n-radio-button>
|
||||
<n-radio-button value="Custom">自定义</n-radio-button>
|
||||
</n-radio-group>
|
||||
|
||||
<n-input-group>
|
||||
<n-input-group-label size="small">http://</n-input-group-label>
|
||||
<n-input
|
||||
:disabled="disableProxyHostAndPort"
|
||||
v-model:value="proxyHost"
|
||||
size="small"
|
||||
placeholder=""
|
||||
@blur="store.config.proxy_host = proxyHost"
|
||||
@keydown.enter="store.config.proxy_host = proxyHost" />
|
||||
<n-input-group-label size="small">:</n-input-group-label>
|
||||
<n-input-number
|
||||
:disabled="disableProxyHostAndPort"
|
||||
v-model:value="store.config.proxy_port"
|
||||
size="small"
|
||||
placeholder=""
|
||||
:parse="(x: string) => parseInt(x)" />
|
||||
</n-input-group>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user