Compare commits

...

3 Commits
v2.10.10 ... v2

Author SHA1 Message Date
jxxghp
a9403c9c34 chore: bump version to 2.10.11 2026-05-07 08:23:20 +08:00
jxxghp
dc4914e3ca style: adjust downloader card API key field to span full width 2026-05-07 08:22:39 +08:00
jxxghp
f3dbc4afad feat: add qBittorrent API key setup support
Expose qBittorrent WebUI API Key fields in settings and setup so 5.2 users can connect without requiring username/password.

Refs jxxghp/MoviePilot#5724
2026-05-07 07:41:05 +08:00
7 changed files with 50 additions and 6 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "moviepilot",
"version": "2.10.10",
"version": "2.10.11",
"private": true,
"type": "module",
"bin": "dist/service.js",

View File

@@ -346,11 +346,23 @@ onUnmounted(() => {
prepend-inner-icon="mdi-server"
/>
</VCol>
<VCol cols="12">
<VTextField
v-model="downloaderInfo.config.apikey"
type="password"
:label="t('downloader.apiKey')"
:hint="t('downloader.qbittorrentApiKeyHint')"
persistent-hint
active
prepend-inner-icon="mdi-key-variant"
/>
</VCol>
<VCol cols="12" md="6">
<VTextField
v-model="downloaderInfo.config.username"
:label="t('downloader.username')"
:hint="t('downloader.username')"
:disabled="!!downloaderInfo.config.apikey"
persistent-hint
active
prepend-inner-icon="mdi-account"
@@ -362,6 +374,7 @@ onUnmounted(() => {
type="password"
:label="t('downloader.password')"
:hint="t('downloader.password')"
:disabled="!!downloaderInfo.config.apikey"
persistent-hint
active
prepend-inner-icon="mdi-lock"

View File

@@ -107,6 +107,7 @@ export interface ValidationErrorState {
downloader: {
name: boolean
host: boolean
apikey: boolean
username: boolean
password: boolean
}
@@ -277,6 +278,7 @@ const validationErrors = ref<ValidationErrorState>({
downloader: {
name: false,
host: false,
apikey: false,
username: false,
password: false,
},
@@ -466,6 +468,7 @@ export function useSetupWizard() {
validationErrors.value.downloader = {
name: false,
host: false,
apikey: false,
username: false,
password: false,
}
@@ -548,9 +551,18 @@ export function useSetupWizard() {
}
// 根据下载器类型验证其他必输项
if (
wizardData.value.downloader.type === 'qbittorrent'
|| wizardData.value.downloader.type === 'transmission'
if (wizardData.value.downloader.type === 'qbittorrent') {
const hasApiKey = !!wizardData.value.downloader.config?.apikey?.trim()
if (!hasApiKey && !wizardData.value.downloader.config?.username?.trim()) {
errors.push(t('downloader.usernameRequired'))
validationErrors.value.downloader.username = true
}
if (!hasApiKey && !wizardData.value.downloader.config?.password?.trim()) {
errors.push(t('downloader.passwordRequired'))
validationErrors.value.downloader.password = true
}
} else if (
wizardData.value.downloader.type === 'transmission'
|| wizardData.value.downloader.type === 'rtorrent'
) {
if (!wizardData.value.downloader.config?.username?.trim()) {

View File

@@ -2933,8 +2933,10 @@ export default {
rtorrentHostHint: 'HTTP: http://ip:port/RPC2 or SCGI: scgi://ip:port',
default: 'Default',
host: 'Host',
apiKey: 'API Key',
username: 'Username',
password: 'Password',
qbittorrentApiKeyHint: 'For qBittorrent 5.2+, you can use the WebUI API Key directly. When set, API Key auth is preferred.',
category: 'Auto Category Management',
sequentail: 'Sequential Download',
force_resume: 'Force Resume',

View File

@@ -2886,8 +2886,10 @@ export default {
rtorrentHostHint: 'HTTP: http://ip:port/RPC2 或 SCGI: scgi://ip:port',
default: '默认',
host: '地址',
apiKey: 'API Key',
username: '用户名',
password: '密码',
qbittorrentApiKeyHint: 'qBittorrent 5.2+ 可直接使用 WebUI API Key填写后将优先使用 API Key 登录。',
category: '自动分类管理',
sequentail: '顺序下载',
force_resume: '强制继续',

View File

@@ -2888,8 +2888,10 @@ export default {
enabled: '啟用',
default: '預設',
host: '地址',
apiKey: 'API Key',
username: '用戶名',
password: '密碼',
qbittorrentApiKeyHint: 'qBittorrent 5.2+ 可直接使用 WebUI API Key填寫後將優先使用 API Key 登入。',
category: '自動分類管理',
sequentail: '順序下載',
force_resume: '強制繼續',

View File

@@ -104,6 +104,17 @@ const { wizardData, selectDownloader, validationErrors } = useSetupWizard()
required
/>
</VCol>
<VCol cols="12" md="6">
<VTextField
v-model="wizardData.downloader.config.apikey"
type="password"
:label="t('downloader.apiKey')"
:hint="t('downloader.qbittorrentApiKeyHint')"
persistent-hint
active
prepend-inner-icon="mdi-key-variant"
/>
</VCol>
<VCol cols="12" md="6">
<VTextField
v-model="wizardData.downloader.config.username"
@@ -111,10 +122,11 @@ const { wizardData, selectDownloader, validationErrors } = useSetupWizard()
:hint="t('downloader.username')"
:error="validationErrors.downloader.username"
:error-messages="validationErrors.downloader.username ? [t('downloader.usernameRequired')] : []"
:disabled="!!wizardData.downloader.config.apikey"
persistent-hint
active
prepend-inner-icon="mdi-account"
required
:required="!wizardData.downloader.config.apikey"
/>
</VCol>
<VCol cols="12" md="6">
@@ -125,10 +137,11 @@ const { wizardData, selectDownloader, validationErrors } = useSetupWizard()
:hint="t('downloader.password')"
:error="validationErrors.downloader.password"
:error-messages="validationErrors.downloader.password ? [t('downloader.passwordRequired')] : []"
:disabled="!!wizardData.downloader.config.apikey"
persistent-hint
active
prepend-inner-icon="mdi-lock"
required
:required="!wizardData.downloader.config.apikey"
/>
</VCol>
<VCol cols="12" md="6">