mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-06 08:06:43 +08:00
更新用户配置
This commit is contained in:
@@ -381,8 +381,11 @@ export default {
|
|||||||
addUser: 'Add User',
|
addUser: 'Add User',
|
||||||
editUser: 'Edit User',
|
editUser: 'Edit User',
|
||||||
username: 'Username',
|
username: 'Username',
|
||||||
|
usernameHint: 'Username for system login',
|
||||||
password: 'Password',
|
password: 'Password',
|
||||||
|
passwordHint: 'Password for system login',
|
||||||
confirmPassword: 'Confirm Password',
|
confirmPassword: 'Confirm Password',
|
||||||
|
confirmPasswordHint: 'Please enter the password again to confirm',
|
||||||
role: 'Role',
|
role: 'Role',
|
||||||
email: 'Email',
|
email: 'Email',
|
||||||
enabled: 'Enabled',
|
enabled: 'Enabled',
|
||||||
@@ -2839,7 +2842,9 @@ export default {
|
|||||||
libraryStorage: 'Library Storage',
|
libraryStorage: 'Library Storage',
|
||||||
libraryDirectory: 'Library Directory',
|
libraryDirectory: 'Library Directory',
|
||||||
transferType: 'Transfer Type',
|
transferType: 'Transfer Type',
|
||||||
|
transferTypeHint: 'File operation organization method, hard link saves space, copy is safer',
|
||||||
overwriteMode: 'Overwrite Mode',
|
overwriteMode: 'Overwrite Mode',
|
||||||
|
overwriteModeHint: 'How to handle when target file already exists',
|
||||||
smartRename: 'Smart Rename',
|
smartRename: 'Smart Rename',
|
||||||
scrapingMetadata: 'Scrape Metadata',
|
scrapingMetadata: 'Scrape Metadata',
|
||||||
sendNotification: 'Send Notification',
|
sendNotification: 'Send Notification',
|
||||||
|
|||||||
@@ -379,8 +379,11 @@ export default {
|
|||||||
addUser: '添加用户',
|
addUser: '添加用户',
|
||||||
editUser: '编辑用户',
|
editUser: '编辑用户',
|
||||||
username: '用户名',
|
username: '用户名',
|
||||||
|
usernameHint: '用于登录系统的用户名',
|
||||||
password: '密码',
|
password: '密码',
|
||||||
|
passwordHint: '用于登录系统的密码',
|
||||||
confirmPassword: '确认密码',
|
confirmPassword: '确认密码',
|
||||||
|
confirmPasswordHint: '请再次输入密码以确认',
|
||||||
role: '角色',
|
role: '角色',
|
||||||
email: '邮箱',
|
email: '邮箱',
|
||||||
enabled: '启用',
|
enabled: '启用',
|
||||||
@@ -2807,7 +2810,9 @@ export default {
|
|||||||
libraryStorage: '媒体库存储',
|
libraryStorage: '媒体库存储',
|
||||||
libraryDirectory: '媒体库目录',
|
libraryDirectory: '媒体库目录',
|
||||||
transferType: '整理方式',
|
transferType: '整理方式',
|
||||||
|
transferTypeHint: '文件操作整理方式,硬链接节省空间,复制更安全',
|
||||||
overwriteMode: '覆盖模式',
|
overwriteMode: '覆盖模式',
|
||||||
|
overwriteModeHint: '当目标文件已存在时的处理方式',
|
||||||
smartRename: '智能重命名',
|
smartRename: '智能重命名',
|
||||||
scrapingMetadata: '刮削元数据',
|
scrapingMetadata: '刮削元数据',
|
||||||
sendNotification: '发送通知',
|
sendNotification: '发送通知',
|
||||||
|
|||||||
@@ -380,8 +380,11 @@ export default {
|
|||||||
addUser: '添加用戶',
|
addUser: '添加用戶',
|
||||||
editUser: '編輯用戶',
|
editUser: '編輯用戶',
|
||||||
username: '用戶名',
|
username: '用戶名',
|
||||||
|
usernameHint: '用於登入系統的用戶名',
|
||||||
password: '密碼',
|
password: '密碼',
|
||||||
|
passwordHint: '用於登入系統的密碼',
|
||||||
confirmPassword: '確認密碼',
|
confirmPassword: '確認密碼',
|
||||||
|
confirmPasswordHint: '請再次輸入密碼以確認',
|
||||||
role: '角色',
|
role: '角色',
|
||||||
email: '郵箱',
|
email: '郵箱',
|
||||||
enabled: '啟用',
|
enabled: '啟用',
|
||||||
@@ -2806,7 +2809,9 @@ export default {
|
|||||||
libraryStorage: '媒體庫存儲',
|
libraryStorage: '媒體庫存儲',
|
||||||
libraryDirectory: '媒體庫目錄',
|
libraryDirectory: '媒體庫目錄',
|
||||||
transferType: '轉移方式',
|
transferType: '轉移方式',
|
||||||
|
transferTypeHint: '文件操作整理方式,硬連結節省空間,複製更安全',
|
||||||
overwriteMode: '覆蓋模式',
|
overwriteMode: '覆蓋模式',
|
||||||
|
overwriteModeHint: '當目標文件已存在時的處理方式',
|
||||||
smartRename: '智能重命名',
|
smartRename: '智能重命名',
|
||||||
scrapingMetadata: '刮削元數據',
|
scrapingMetadata: '刮削元數據',
|
||||||
sendNotification: '發送通知',
|
sendNotification: '發送通知',
|
||||||
|
|||||||
+383
-210
@@ -21,14 +21,19 @@ const wizardData = ref({
|
|||||||
// 步骤1:基础参数
|
// 步骤1:基础参数
|
||||||
basic: {
|
basic: {
|
||||||
appDomain: '',
|
appDomain: '',
|
||||||
wallpaper: 'tmdb',
|
|
||||||
recognizeSource: 'themoviedb',
|
|
||||||
apiToken: '',
|
apiToken: '',
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
confirmPassword: '',
|
||||||
|
proxyHost: '',
|
||||||
|
githubToken: '',
|
||||||
},
|
},
|
||||||
// 步骤2:存储目录
|
// 步骤2:存储目录
|
||||||
storage: {
|
storage: {
|
||||||
downloadPath: '',
|
downloadPath: '',
|
||||||
libraryPath: '',
|
libraryPath: '',
|
||||||
|
transferType: 'link',
|
||||||
|
overwriteMode: 'never',
|
||||||
},
|
},
|
||||||
// 步骤3:下载器
|
// 步骤3:下载器
|
||||||
downloader: {
|
downloader: {
|
||||||
@@ -79,18 +84,24 @@ const stepDescriptions = [
|
|||||||
t('setupWizard.step6.description'),
|
t('setupWizard.step6.description'),
|
||||||
]
|
]
|
||||||
|
|
||||||
// 壁纸选项
|
// 密码可见性控制
|
||||||
const wallpaperItems = [
|
const isPasswordVisible = ref(false)
|
||||||
{ title: t('setting.system.wallpaperItems.tmdb'), value: 'tmdb' },
|
const isConfirmPasswordVisible = ref(false)
|
||||||
{ title: t('setting.system.wallpaperItems.bing'), value: 'bing' },
|
|
||||||
{ title: t('setting.system.wallpaperItems.mediaserver'), value: 'mediaserver' },
|
// 整理方式选项
|
||||||
{ title: t('setting.system.wallpaperItems.none'), value: '' },
|
const transferTypeItems = [
|
||||||
|
{ title: '硬链接', value: 'link' },
|
||||||
|
{ title: '软链接', value: 'softlink' },
|
||||||
|
{ title: '复制', value: 'copy' },
|
||||||
|
{ title: '移动', value: 'move' },
|
||||||
]
|
]
|
||||||
|
|
||||||
// 识别源选项
|
// 覆盖模式选项
|
||||||
const recognizeSourceItems = [
|
const overwriteModeItems = [
|
||||||
{ title: 'TheMovieDb', value: 'themoviedb' },
|
{ title: '从不覆盖', value: 'never' },
|
||||||
{ title: '豆瓣', value: 'douban' },
|
{ title: '总是覆盖', value: 'always' },
|
||||||
|
{ title: '按文件大小', value: 'size' },
|
||||||
|
{ title: '仅保留最新', value: 'latest' },
|
||||||
]
|
]
|
||||||
|
|
||||||
// 质量偏好选项
|
// 质量偏好选项
|
||||||
@@ -182,8 +193,11 @@ function selectPreset(preset: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 下一步
|
// 下一步
|
||||||
function nextStep() {
|
async function nextStep() {
|
||||||
if (currentStep.value < totalSteps) {
|
if (currentStep.value < totalSteps) {
|
||||||
|
// 保存当前步骤的设置
|
||||||
|
await saveCurrentStepSettings()
|
||||||
|
|
||||||
currentStep.value++
|
currentStep.value++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,25 +209,48 @@ function prevStep() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 保存当前步骤的设置
|
||||||
|
async function saveCurrentStepSettings() {
|
||||||
|
try {
|
||||||
|
switch (currentStep.value) {
|
||||||
|
case 1:
|
||||||
|
await saveBasicSettings()
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
await saveStorageSettings()
|
||||||
|
break
|
||||||
|
case 3:
|
||||||
|
await saveDownloaderSettings()
|
||||||
|
break
|
||||||
|
case 4:
|
||||||
|
await saveMediaServerSettings()
|
||||||
|
break
|
||||||
|
case 5:
|
||||||
|
await saveNotificationSettings()
|
||||||
|
break
|
||||||
|
case 6:
|
||||||
|
await savePreferenceSettings()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Save current step settings failed:', error)
|
||||||
|
$toast.error(t('setupWizard.saveStepFailed'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 完成向导
|
// 完成向导
|
||||||
async function completeWizard() {
|
async function completeWizard() {
|
||||||
try {
|
try {
|
||||||
// 保存基础设置
|
// 验证密码一致性
|
||||||
await saveBasicSettings()
|
if (wizardData.value.basic.password !== wizardData.value.basic.confirmPassword) {
|
||||||
|
$toast.error(t('user.passwordMismatch'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 保存存储配置
|
// 创建用户(如果还没有创建)
|
||||||
await saveStorageSettings()
|
await createUser()
|
||||||
|
|
||||||
// 保存下载器配置
|
// 保存最后一步的设置(资源偏好)
|
||||||
await saveDownloaderSettings()
|
|
||||||
|
|
||||||
// 保存媒体服务器配置
|
|
||||||
await saveMediaServerSettings()
|
|
||||||
|
|
||||||
// 保存通知配置
|
|
||||||
await saveNotificationSettings()
|
|
||||||
|
|
||||||
// 保存资源偏好
|
|
||||||
await savePreferenceSettings()
|
await savePreferenceSettings()
|
||||||
|
|
||||||
$toast.success(t('setupWizard.completed'))
|
$toast.success(t('setupWizard.completed'))
|
||||||
@@ -224,104 +261,292 @@ async function completeWizard() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 创建用户
|
||||||
|
async function createUser() {
|
||||||
|
if (wizardData.value.basic.username && wizardData.value.basic.password) {
|
||||||
|
try {
|
||||||
|
// 检查用户是否已存在
|
||||||
|
const response = await api.get('user/')
|
||||||
|
const existingUsers = response.data || []
|
||||||
|
const userExists = existingUsers.some((user: any) => user.name === wizardData.value.basic.username)
|
||||||
|
|
||||||
|
if (!userExists) {
|
||||||
|
const userData = {
|
||||||
|
name: wizardData.value.basic.username,
|
||||||
|
password: wizardData.value.basic.password,
|
||||||
|
is_active: true,
|
||||||
|
is_superuser: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
await api.post('user/', userData)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Create user failed or user already exists:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 保存基础设置
|
// 保存基础设置
|
||||||
async function saveBasicSettings() {
|
async function saveBasicSettings() {
|
||||||
const basicSettings = {
|
try {
|
||||||
APP_DOMAIN: wizardData.value.basic.appDomain,
|
const basicSettings = {
|
||||||
WALLPAPER: wizardData.value.basic.wallpaper,
|
APP_DOMAIN: wizardData.value.basic.appDomain,
|
||||||
RECOGNIZE_SOURCE: wizardData.value.basic.recognizeSource,
|
API_TOKEN: wizardData.value.basic.apiToken,
|
||||||
API_TOKEN: wizardData.value.basic.apiToken,
|
PROXY_HOST: wizardData.value.basic.proxyHost,
|
||||||
}
|
GITHUB_TOKEN: wizardData.value.basic.githubToken,
|
||||||
|
}
|
||||||
|
|
||||||
await api.post('system/env', basicSettings)
|
const response = await api.post('system/env', basicSettings)
|
||||||
|
if (response.data?.success) {
|
||||||
|
$toast.success(t('setupWizard.basicSettingsSaved'))
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Save basic settings failed:', error)
|
||||||
|
$toast.error(t('setupWizard.saveBasicSettingsFailed'))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存存储配置
|
// 保存存储配置
|
||||||
async function saveStorageSettings() {
|
async function saveStorageSettings() {
|
||||||
// 创建本地存储
|
try {
|
||||||
const storage = {
|
// 创建本地存储
|
||||||
name: '本地存储',
|
const storage = {
|
||||||
type: 'local',
|
name: '本地存储',
|
||||||
config: {},
|
type: 'local',
|
||||||
|
config: {},
|
||||||
|
}
|
||||||
|
|
||||||
|
await api.post('system/setting/Storages', [storage])
|
||||||
|
|
||||||
|
// 创建目录配置
|
||||||
|
const directory = {
|
||||||
|
name: '默认目录',
|
||||||
|
storage: 'local',
|
||||||
|
download_path: wizardData.value.storage.downloadPath,
|
||||||
|
library_path: wizardData.value.storage.libraryPath,
|
||||||
|
priority: 0,
|
||||||
|
monitor_type: 'compatibility',
|
||||||
|
media_type: 'movie,tv',
|
||||||
|
media_category: 'default',
|
||||||
|
transfer_type: wizardData.value.storage.transferType,
|
||||||
|
overwrite_mode: wizardData.value.storage.overwriteMode,
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await api.post('system/setting/Directories', [directory])
|
||||||
|
if (response.data?.success) {
|
||||||
|
$toast.success(t('setupWizard.storageSettingsSaved'))
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Save storage settings failed:', error)
|
||||||
|
$toast.error(t('setupWizard.saveStorageSettingsFailed'))
|
||||||
}
|
}
|
||||||
|
|
||||||
await api.post('system/setting/Storages', [storage])
|
|
||||||
|
|
||||||
// 创建目录配置
|
|
||||||
const directory = {
|
|
||||||
name: '默认目录',
|
|
||||||
storage: 'local',
|
|
||||||
download_path: wizardData.value.storage.downloadPath,
|
|
||||||
library_path: wizardData.value.storage.libraryPath,
|
|
||||||
priority: 0,
|
|
||||||
monitor_type: 'compatibility',
|
|
||||||
media_type: 'movie,tv',
|
|
||||||
media_category: 'default',
|
|
||||||
transfer_type: 'link',
|
|
||||||
}
|
|
||||||
|
|
||||||
await api.post('system/setting/Directories', [directory])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存下载器配置
|
// 保存下载器配置
|
||||||
async function saveDownloaderSettings() {
|
async function saveDownloaderSettings() {
|
||||||
if (wizardData.value.downloader.type) {
|
if (wizardData.value.downloader.type) {
|
||||||
const downloader = {
|
try {
|
||||||
name: wizardData.value.downloader.name,
|
const downloader = {
|
||||||
type: wizardData.value.downloader.type,
|
name: wizardData.value.downloader.name,
|
||||||
default: true,
|
type: wizardData.value.downloader.type,
|
||||||
enabled: true,
|
default: true,
|
||||||
config: wizardData.value.downloader.config,
|
enabled: true,
|
||||||
}
|
config: wizardData.value.downloader.config,
|
||||||
|
}
|
||||||
|
|
||||||
await api.post('system/setting/Downloaders', [downloader])
|
const response = await api.post('system/setting/Downloaders', [downloader])
|
||||||
|
if (response.data?.success) {
|
||||||
|
$toast.success(t('setupWizard.downloaderSettingsSaved'))
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Save downloader settings failed:', error)
|
||||||
|
$toast.error(t('setupWizard.saveDownloaderSettingsFailed'))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存媒体服务器配置
|
// 保存媒体服务器配置
|
||||||
async function saveMediaServerSettings() {
|
async function saveMediaServerSettings() {
|
||||||
if (wizardData.value.mediaServer.type) {
|
if (wizardData.value.mediaServer.type) {
|
||||||
const mediaServer = {
|
try {
|
||||||
name: wizardData.value.mediaServer.name,
|
const mediaServer = {
|
||||||
type: wizardData.value.mediaServer.type,
|
name: wizardData.value.mediaServer.name,
|
||||||
enabled: true,
|
type: wizardData.value.mediaServer.type,
|
||||||
config: wizardData.value.mediaServer.config,
|
enabled: true,
|
||||||
}
|
config: wizardData.value.mediaServer.config,
|
||||||
|
}
|
||||||
|
|
||||||
await api.post('system/setting/MediaServers', [mediaServer])
|
const response = await api.post('system/setting/MediaServers', [mediaServer])
|
||||||
|
if (response.data?.success) {
|
||||||
|
$toast.success(t('setupWizard.mediaServerSettingsSaved'))
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Save media server settings failed:', error)
|
||||||
|
$toast.error(t('setupWizard.saveMediaServerSettingsFailed'))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存通知配置
|
// 保存通知配置
|
||||||
async function saveNotificationSettings() {
|
async function saveNotificationSettings() {
|
||||||
if (wizardData.value.notification.type) {
|
if (wizardData.value.notification.type) {
|
||||||
const notification = {
|
try {
|
||||||
name: wizardData.value.notification.name,
|
const notification = {
|
||||||
type: wizardData.value.notification.type,
|
name: wizardData.value.notification.name,
|
||||||
enabled: true,
|
type: wizardData.value.notification.type,
|
||||||
config: wizardData.value.notification.config,
|
enabled: true,
|
||||||
}
|
config: wizardData.value.notification.config,
|
||||||
|
}
|
||||||
|
|
||||||
await api.post('system/setting/Notifications', [notification])
|
const response = await api.post('system/setting/Notifications', [notification])
|
||||||
|
if (response.data?.success) {
|
||||||
|
$toast.success(t('setupWizard.notificationSettingsSaved'))
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Save notification settings failed:', error)
|
||||||
|
$toast.error(t('setupWizard.saveNotificationSettingsFailed'))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存资源偏好设置
|
// 保存资源偏好设置
|
||||||
async function savePreferenceSettings() {
|
async function savePreferenceSettings() {
|
||||||
// 这里可以根据偏好设置创建相应的过滤规则
|
try {
|
||||||
// 暂时保存到系统设置中
|
// 这里可以根据偏好设置创建相应的过滤规则
|
||||||
const preferenceSettings = {
|
// 暂时保存到系统设置中
|
||||||
QUALITY_PREFERENCE: wizardData.value.preferences.quality,
|
const preferenceSettings = {
|
||||||
SUBTITLE_PREFERENCE: wizardData.value.preferences.subtitle,
|
QUALITY_PREFERENCE: wizardData.value.preferences.quality,
|
||||||
RESOLUTION_PREFERENCE: wizardData.value.preferences.resolution,
|
SUBTITLE_PREFERENCE: wizardData.value.preferences.subtitle,
|
||||||
}
|
RESOLUTION_PREFERENCE: wizardData.value.preferences.resolution,
|
||||||
|
}
|
||||||
|
|
||||||
await api.post('system/env', preferenceSettings)
|
const response = await api.post('system/env', preferenceSettings)
|
||||||
|
if (response.data?.success) {
|
||||||
|
$toast.success(t('setupWizard.preferenceSettingsSaved'))
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Save preference settings failed:', error)
|
||||||
|
$toast.error(t('setupWizard.savePreferenceSettingsFailed'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载系统设置
|
||||||
|
async function loadSystemSettings() {
|
||||||
|
try {
|
||||||
|
const result: { [key: string]: any } = await api.get('system/env')
|
||||||
|
if (result.success) {
|
||||||
|
// 加载基础设置
|
||||||
|
if (result.data.APP_DOMAIN) {
|
||||||
|
wizardData.value.basic.appDomain = result.data.APP_DOMAIN
|
||||||
|
}
|
||||||
|
if (result.data.API_TOKEN) {
|
||||||
|
wizardData.value.basic.apiToken = result.data.API_TOKEN
|
||||||
|
}
|
||||||
|
if (result.data.PROXY_HOST) {
|
||||||
|
wizardData.value.basic.proxyHost = result.data.PROXY_HOST
|
||||||
|
}
|
||||||
|
if (result.data.GITHUB_TOKEN) {
|
||||||
|
wizardData.value.basic.githubToken = result.data.GITHUB_TOKEN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Load system settings failed:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载存储设置
|
||||||
|
async function loadStorageSettings() {
|
||||||
|
try {
|
||||||
|
const result: { [key: string]: any } = await api.get('system/setting/Directories')
|
||||||
|
if (result.success && result.data?.value && result.data.value.length > 0) {
|
||||||
|
const directory = result.data.value[0]
|
||||||
|
wizardData.value.storage.downloadPath = directory.download_path || ''
|
||||||
|
wizardData.value.storage.libraryPath = directory.library_path || ''
|
||||||
|
wizardData.value.storage.transferType = directory.transfer_type || 'link'
|
||||||
|
wizardData.value.storage.overwriteMode = directory.overwrite_mode || 'never'
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Load storage settings failed:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载下载器设置
|
||||||
|
async function loadDownloaderSettings() {
|
||||||
|
try {
|
||||||
|
const result: { [key: string]: any } = await api.get('system/setting/Downloaders')
|
||||||
|
if (result.success && result.data?.value && result.data.value.length > 0) {
|
||||||
|
const downloader = result.data.value[0]
|
||||||
|
wizardData.value.downloader.type = downloader.type
|
||||||
|
wizardData.value.downloader.name = downloader.name
|
||||||
|
wizardData.value.downloader.config = downloader.config || {}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Load downloader settings failed:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载媒体服务器设置
|
||||||
|
async function loadMediaServerSettings() {
|
||||||
|
try {
|
||||||
|
const result: { [key: string]: any } = await api.get('system/setting/MediaServers')
|
||||||
|
if (result.success && result.data?.value && result.data.value.length > 0) {
|
||||||
|
const mediaServer = result.data.value[0]
|
||||||
|
wizardData.value.mediaServer.type = mediaServer.type
|
||||||
|
wizardData.value.mediaServer.name = mediaServer.name
|
||||||
|
wizardData.value.mediaServer.config = mediaServer.config || {}
|
||||||
|
wizardData.value.mediaServer.sync_libraries = mediaServer.sync_libraries || []
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Load media server settings failed:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载通知设置
|
||||||
|
async function loadNotificationSettings() {
|
||||||
|
try {
|
||||||
|
const result: { [key: string]: any } = await api.get('system/setting/Notifications')
|
||||||
|
if (result.success && result.data?.value && result.data.value.length > 0) {
|
||||||
|
const notification = result.data.value[0]
|
||||||
|
wizardData.value.notification.type = notification.type
|
||||||
|
wizardData.value.notification.name = notification.name
|
||||||
|
wizardData.value.notification.enabled = notification.enabled
|
||||||
|
wizardData.value.notification.config = notification.config || {}
|
||||||
|
wizardData.value.notification.switchs = notification.switchs || []
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Load notification settings failed:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载资源偏好设置
|
||||||
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化
|
// 初始化
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
createRandomString()
|
createRandomString()
|
||||||
|
await loadSystemSettings()
|
||||||
|
await loadStorageSettings()
|
||||||
|
await loadDownloaderSettings()
|
||||||
|
await loadMediaServerSettings()
|
||||||
|
await loadNotificationSettings()
|
||||||
|
await loadPreferenceSettings()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -382,23 +607,62 @@ onMounted(() => {
|
|||||||
/>
|
/>
|
||||||
</VCol>
|
</VCol>
|
||||||
<VCol cols="12" md="6">
|
<VCol cols="12" md="6">
|
||||||
<VSelect
|
<VTextField
|
||||||
v-model="wizardData.basic.wallpaper"
|
v-model="wizardData.basic.username"
|
||||||
:label="t('setupWizard.basic.wallpaper')"
|
:label="t('user.username')"
|
||||||
:hint="t('setupWizard.basic.wallpaperHint')"
|
:hint="t('user.usernameHint')"
|
||||||
persistent-hint
|
persistent-hint
|
||||||
:items="wallpaperItems"
|
prepend-inner-icon="mdi-account"
|
||||||
prepend-inner-icon="mdi-image"
|
:rules="[(v: string) => !!v || t('user.usernameRequired')]"
|
||||||
/>
|
/>
|
||||||
</VCol>
|
</VCol>
|
||||||
<VCol cols="12" md="6">
|
<VCol cols="12" md="6">
|
||||||
<VSelect
|
<VTextField
|
||||||
v-model="wizardData.basic.recognizeSource"
|
v-model="wizardData.basic.password"
|
||||||
:label="t('setupWizard.basic.recognizeSource')"
|
:type="isPasswordVisible ? 'text' : 'password'"
|
||||||
:hint="t('setupWizard.basic.recognizeSourceHint')"
|
:label="t('user.password')"
|
||||||
|
:hint="t('user.passwordHint')"
|
||||||
persistent-hint
|
persistent-hint
|
||||||
:items="recognizeSourceItems"
|
prepend-inner-icon="mdi-lock"
|
||||||
prepend-inner-icon="mdi-database"
|
:append-inner-icon="isPasswordVisible ? 'mdi-eye-off-outline' : 'mdi-eye-outline'"
|
||||||
|
@click:append-inner="isPasswordVisible = !isPasswordVisible"
|
||||||
|
:rules="[(v: string) => !!v || t('user.passwordRequired'), (v: string) => v.length >= 6 || t('user.passwordMinLength')]"
|
||||||
|
/>
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12" md="6">
|
||||||
|
<VTextField
|
||||||
|
v-model="wizardData.basic.confirmPassword"
|
||||||
|
:type="isConfirmPasswordVisible ? 'text' : 'password'"
|
||||||
|
:label="t('user.confirmPassword')"
|
||||||
|
:hint="t('user.confirmPasswordHint')"
|
||||||
|
persistent-hint
|
||||||
|
prepend-inner-icon="mdi-lock-check"
|
||||||
|
:append-inner-icon="isConfirmPasswordVisible ? 'mdi-eye-off-outline' : 'mdi-eye-outline'"
|
||||||
|
@click:append-inner="isConfirmPasswordVisible = !isConfirmPasswordVisible"
|
||||||
|
:rules="[
|
||||||
|
(v: string) => !!v || t('user.confirmPasswordRequired'),
|
||||||
|
(v: string) => v === wizardData.basic.password || t('user.passwordMismatch')
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12" md="6">
|
||||||
|
<VTextField
|
||||||
|
v-model="wizardData.basic.proxyHost"
|
||||||
|
:label="t('setting.system.proxyHost')"
|
||||||
|
:hint="t('setting.system.proxyHostHint')"
|
||||||
|
placeholder="http://127.0.0.1:7890"
|
||||||
|
persistent-hint
|
||||||
|
prepend-inner-icon="mdi-server-network"
|
||||||
|
/>
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12" md="6">
|
||||||
|
<VTextField
|
||||||
|
v-model="wizardData.basic.githubToken"
|
||||||
|
:label="t('setting.system.githubToken')"
|
||||||
|
:placeholder="t('setting.system.githubTokenFormat')"
|
||||||
|
:hint="t('setting.system.githubTokenHint')"
|
||||||
|
persistent-hint
|
||||||
|
prepend-inner-icon="mdi-github"
|
||||||
/>
|
/>
|
||||||
</VCol>
|
</VCol>
|
||||||
<VCol cols="12" md="6">
|
<VCol cols="12" md="6">
|
||||||
@@ -455,6 +719,26 @@ onMounted(() => {
|
|||||||
placeholder="/media"
|
placeholder="/media"
|
||||||
/>
|
/>
|
||||||
</VCol>
|
</VCol>
|
||||||
|
<VCol cols="12" md="6">
|
||||||
|
<VSelect
|
||||||
|
v-model="wizardData.storage.transferType"
|
||||||
|
:label="t('directory.transferType')"
|
||||||
|
:hint="t('directory.transferTypeHint')"
|
||||||
|
persistent-hint
|
||||||
|
:items="transferTypeItems"
|
||||||
|
prepend-inner-icon="mdi-swap-horizontal"
|
||||||
|
/>
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12" md="6">
|
||||||
|
<VSelect
|
||||||
|
v-model="wizardData.storage.overwriteMode"
|
||||||
|
:label="t('directory.overwriteMode')"
|
||||||
|
:hint="t('directory.overwriteModeHint')"
|
||||||
|
persistent-hint
|
||||||
|
:items="overwriteModeItems"
|
||||||
|
prepend-inner-icon="mdi-file-replace"
|
||||||
|
/>
|
||||||
|
</VCol>
|
||||||
</VRow>
|
</VRow>
|
||||||
</VCardText>
|
</VCardText>
|
||||||
</VCard>
|
</VCard>
|
||||||
@@ -1621,117 +1905,6 @@ onMounted(() => {
|
|||||||
</VCardText>
|
</VCardText>
|
||||||
</VCard>
|
</VCard>
|
||||||
</VStepperWindowItem>
|
</VStepperWindowItem>
|
||||||
|
|
||||||
<!-- 步骤6:资源偏好 -->
|
|
||||||
<VStepperWindowItem :value="6">
|
|
||||||
<VCard variant="outlined">
|
|
||||||
<VCardText>
|
|
||||||
<div class="text-center mb-6">
|
|
||||||
<h3 class="text-h4 mb-2">{{ stepTitles[5] }}</h3>
|
|
||||||
<p class="text-body-1 text-medium-emphasis">{{ stepDescriptions[5] }}</p>
|
|
||||||
</div>
|
|
||||||
<VRow>
|
|
||||||
<VCol cols="12">
|
|
||||||
<VAlert type="info" variant="tonal" class="mb-4">
|
|
||||||
<VAlertTitle>{{ t('setupWizard.preferences.info') }}</VAlertTitle>
|
|
||||||
{{ t('setupWizard.preferences.infoDesc') }}
|
|
||||||
</VAlert>
|
|
||||||
</VCol>
|
|
||||||
|
|
||||||
<!-- 预设规则选择 -->
|
|
||||||
<VCol cols="12">
|
|
||||||
<VCard>
|
|
||||||
<VCardTitle class="text-h6">{{ t('setupWizard.preferences.presetRules') }}</VCardTitle>
|
|
||||||
<VCardText>
|
|
||||||
<VRow>
|
|
||||||
<VCol cols="12" md="4">
|
|
||||||
<VCard
|
|
||||||
:color="selectedPreset === '4k' ? 'primary' : 'default'"
|
|
||||||
:variant="selectedPreset === '4k' ? 'tonal' : 'outlined'"
|
|
||||||
class="cursor-pointer"
|
|
||||||
@click="selectPreset('4k')"
|
|
||||||
>
|
|
||||||
<VCardText class="text-center">
|
|
||||||
<VIcon icon="mdi-4k" size="48" class="mb-2" />
|
|
||||||
<div class="text-h6">4K 优先</div>
|
|
||||||
</VCardText>
|
|
||||||
</VCard>
|
|
||||||
</VCol>
|
|
||||||
<VCol cols="12" md="4">
|
|
||||||
<VCard
|
|
||||||
:color="selectedPreset === 'balanced' ? 'primary' : 'default'"
|
|
||||||
:variant="selectedPreset === 'balanced' ? 'tonal' : 'outlined'"
|
|
||||||
class="cursor-pointer"
|
|
||||||
@click="selectPreset('balanced')"
|
|
||||||
>
|
|
||||||
<VCardText class="text-center">
|
|
||||||
<VIcon icon="mdi-balance-scale" size="48" class="mb-2" />
|
|
||||||
<div class="text-h6">平衡模式</div>
|
|
||||||
</VCardText>
|
|
||||||
</VCard>
|
|
||||||
</VCol>
|
|
||||||
<VCol cols="12" md="4">
|
|
||||||
<VCard
|
|
||||||
:color="selectedPreset === 'chinese' ? 'primary' : 'default'"
|
|
||||||
:variant="selectedPreset === 'chinese' ? 'tonal' : 'outlined'"
|
|
||||||
class="cursor-pointer"
|
|
||||||
@click="selectPreset('chinese')"
|
|
||||||
>
|
|
||||||
<VCardText class="text-center">
|
|
||||||
<VIcon icon="mdi-translate" size="48" class="mb-2" />
|
|
||||||
<div class="text-h6">中文字幕</div>
|
|
||||||
</VCardText>
|
|
||||||
</VCard>
|
|
||||||
</VCol>
|
|
||||||
</VRow>
|
|
||||||
</VCardText>
|
|
||||||
</VCard>
|
|
||||||
</VCol>
|
|
||||||
|
|
||||||
<!-- 详细配置 -->
|
|
||||||
<VCol cols="12">
|
|
||||||
<VCard>
|
|
||||||
<VCardTitle class="text-h6">{{ t('setupWizard.preferences.detailedConfig') }}</VCardTitle>
|
|
||||||
<VCardText>
|
|
||||||
<VRow>
|
|
||||||
<VCol cols="12" md="4">
|
|
||||||
<VSelect
|
|
||||||
v-model="wizardData.preferences.quality"
|
|
||||||
:label="t('setupWizard.preferences.quality')"
|
|
||||||
:hint="t('setupWizard.preferences.qualityHint')"
|
|
||||||
persistent-hint
|
|
||||||
:items="qualityItems"
|
|
||||||
prepend-inner-icon="mdi-star"
|
|
||||||
/>
|
|
||||||
</VCol>
|
|
||||||
<VCol cols="12" md="4">
|
|
||||||
<VSelect
|
|
||||||
v-model="wizardData.preferences.subtitle"
|
|
||||||
:label="t('setupWizard.preferences.subtitle')"
|
|
||||||
:hint="t('setupWizard.preferences.subtitleHint')"
|
|
||||||
persistent-hint
|
|
||||||
:items="subtitleItems"
|
|
||||||
prepend-inner-icon="mdi-subtitles"
|
|
||||||
/>
|
|
||||||
</VCol>
|
|
||||||
<VCol cols="12" md="4">
|
|
||||||
<VSelect
|
|
||||||
v-model="wizardData.preferences.resolution"
|
|
||||||
:label="t('setupWizard.preferences.resolution')"
|
|
||||||
:hint="t('setupWizard.preferences.resolutionHint')"
|
|
||||||
persistent-hint
|
|
||||||
:items="resolutionItems"
|
|
||||||
prepend-inner-icon="mdi-monitor"
|
|
||||||
/>
|
|
||||||
</VCol>
|
|
||||||
</VRow>
|
|
||||||
</VCardText>
|
|
||||||
</VCard>
|
|
||||||
</VCol>
|
|
||||||
</VRow>
|
|
||||||
</VCardText>
|
|
||||||
</VCard>
|
|
||||||
</VStepperWindowItem>
|
|
||||||
</VStepperWindow>
|
</VStepperWindow>
|
||||||
|
|
||||||
<!-- 操作按钮 -->
|
<!-- 操作按钮 -->
|
||||||
|
|||||||
Reference in New Issue
Block a user