From 08f36a74ca8a9395e80ab112c433d2dd5573bbca Mon Sep 17 00:00:00 2001 From: jxxghp Date: Thu, 11 Sep 2025 14:30:52 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=BC=BA=E9=85=8D=E7=BD=AE=E5=90=91?= =?UTF-8?q?=E5=AF=BC=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/composables/useSetupWizard.ts | 164 ++++----- src/locales/en-US.ts | 27 ++ src/locales/zh-CN.ts | 27 ++ src/locales/zh-TW.ts | 27 ++ src/pages/setup.vue | 21 +- src/views/setup/DownloaderSettingsStep.vue | 2 + src/views/setup/MediaServerSettingsStep.vue | 2 + src/views/setup/NotificationSettingsStep.vue | 2 + src/views/setup/PreferencesSettingsStep.vue | 366 ++++++++++++------- 9 files changed, 427 insertions(+), 211 deletions(-) diff --git a/src/composables/useSetupWizard.ts b/src/composables/useSetupWizard.ts index 9c7a937f..66fdfa24 100644 --- a/src/composables/useSetupWizard.ts +++ b/src/composables/useSetupWizard.ts @@ -45,6 +45,16 @@ export interface WizardData { quality: string subtitle: string resolution: string + personalizationOptions?: { + excludeDolbyVision: boolean + excludeBluray: boolean + } + ruleSequences?: Array<{ + name: string + rule_string: string + media_type: string + category: string + }> } } @@ -81,6 +91,9 @@ export interface ValidationErrorState { const currentStep = ref(1) const totalSteps = 6 +// 加载状态 +const isLoading = ref(false) + // 选中的预设规则 const selectedPreset = ref('') @@ -298,6 +311,15 @@ export function useSetupWizard() { } } + // 更新偏好设置 + function updatePreferences( + personalizationOptions: { excludeDolbyVision: boolean; excludeBluray: boolean }, + ruleSequences: Array<{ name: string; rule_string: string; media_type: string; category: string }>, + ) { + wizardData.value.preferences.personalizationOptions = personalizationOptions + wizardData.value.preferences.ruleSequences = ruleSequences + } + // 清除验证错误状态 function clearValidationErrors() { validationErrors.value.downloader = { @@ -412,7 +434,6 @@ export function useSetupWizard() { // 根据通知类型验证必输项 const config = wizardData.value.notification.config || {} - alert(wizardData.value.notification.type) switch (wizardData.value.notification.type) { case 'wechat': if (!config.WECHAT_CORPID?.trim()) { @@ -591,11 +612,9 @@ export function useSetupWizard() { // 根据结果显示不同的消息 if (testResult.success) { connectivityTest.value.testMessage = t('setupWizard.connectivityTestSuccess') - $toast.success(t('setupWizard.connectivityTestSuccess')) } else { // 显示API返回的具体错误原因 connectivityTest.value.testMessage = testResult.message || t('setupWizard.connectivityTestFailed') - $toast.error(testResult.message || t('setupWizard.connectivityTestFailed')) } // 成功时2秒后隐藏结果,失败时保持显示直到用户操作 @@ -611,7 +630,6 @@ export function useSetupWizard() { connectivityTest.value.testResult = 'error' connectivityTest.value.showResult = true connectivityTest.value.testMessage = (error as Error).message || t('setupWizard.connectivityTestFailed') - $toast.error((error as Error).message || t('setupWizard.connectivityTestFailed')) return false } } @@ -757,29 +775,30 @@ export function useSetupWizard() { // 下一步 async function nextStep() { - if (currentStep.value < totalSteps) { - // 验证当前步骤的必输项 - const validation = validateCurrentStep() - if (!validation.isValid) { - // 显示验证错误 - validation.errors.forEach(error => { - $toast.error(error) - }) + // 验证当前步骤的必输项 + const validation = validateCurrentStep() + if (!validation.isValid) { + // 显示验证错误 + validation.errors.forEach(error => { + $toast.error(error) + }) + return + } + + // 保存当前步骤的设置 + await saveCurrentStepSettings() + + // 检查是否需要进行测试 + const needsTest = shouldPerformTest(currentStep.value) + if (needsTest) { + const testResult = await testConnectivity(currentStep.value) + if (!testResult) { return } + } - // 保存当前步骤的设置 - await saveCurrentStepSettings() - - // 检查是否需要进行测试 - const needsTest = shouldPerformTest(currentStep.value) - if (needsTest) { - const testResult = await testConnectivity(currentStep.value) - if (!testResult) { - return - } - } - + // 如果不是最后一步,则前进到下一步 + if (currentStep.value < totalSteps) { currentStep.value++ connectivityTest.value.showResult = false } @@ -825,7 +844,7 @@ export function useSetupWizard() { // 完成向导 async function completeWizard() { try { - // 先处理下一步 + // 先处理下一步(保存当前步骤设置) await nextStep() // 保存设置向导完成状态 await saveSetupWizardState() @@ -855,7 +874,6 @@ export function useSetupWizard() { } await api.put(`user/${currentUser.id}`, userData) - $toast.success(t('setupWizard.passwordUpdateSuccess')) } else { // 如果用户不存在,创建新用户(通常不会发生) const userData = { @@ -866,11 +884,9 @@ export function useSetupWizard() { } await api.post('user/', userData) - $toast.success(t('setupWizard.userCreateSuccess')) } } catch (error) { console.error('Update user password failed:', error) - $toast.error(t('setupWizard.passwordUpdateFailed')) throw error } } @@ -888,9 +904,7 @@ export function useSetupWizard() { // 保存基础设置 const response: { [key: string]: any } = await api.post('system/env', basicSettings) - if (response.success) { - $toast.success(t('setupWizard.basicSettingsSaved')) - } else { + if (!response.success) { return } @@ -943,10 +957,7 @@ export function useSetupWizard() { library_category_folder: true, } - const response: { [key: string]: any } = await api.post('system/setting/Directories', [directory]) - if (response.success) { - $toast.success(t('setupWizard.storageSettingsSaved')) - } + await api.post('system/setting/Directories', [directory]) } catch (error) { console.error('Save storage settings failed:', error) $toast.error(t('setupWizard.saveStorageSettingsFailed')) @@ -968,10 +979,7 @@ export function useSetupWizard() { config: config, } - const response: { [key: string]: any } = await api.post('system/setting/Downloaders', [downloader]) - if (response.success) { - $toast.success(t('setupWizard.downloaderSettingsSaved')) - } + await api.post('system/setting/Downloaders', [downloader]) } catch (error) { console.error('Save downloader settings failed:', error) $toast.error(t('setupWizard.saveDownloaderSettingsFailed')) @@ -998,10 +1006,7 @@ export function useSetupWizard() { sync_libraries: sync_libraries, } - const response: { [key: string]: any } = await api.post('system/setting/MediaServers', [mediaServer]) - if (response.success) { - $toast.success(t('setupWizard.mediaServerSettingsSaved')) - } + await api.post('system/setting/MediaServers', [mediaServer]) } catch (error) { console.error('Save media server settings failed:', error) $toast.error(t('setupWizard.saveMediaServerSettingsFailed')) @@ -1028,10 +1033,7 @@ export function useSetupWizard() { switchs: switchs, } - const response: { [key: string]: any } = await api.post('system/setting/Notifications', [notification]) - if (response.success) { - $toast.success(t('setupWizard.notificationSettingsSaved')) - } + await api.post('system/setting/Notifications', [notification]) } catch (error) { console.error('Save notification settings failed:', error) $toast.error(t('setupWizard.saveNotificationSettingsFailed')) @@ -1045,17 +1047,27 @@ export function useSetupWizard() { // 保存资源偏好设置 async function savePreferenceSettings() { try { - // 这里可以根据偏好设置创建相应的过滤规则 - // 暂时保存到系统设置中 - const preferenceSettings = { - QUALITY_PREFERENCE: wizardData.value.preferences.quality, - SUBTITLE_PREFERENCE: wizardData.value.preferences.subtitle, - RESOLUTION_PREFERENCE: wizardData.value.preferences.resolution, - } + // 如果有自定义规则序列,保存到用户过滤规则组 + if (wizardData.value.preferences.ruleSequences && wizardData.value.preferences.ruleSequences.length > 0) { + try { + // 保存当前选中的规则组到 UserFilterRuleGroups + const filterResponse: { [key: string]: any } = await api.post( + 'system/setting/UserFilterRuleGroups', + wizardData.value.preferences.ruleSequences, + ) + if (filterResponse.success) { + // 保存规则组名称到其他设置 + const ruleGroupNames = wizardData.value.preferences.ruleSequences.map(rule => [rule.name]) - const response: { [key: string]: any } = await api.post('system/env', preferenceSettings) - if (response.success) { - $toast.success(t('setupWizard.preferenceSettingsSaved')) + // 保存到 SubscribeFilterRuleGroups + await api.post('system/setting/SubscribeFilterRuleGroups', ruleGroupNames) + + // 保存到 BestVersionFilterRuleGroups + await api.post('system/setting/BestVersionFilterRuleGroups', ruleGroupNames) + } + } catch (error) { + console.error('Save rule sequences failed:', error) + } } } catch (error) { console.error('Save preference settings failed:', error) @@ -1172,34 +1184,18 @@ export function useSetupWizard() { } } - // 加载资源偏好设置 - async function loadPreferenceSettings() { - try { - const result: { [key: string]: any } = await api.get('system/env') - if (result.success) { - if (result.data.QUALITY_PREFERENCE) { - wizardData.value.preferences.quality = result.data.QUALITY_PREFERENCE - } - if (result.data.SUBTITLE_PREFERENCE) { - wizardData.value.preferences.subtitle = result.data.SUBTITLE_PREFERENCE - } - if (result.data.RESOLUTION_PREFERENCE) { - wizardData.value.preferences.resolution = result.data.RESOLUTION_PREFERENCE - } - } - } catch (error) { - console.log('Load preference settings failed:', error) - } - } - // 初始化 async function initialize() { - await loadSystemSettings() - await loadStorageSettings() - await loadDownloaderSettings() - await loadMediaServerSettings() - await loadNotificationSettings() - await loadPreferenceSettings() + isLoading.value = true + try { + await loadSystemSettings() + await loadStorageSettings() + await loadDownloaderSettings() + await loadMediaServerSettings() + await loadNotificationSettings() + } finally { + isLoading.value = false + } } return { @@ -1212,6 +1208,7 @@ export function useSetupWizard() { selectedPreset, connectivityTest, validationErrors, + isLoading, // 方法 createRandomString, @@ -1220,6 +1217,7 @@ export function useSetupWizard() { selectMediaServer, selectNotification, selectPreset, + updatePreferences, validateCurrentStep, validateDownloaderFields, validateMediaServerFields, diff --git a/src/locales/en-US.ts b/src/locales/en-US.ts index b82f6c2b..86c4b204 100644 --- a/src/locales/en-US.ts +++ b/src/locales/en-US.ts @@ -2914,6 +2914,7 @@ export default { completed: 'Setup Wizard completed!', failed: 'Setup Wizard failed, please try again', complete: 'Complete Configuration', + loading: 'Loading configuration data...', testing: 'Testing', connectivityTestSuccess: 'Connectivity test passed', connectivityTestFailed: 'Connectivity test failed', @@ -3025,6 +3026,32 @@ export default { resolutionHint: 'Select preferred video resolution', presetRules: 'Preset Rules', detailedConfig: 'Detailed Configuration', + quickPresets: 'Quick Presets', + quickPresetsDesc: 'Select preset configuration, system will automatically apply corresponding rules', + personalizationOptions: 'Personalization Options', + personalizationOptionsDesc: 'Adjust rules according to your needs', + excludeDolbyVision: 'Exclude Dolby Vision', + excludeDolbyVisionHint: 'Exclude Dolby Vision resources from rules when selected', + excludeBluray: 'Exclude Blu-ray', + excludeBlurayHint: 'Exclude Blu-ray resources from rules when selected', + presets: { + '4k-enthusiast': { + name: '4K Enthusiast', + description: 'Pursue the highest quality, prioritize 4K', + }, + 'balanced': { + name: 'Balanced Mode', + description: 'Balance between quality and storage space', + }, + 'space-saver': { + name: 'Space Saver', + description: 'Prioritize smaller files to save storage space', + }, + 'free-priority': { + name: 'Free Priority', + description: 'Prioritize free resources, no other requirements', + }, + }, }, }, } diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index e06b1408..5b8d8897 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -2881,6 +2881,7 @@ export default { completed: '配置向导完成!', failed: '配置向导失败,请重试', complete: '完成配置', + loading: '正在加载配置数据...', testing: '正在测试', connectivityTestSuccess: '连通性测试通过', connectivityTestFailed: '连通性测试失败', @@ -3011,6 +3012,32 @@ export default { resolutionHint: '选择偏好的视频分辨率', presetRules: '预设规则', detailedConfig: '详细配置', + quickPresets: '快速预设', + quickPresetsDesc: '选择预设配置,系统将自动应用对应的规则', + personalizationOptions: '个性化选项', + personalizationOptionsDesc: '根据您的需求调整规则', + excludeDolbyVision: '排除杜比视界', + excludeDolbyVisionHint: '选中后规则中将排除杜比视界资源', + excludeBluray: '排除蓝光原盘', + excludeBlurayHint: '选中后规则中将排除蓝光原盘资源', + presets: { + '4k-enthusiast': { + name: '4K发烧友', + description: '追求最高画质,优先4K', + }, + 'balanced': { + name: '平衡模式', + description: '画质与存储空间的平衡选择', + }, + 'space-saver': { + name: '节省空间', + description: '优先较小文件,节省存储空间', + }, + 'free-priority': { + name: '免费优先', + description: '优先免费资源,其它的没有要求', + }, + }, }, }, } diff --git a/src/locales/zh-TW.ts b/src/locales/zh-TW.ts index 122d6146..7bdf1e53 100644 --- a/src/locales/zh-TW.ts +++ b/src/locales/zh-TW.ts @@ -2869,6 +2869,7 @@ export default { completed: '設定精靈完成!', failed: '設定精靈失敗,請重試', complete: '完成設定', + loading: '正在載入配置資料...', testing: '正在測試', connectivityTestSuccess: '連通性測試通過', connectivityTestFailed: '連通性測試失敗', @@ -2979,6 +2980,32 @@ export default { resolutionHint: '選擇偏好的影片解析度', presetRules: '預設規則', detailedConfig: '詳細設定', + quickPresets: '快速預設', + quickPresetsDesc: '選擇預設配置,系統將自動應用對應的規則', + personalizationOptions: '個性化選項', + personalizationOptionsDesc: '根據您的需求調整規則', + excludeDolbyVision: '排除杜比視界', + excludeDolbyVisionHint: '選中後規則中將排除杜比視界資源', + excludeBluray: '排除藍光原盤', + excludeBlurayHint: '選中後規則中將排除藍光原盤資源', + presets: { + '4k-enthusiast': { + name: '4K發燒友', + description: '追求最高畫質,優先4K', + }, + 'balanced': { + name: '平衡模式', + description: '畫質與儲存空間的平衡選擇', + }, + 'space-saver': { + name: '節省空間', + description: '優先較小檔案,節省儲存空間', + }, + 'free-priority': { + name: '免費優先', + description: '優先免費資源,其它的沒有要求', + }, + }, }, }, } diff --git a/src/pages/setup.vue b/src/pages/setup.vue index be62182f..69283582 100644 --- a/src/pages/setup.vue +++ b/src/pages/setup.vue @@ -18,8 +18,17 @@ const router = useRouter() // 显示器宽度 const display = useDisplay() -const { currentStep, totalSteps, stepTitles, connectivityTest, nextStep, prevStep, completeWizard, initialize } = - useSetupWizard() +const { + currentStep, + totalSteps, + stepTitles, + connectivityTest, + nextStep, + prevStep, + completeWizard, + initialize, + isLoading, +} = useSetupWizard() // 初始化 onMounted(async () => { @@ -60,8 +69,14 @@ onMounted(async () => { + +
+ +

{{ t('setupWizard.loading') }}

+
+ - +