优化配置向导

This commit is contained in:
jxxghp
2025-09-10 16:56:06 +08:00
parent c8a65ecbe4
commit 4a2073a038
8 changed files with 69 additions and 69 deletions

View File

@@ -10,7 +10,6 @@ const props = defineProps({
root: {
type: String,
default: '/',
required: true,
},
storage: {
type: String,

View File

@@ -232,12 +232,13 @@ export function useSetupWizard() {
if (wizardData.value.downloader.type === type) {
// 重复点击已选中的类型,取消选择
wizardData.value.downloader.type = ''
wizardData.value.downloader.name = ''
wizardData.value.downloader.config = {}
} else {
wizardData.value.downloader.type = type
wizardData.value.downloader.name = `${type} 下载器`
wizardData.value.downloader.config = {}
// 如果名称为空或为默认名称,则设置默认名称
if (!wizardData.value.downloader.name || wizardData.value.downloader.name.includes('下载器')) {
wizardData.value.downloader.name = `${type} 下载器`
}
// 不清空config保留用户已输入的值
}
}
@@ -246,14 +247,13 @@ export function useSetupWizard() {
if (wizardData.value.mediaServer.type === type) {
// 重复点击已选中的类型,取消选择
wizardData.value.mediaServer.type = ''
wizardData.value.mediaServer.name = ''
wizardData.value.mediaServer.config = {}
wizardData.value.mediaServer.sync_libraries = []
} else {
wizardData.value.mediaServer.type = type
wizardData.value.mediaServer.name = `${type} 服务器`
wizardData.value.mediaServer.config = {}
wizardData.value.mediaServer.sync_libraries = []
// 如果名称为空或为默认名称,则设置默认名称
if (!wizardData.value.mediaServer.name || wizardData.value.mediaServer.name.includes('服务器')) {
wizardData.value.mediaServer.name = `${type} 服务器`
}
// 不清空config和sync_libraries保留用户已输入的值
}
}
@@ -262,16 +262,14 @@ export function useSetupWizard() {
if (wizardData.value.notification.type === type) {
// 重复点击已选中的类型,取消选择
wizardData.value.notification.type = ''
wizardData.value.notification.name = ''
wizardData.value.notification.enabled = false
wizardData.value.notification.config = {}
wizardData.value.notification.switchs = []
} else {
wizardData.value.notification.type = type
wizardData.value.notification.name = `${type} 通知`
// 如果名称为空或为默认名称,则设置默认名称
if (!wizardData.value.notification.name || wizardData.value.notification.name.includes('通知')) {
wizardData.value.notification.name = `${type} 通知`
}
wizardData.value.notification.enabled = true
wizardData.value.notification.config = {}
wizardData.value.notification.switchs = []
// 不清空config和switchs保留用户已输入的值
}
}
@@ -924,6 +922,7 @@ export function useSetupWizard() {
const directory = {
name: '默认目录',
storage: 'local',
library_storage: 'local',
download_path: wizardData.value.storage.downloadPath,
library_path: wizardData.value.storage.libraryPath,
priority: 0,
@@ -955,12 +954,15 @@ export function useSetupWizard() {
async function saveDownloaderSettings() {
if (wizardData.value.downloader.type) {
try {
// 只保存当前选中类型的配置
const config = { ...wizardData.value.downloader.config }
const downloader = {
name: wizardData.value.downloader.name,
type: wizardData.value.downloader.type,
default: true,
enabled: true,
config: wizardData.value.downloader.config,
config: config,
}
const response: { [key: string]: any } = await api.post('system/setting/Downloaders', [downloader])
@@ -981,11 +983,16 @@ export function useSetupWizard() {
async function saveMediaServerSettings() {
if (wizardData.value.mediaServer.type) {
try {
// 只保存当前选中类型的配置
const config = { ...wizardData.value.mediaServer.config }
const sync_libraries = [...(wizardData.value.mediaServer.sync_libraries || [])]
const mediaServer = {
name: wizardData.value.mediaServer.name,
type: wizardData.value.mediaServer.type,
enabled: true,
config: wizardData.value.mediaServer.config,
config: config,
sync_libraries: sync_libraries,
}
const response: { [key: string]: any } = await api.post('system/setting/MediaServers', [mediaServer])
@@ -1006,11 +1013,16 @@ export function useSetupWizard() {
async function saveNotificationSettings() {
if (wizardData.value.notification.type) {
try {
// 只保存当前选中类型的配置
const config = { ...wizardData.value.notification.config }
const switchs = [...(wizardData.value.notification.switchs || [])]
const notification = {
name: wizardData.value.notification.name,
type: wizardData.value.notification.type,
enabled: true,
config: wizardData.value.notification.config,
enabled: wizardData.value.notification.enabled,
config: config,
switchs: switchs,
}
const response: { [key: string]: any } = await api.post('system/setting/Notifications', [notification])

View File

@@ -526,7 +526,7 @@ onUnmounted(() => {
<template #prepend>
<VIcon :icon="isAdvancedMode ? 'mdi-cog-outline' : 'mdi-wizard-hat'" />
</template>
<VListItemTitle>{{ t('user.systemSettings') }}</VListItemTitle>
<VListItemTitle>{{ isAdvancedMode ? t('user.systemSettings') : t('user.wizardSettings') }}</VListItemTitle>
</VListItem>
<!-- 👉 Site Auth -->

View File

@@ -372,6 +372,7 @@ export default {
deleteFailed: 'Failed to delete user!',
profile: 'Profile',
systemSettings: 'System Settings',
wizardSettings: 'Setup Wizard',
siteAuth: 'User Authentication',
helpDocs: 'Help Documents',
restart: 'Restart',
@@ -2948,7 +2949,7 @@ export default {
apiTokenRequired: 'API Token is required',
},
storage: {
title: 'Storage Configuration',
title: 'Storage',
description: 'Configure download directory and media library directory',
info: 'Storage Configuration',
infoDesc: 'Configure local storage directories for download and media library management',
@@ -2960,7 +2961,7 @@ export default {
libraryPathRequired: 'Media library directory is required',
},
downloader: {
title: 'Downloader Configuration',
title: 'Downloader',
description: 'Configure downloader',
info: 'Downloader Configuration',
infoDesc: 'Configure downloader for resource download, can choose qBittorrent or Transmission',
@@ -2992,7 +2993,7 @@ export default {
token: 'Access Token',
},
notification: {
title: 'Notification Settings',
title: 'Notification',
description: 'Configure notification channels',
info: 'Notification Configuration',
infoDesc: 'Configure notification channels for receiving system messages (optional)',

View File

@@ -370,6 +370,7 @@ export default {
deleteFailed: '用户删除失败!',
profile: '个人信息',
systemSettings: '系统设定',
wizardSettings: '设置向导',
siteAuth: '用户认证',
helpDocs: '帮助文档',
restart: '重启',
@@ -1791,11 +1792,7 @@ export default {
webPush: 'WebPush',
creatingUser: '正在创建【{name}】用户,请稍后',
updatingUser: '正在更新【{name}】用户,请稍后',
usernameRequired: '用户名不能为空',
usernameExists: '用户名已存在',
passwordMinLength: '密码长度不能少于6位字符',
confirmPasswordRequired: '请确认密码',
passwordMismatch: '两次输入的密码不一致',
userCreated: '用户【{name}】创建成功',
userCreateFailed: '创建用户失败:{message}',
userUpdateSuccess: '用户【{name}】更新成功',
@@ -2939,7 +2936,7 @@ export default {
apiTokenRequired: 'API Token不能为空',
},
storage: {
title: '存储配置',
title: '存储',
description: '配置下载目录和媒体库目录',
info: '存储配置说明',
infoDesc: '配置本地存储目录,用于下载和媒体库管理',
@@ -2951,7 +2948,7 @@ export default {
libraryPathRequired: '媒体库目录不能为空',
},
downloader: {
title: '下载器配置',
title: '下载器',
description: '配置下载器',
info: '下载器配置说明',
infoDesc: '配置下载器用于下载资源可选择qBittorrent或Transmission',
@@ -2983,7 +2980,7 @@ export default {
token: '访问令牌',
},
notification: {
title: '通知设置',
title: '通知',
description: '配置通知渠道',
info: '通知配置说明',
infoDesc: '配置通知渠道用于接收系统消息(可选)',

View File

@@ -371,6 +371,7 @@ export default {
deleteFailed: '用戶刪除失敗!',
profile: '個人信息',
systemSettings: '系統設定',
wizardSettings: '設定向導',
siteAuth: '用戶認證',
helpDocs: '幫助文檔',
restart: '重啟',
@@ -2903,7 +2904,7 @@ export default {
apiTokenRequired: 'API Token 不能為空',
},
storage: {
title: '儲存配置',
title: '儲存',
description: '設定下載目錄和媒體庫目錄',
info: '儲存設定說明',
infoDesc: '設定本機儲存目錄,用於下載和媒體庫管理',
@@ -2915,7 +2916,7 @@ export default {
libraryPathRequired: '媒體庫目錄不能為空',
},
downloader: {
title: '下載器配置',
title: '下載器',
description: '設定下載器',
info: '下載器設定說明',
infoDesc: '設定下載器用於下載資源可選擇qBittorrent或Transmission',
@@ -2947,7 +2948,7 @@ export default {
token: '存取權杖',
},
notification: {
title: '通知設定',
title: '通知',
description: '設定通知管道',
info: '通知設定說明',
infoDesc: '設定通知管道用於接收系統訊息(可選)',

View File

@@ -10,10 +10,14 @@ import MediaServerSettingsStep from '@/views/setup/MediaServerSettingsStep.vue'
import NotificationSettingsStep from '@/views/setup/NotificationSettingsStep.vue'
import PreferencesSettingsStep from '@/views/setup/PreferencesSettingsStep.vue'
import ConnectivityTest from '@/views/setup/ConnectivityTest.vue'
import { useDisplay } from 'vuetify'
const { t } = useI18n()
const router = useRouter()
// 显示器宽度
const display = useDisplay()
const { currentStep, totalSteps, stepTitles, connectivityTest, nextStep, prevStep, completeWizard, initialize } =
useSetupWizard()
@@ -28,20 +32,27 @@ onMounted(async () => {
<!-- 全屏头部 -->
<div class="setup-wizard-header">
<div class="d-flex align-center justify-space-between">
<div class="d-flex align-center text-center mx-auto">
<!-- 左侧占位 -->
<div style="inline-size: 40px"></div>
<!-- 中间标题 -->
<div class="d-flex align-center text-center">
<div>
<h1 class="text-h3 font-weight-bold text-moviepilot mb-3">{{ t('setupWizard.title') }}</h1>
<p class="text-body-1 text-medium-emphasis">{{ t('setupWizard.subtitle') }}</p>
</div>
</div>
<!-- 右侧关闭按钮 -->
<VBtn variant="text" icon="mdi-close" @click="router.push('/')" size="small" />
</div>
</div>
<!-- 向导内容 -->
<div class="setup-wizard-content">
<div class="setup-wizard">
<VCard max-width="800px" class="mx-auto my-7">
<VCardText>
<!-- 使用 VStepper 组件 -->
<VStepper v-model="currentStep" class="elevation-0" flat>
<VStepper v-model="currentStep" class="elevation-0" flat alt-labels :mobile="display.smAndDown.value">
<!-- 步骤标题 -->
<VStepperHeader class="elevation-0">
<template v-for="(step, index) in stepTitles" :key="index">
@@ -49,6 +60,7 @@ onMounted(async () => {
:value="index + 1"
:complete="currentStep > index + 1"
:color="currentStep >= index + 1 ? 'primary' : 'default'"
complete-icon="mdi-check-circle"
>
<template #title>
<span class="text-caption">{{ step }}</span>
@@ -105,15 +117,6 @@ onMounted(async () => {
>
{{ t('common.previous') }}
</VBtn>
<VBtn
v-else
color="primary"
prepend-icon="mdi-keyboard-return"
@click="router.push('/')"
:disabled="connectivityTest.isTesting"
>
{{ t('common.skip') }}
</VBtn>
</div>
<div class="d-flex gap-2">
@@ -138,16 +141,15 @@ onMounted(async () => {
</div>
</VCardActions>
</VStepper>
</div>
</div>
</VCardText>
</VCard>
</div>
</template>
<style scoped>
.setup-wizard-fullscreen {
position: fixed;
z-index: 9999;
background-color: rgb(var(--v-theme-surface));
background-color: rgb(var(--v-theme-background));
inset: 0;
overflow-y: auto;
}
@@ -161,16 +163,4 @@ onMounted(async () => {
padding-block: 16px;
padding-inline: 24px;
}
.setup-wizard-content {
padding: 24px;
min-block-size: calc(100vh - 80px);
}
.setup-wizard {
padding: 20px;
margin-block: 0;
margin-inline: auto;
max-inline-size: 800px;
}
</style>

View File

@@ -41,7 +41,7 @@ const overwriteModeItems = [
</VAlert>
</VCol>
<VCol cols="12" md="6">
<VTextField
<VPathField
v-model="wizardData.storage.downloadPath"
:label="t('setupWizard.storage.downloadPath')"
:hint="t('setupWizard.storage.downloadPathHint')"
@@ -55,7 +55,7 @@ const overwriteModeItems = [
/>
</VCol>
<VCol cols="12" md="6">
<VTextField
<VPathField
v-model="wizardData.storage.libraryPath"
:label="t('setupWizard.storage.libraryPath')"
:hint="t('setupWizard.storage.libraryPathHint')"
@@ -69,7 +69,7 @@ const overwriteModeItems = [
/>
</VCol>
<VCol cols="12" md="6">
<VAutocomplete
<VSelect
v-model="wizardData.storage.transferType"
:label="t('directory.transferType')"
:hint="t('directory.transferTypeHint')"
@@ -79,7 +79,7 @@ const overwriteModeItems = [
/>
</VCol>
<VCol cols="12" md="6">
<VAutocomplete
<VSelect
v-model="wizardData.storage.overwriteMode"
:label="t('directory.overwriteMode')"
:hint="t('directory.overwriteModeHint')"