Skip to content

Commit 4207a70

Browse files
committed
feat: add support for ZSpace media server integration including UI configuration and logo assets
1 parent c97247b commit 4207a70

12 files changed

Lines changed: 217 additions & 10 deletions

File tree

src/api/constants.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ export const mediaServerOptions = [
6868
value: 'emby',
6969
title: i18n.global.t('setting.system.emby'),
7070
},
71+
{
72+
value: 'zspace',
73+
title: i18n.global.t('setting.system.zspace'),
74+
},
7175
{
7276
value: 'jellyfin',
7377
title: i18n.global.t('setting.system.jellyfin'),

src/api/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1145,7 +1145,7 @@ export interface StorageConf {
11451145
export interface MediaServerConf {
11461146
// 名称
11471147
name: string
1148-
// 类型 emby/jellyfin/plex/trimemedia/ugreen
1148+
// 类型 emby/zspace/jellyfin/plex/trimemedia/ugreen
11491149
type: string
11501150
// 配置
11511151
config: { [key: string]: any }
7.19 KB
Loading

src/components/cards/LibraryCard.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ function imageErrorHandler() {
4040
function getDefaultImage() {
4141
if (props.media?.server_type === 'plex') return plex
4242
else if (props.media?.server_type === 'emby') return emby
43+
else if (props.media?.server_type === 'zspace') return getLogoUrl('zspace')
4344
else if (props.media?.server_type === 'jellyfin') return jellyfin
4445
else if (props.media?.server_type === 'trimemedia') return getLogoUrl('trimemedia')
4546
else if (props.media?.server_type === 'ugreen') return getLogoUrl('ugreen')

src/components/cards/MediaServerCard.vue

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ const getIcon = computed(() => {
121121
switch (props.mediaserver.type) {
122122
case 'emby':
123123
return getLogoUrl('emby')
124+
case 'zspace':
125+
return getLogoUrl('zspace')
124126
case 'jellyfin':
125127
return getLogoUrl('jellyfin')
126128
case 'trimemedia':
@@ -318,6 +320,77 @@ onMounted(() => {
318320
/>
319321
</VCol>
320322
</VRow>
323+
<VRow v-else-if="mediaServerInfo.type == 'zspace'">
324+
<VCol cols="12" md="6">
325+
<VTextField
326+
v-model="mediaServerInfo.name"
327+
:label="t('common.name')"
328+
:placeholder="t('mediaserver.nameRequired')"
329+
:hint="t('mediaserver.serverAlias')"
330+
persistent-hint
331+
active
332+
prepend-inner-icon="mdi-label"
333+
/>
334+
</VCol>
335+
<VCol cols="12" md="6">
336+
<VTextField
337+
v-model="mediaServerInfo.config.host"
338+
:label="t('mediaserver.host')"
339+
:placeholder="t('mediaserver.hostPlaceholder')"
340+
:hint="t('mediaserver.hostHint')"
341+
persistent-hint
342+
active
343+
prepend-inner-icon="mdi-server"
344+
/>
345+
</VCol>
346+
<VCol cols="12">
347+
<VTextField
348+
v-model="mediaServerInfo.config.play_host"
349+
:label="t('mediaserver.playHost')"
350+
:placeholder="t('mediaserver.playHostPlaceholder')"
351+
:hint="t('mediaserver.playHostHint')"
352+
persistent-hint
353+
active
354+
prepend-inner-icon="mdi-play-network"
355+
/>
356+
</VCol>
357+
<VCol cols="12" md="6">
358+
<VTextField
359+
v-model="mediaServerInfo.config.username"
360+
:label="t('mediaserver.username')"
361+
:hint="t('mediaserver.usernameHint')"
362+
persistent-hint
363+
active
364+
prepend-inner-icon="mdi-account"
365+
/>
366+
</VCol>
367+
<VCol cols="12" md="6">
368+
<VTextField
369+
type="password"
370+
v-model="mediaServerInfo.config.password"
371+
:label="t('mediaserver.password')"
372+
persistent-hint
373+
active
374+
prepend-inner-icon="mdi-lock"
375+
/>
376+
</VCol>
377+
<VCol cols="12">
378+
<VAutocomplete
379+
v-model="mediaServerInfo.sync_libraries"
380+
:label="t('mediaserver.syncLibraries')"
381+
:items="librariesOptions"
382+
chips
383+
multiple
384+
clearable
385+
:hint="t('mediaserver.syncLibrariesHint')"
386+
persistent-hint
387+
active
388+
append-inner-icon="mdi-refresh"
389+
prepend-inner-icon="mdi-library"
390+
@click:append-inner="loadLibrary(mediaServerInfo.name)"
391+
/>
392+
</VCol>
393+
</VRow>
321394
<VRow v-else-if="mediaServerInfo.type == 'jellyfin'">
322395
<VCol cols="12" md="6">
323396
<VTextField

src/composables/useSetupWizard.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ export function useSetupWizard() {
320320
// 媒体服务器映射
321321
mediaServer: {
322322
'emby': 'EmbyModule',
323+
'zspace': 'ZSpaceModule',
323324
'jellyfin': 'JellyfinModule',
324325
'plex': 'PlexModule',
325326
'trimemedia': 'TrimeMediaModule',
@@ -617,6 +618,15 @@ export function useSetupWizard() {
617618
errors.push(t('mediaserver.apiKeyRequired'))
618619
validationErrors.value.mediaServer.apikey = true
619620
}
621+
} else if (wizardData.value.mediaServer.type === 'zspace') {
622+
if (!wizardData.value.mediaServer.config?.username?.trim()) {
623+
errors.push(t('mediaserver.usernameRequired'))
624+
validationErrors.value.mediaServer.username = true
625+
}
626+
if (!wizardData.value.mediaServer.config?.password?.trim()) {
627+
errors.push(t('mediaserver.passwordRequired'))
628+
validationErrors.value.mediaServer.password = true
629+
}
620630
} else if (wizardData.value.mediaServer.type === 'plex') {
621631
if (!wizardData.value.mediaServer.config?.token?.trim()) {
622632
errors.push(t('mediaserver.tokenRequired'))

src/locales/en-US.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ export default {
321321
system: {
322322
title: 'System',
323323
description:
324-
'Basic settings, downloaders (Qbittorrent, Transmission), media servers (Emby, Jellyfin, Plex, TrimeMedia, Ugreen)',
324+
'Basic settings, downloaders (Qbittorrent, Transmission), media servers (Emby, ZSpace, Jellyfin, Plex, TrimeMedia, Ugreen)',
325325
},
326326
directory: {
327327
title: 'Storage & Directories',
@@ -920,6 +920,7 @@ export default {
920920
plex: 'Plex',
921921
jellyfin: 'Jellyfin',
922922
emby: 'Emby',
923+
zspace: 'ZSpace',
923924
appLaunchFailed: 'App launch failed, redirecting to web version',
924925
appNotInstalled: 'App not detected, redirecting to web version',
925926
downloadApp: 'Download App',
@@ -1493,6 +1494,7 @@ export default {
14931494
transmission: 'Transmission',
14941495
rtorrent: 'rTorrent',
14951496
emby: 'Emby',
1497+
zspace: 'ZSpace',
14961498
jellyfin: 'Jellyfin',
14971499
plex: 'Plex',
14981500
ugreen: 'Ugreen',
@@ -3392,12 +3394,13 @@ export default {
33923394
description: 'Configure media server',
33933395
info: 'Media Server Configuration',
33943396
infoDesc:
3395-
'Configure media server for media library management, can choose Emby, Jellyfin, Plex, TrimeMedia or Ugreen.',
3397+
'Configure media server for media library management, can choose Emby, ZSpace, Jellyfin, Plex, TrimeMedia or Ugreen.',
33963398
type: 'Media Server Type',
33973399
typeHint: 'Select the type of media server to use',
33983400
name: 'Server Name',
33993401
nameHint: 'Set a name for the media server',
34003402
embyConfig: 'Emby Configuration',
3403+
zspaceConfig: 'ZSpace Configuration',
34013404
jellyfinConfig: 'Jellyfin Configuration',
34023405
plexConfig: 'Plex Configuration',
34033406
host: 'Server Address',

src/locales/zh-CN.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ export default {
319319
settingTabs: {
320320
system: {
321321
title: '系统',
322-
description: '基础设置、下载器(Qbittorrent、Transmission)、媒体服务器(Emby、Jellyfin、Plex、飞牛影视、绿联影视)',
322+
description: '基础设置、下载器(Qbittorrent、Transmission)、媒体服务器(Emby、极影视、Jellyfin、Plex、飞牛影视、绿联影视)',
323323
},
324324
directory: {
325325
title: '存储 & 目录',
@@ -915,6 +915,7 @@ export default {
915915
plex: 'Plex',
916916
jellyfin: 'Jellyfin',
917917
emby: 'Emby',
918+
zspace: '极影视',
918919
appLaunchFailed: 'APP启动失败,正在跳转到网页版',
919920
appNotInstalled: '未检测到APP,正在跳转到网页版',
920921
downloadApp: '下载APP',
@@ -1478,6 +1479,7 @@ export default {
14781479
transmission: 'Transmission',
14791480
rtorrent: 'rTorrent',
14801481
emby: 'Emby',
1482+
zspace: '极影视',
14811483
jellyfin: 'Jellyfin',
14821484
plex: 'Plex',
14831485
ugreen: '绿联影视',
@@ -3337,12 +3339,13 @@ export default {
33373339
title: '媒体服务器',
33383340
description: '配置媒体服务器',
33393341
info: '媒体服务器配置说明',
3340-
infoDesc: '配置媒体服务器用于媒体库管理,可选择Emby、Jellyfin、Plex、飞牛影视或绿联影视',
3342+
infoDesc: '配置媒体服务器用于媒体库管理,可选择Emby、极影视、Jellyfin、Plex、飞牛影视或绿联影视',
33413343
type: '媒体服务器类型',
33423344
typeHint: '选择要使用的媒体服务器类型',
33433345
name: '服务器名称',
33443346
nameHint: '为媒体服务器设置一个名称',
33453347
embyConfig: 'Emby 配置',
3348+
zspaceConfig: '极影视 配置',
33463349
jellyfinConfig: 'Jellyfin 配置',
33473350
plexConfig: 'Plex 配置',
33483351
host: '服务器地址',

src/locales/zh-TW.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ export default {
320320
system: {
321321
title: '系統',
322322
description:
323-
'基礎設置、下載器(Qbittorrent、Transmission)、媒體服務器(Emby、Jellyfin、Plex、飛牛影視、綠聯影視)',
323+
'基礎設置、下載器(Qbittorrent、Transmission)、媒體服務器(Emby、極影視、Jellyfin、Plex、飛牛影視、綠聯影視)',
324324
},
325325
directory: {
326326
title: '存儲 & 目錄',
@@ -916,6 +916,7 @@ export default {
916916
plex: 'Plex',
917917
jellyfin: 'Jellyfin',
918918
emby: 'Emby',
919+
zspace: '極影視',
919920
appLaunchFailed: 'APP啟動失敗,正在跳轉到網頁版',
920921
appNotInstalled: '未檢測到APP,正在跳轉到網頁版',
921922
downloadApp: '下載APP',
@@ -1480,6 +1481,7 @@ export default {
14801481
transmission: 'Transmission',
14811482
rtorrent: 'rTorrent',
14821483
emby: 'Emby',
1484+
zspace: '極影視',
14831485
jellyfin: 'Jellyfin',
14841486
plex: 'Plex',
14851487
ugreen: '綠聯影視',
@@ -3339,12 +3341,13 @@ export default {
33393341
title: '媒體伺服器',
33403342
description: '設定媒體伺服器',
33413343
info: '媒體伺服器設定說明',
3342-
infoDesc: '設定媒體伺服器用於媒體庫管理,可選擇Emby、Jellyfin、Plex、飛牛影視或綠聯影視',
3344+
infoDesc: '設定媒體伺服器用於媒體庫管理,可選擇Emby、極影視、Jellyfin、Plex、飛牛影視或綠聯影視',
33433345
type: '媒體伺服器類型',
33443346
typeHint: '選擇要使用的媒體伺服器類型',
33453347
name: '伺服器名稱',
33463348
nameHint: '為媒體伺服器設定一個名稱',
33473349
embyConfig: 'Emby 設定',
3350+
zspaceConfig: '極影視 設定',
33483351
jellyfinConfig: 'Jellyfin 設定',
33493352
plexConfig: 'Plex 設定',
33503353
host: '伺服器位址',

src/utils/appDeepLink.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* 通用APP深度链接工具类
3-
* 支持媒体服务器(Plex、Jellyfin、Emby)和豆瓣的APP跳转和网页跳转
3+
* 支持媒体服务器(Plex、Jellyfin、Emby、极影视、飞牛影视)和豆瓣的APP跳转和网页跳转
44
*
55
* 深度链接格式参考:
66
* - Plex: https://forums.plex.tv/t/plex-mobile-app-deep-linking/123456
@@ -12,7 +12,7 @@
1212
import { isMobileDevice, isIOSDevice, isAndroidDevice } from '@/@core/utils'
1313

1414
// APP类型
15-
export type AppType = 'plex' | 'jellyfin' | 'emby' | 'trimemedia' | 'douban'
15+
export type AppType = 'plex' | 'jellyfin' | 'emby' | 'zspace' | 'trimemedia' | 'douban'
1616

1717
// 深度链接配置
1818
interface DeepLinkConfig {
@@ -38,6 +38,11 @@ const DEEP_LINK_CONFIGS: Record<AppType, DeepLinkConfig> = {
3838
webUrl: 'https://emby.media',
3939
timeout: 2000,
4040
},
41+
zspace: {
42+
appScheme: 'emby://',
43+
webUrl: 'https://www.zspace.com.cn',
44+
timeout: 2000,
45+
},
4146
trimemedia: {
4247
appScheme: 'trimemedia://',
4348
webUrl: 'https://trimemedia.com',
@@ -135,6 +140,9 @@ function buildDeepLinkUrl(appType: AppType, params: string | DoubanAppParams): s
135140
case 'emby':
136141
return buildEmbyDeepLink(params as string)
137142

143+
case 'zspace':
144+
return buildEmbyDeepLink(params as string)
145+
138146
case 'trimemedia':
139147
return buildTrimemediaDeepLink(params as string)
140148

@@ -634,7 +642,7 @@ export async function openMediaServerWithAutoDetect(
634642
// 优先使用传入的 serverType 参数
635643
if (serverType) {
636644
const type = serverType.toLowerCase()
637-
if (type === 'plex' || type === 'jellyfin' || type === 'emby' || type === 'trimemedia') {
645+
if (type === 'plex' || type === 'jellyfin' || type === 'emby' || type === 'zspace' || type === 'trimemedia') {
638646
detectedServerType = type as AppType
639647
}
640648
}
@@ -649,6 +657,8 @@ export async function openMediaServerWithAutoDetect(
649657
detectedServerType = 'jellyfin'
650658
} else if (url.includes('emby')) {
651659
detectedServerType = 'emby'
660+
} else if (url.includes('zspace')) {
661+
detectedServerType = 'zspace'
652662
}
653663
}
654664

@@ -698,6 +708,8 @@ export function getAppDownloadUrl(appType: AppType): string {
698708
return 'https://jellyfin.org/downloads/'
699709
case 'emby':
700710
return 'https://emby.media/download.html'
711+
case 'zspace':
712+
return 'https://www.zspace.com.cn/'
701713
case 'trimemedia':
702714
return 'https://trimemedia.com/download'
703715
case 'douban':

0 commit comments

Comments
 (0)