mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-05-31 13:21:01 +08:00
统一图标导入方式
This commit is contained in:
@@ -4,9 +4,7 @@ import { formatFileSize } from '@/@core/utils/formatters'
|
||||
import { DownloaderConf } from '@/api/types'
|
||||
import { useToast } from 'vue-toastification'
|
||||
import type { DownloaderInfo } from '@/api/types'
|
||||
import qbittorrent_image from '@images/logos/qbittorrent.png'
|
||||
import transmission_image from '@images/logos/transmission.png'
|
||||
import custom_image from '@images/logos/downloader.png'
|
||||
import { getLogoUrl } from '@/utils/imageUtils'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { downloaderDict } from '@/api/constants'
|
||||
@@ -128,11 +126,11 @@ function saveDownloaderInfo() {
|
||||
const getIcon = computed(() => {
|
||||
switch (props.downloader.type) {
|
||||
case 'qbittorrent':
|
||||
return qbittorrent_image
|
||||
return getLogoUrl('qbittorrent')
|
||||
case 'transmission':
|
||||
return transmission_image
|
||||
return getLogoUrl('transmission')
|
||||
default:
|
||||
return custom_image
|
||||
return getLogoUrl('downloader')
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { MediaServerLibrary } from '@/api/types'
|
||||
import plex from '@images/misc/plex.png'
|
||||
import emby from '@images/misc/emby.png'
|
||||
import jellyfin from '@images/misc/jellyfin.png'
|
||||
import trimemedia from '@images/logos/trimemedia.png'
|
||||
import { getLogoUrl } from '@/utils/imageUtils'
|
||||
import { openMediaServerWithAutoDetect } from '@/utils/appDeepLink'
|
||||
|
||||
// 输入参数
|
||||
@@ -40,7 +40,7 @@ function getDefaultImage() {
|
||||
if (props.media?.server_type === 'plex') return plex
|
||||
else if (props.media?.server_type === 'emby') return emby
|
||||
else if (props.media?.server_type === 'jellyfin') return jellyfin
|
||||
else if (props.media?.server_type === 'trimemedia') return trimemedia
|
||||
else if (props.media?.server_type === 'trimemedia') return getLogoUrl('trimemedia')
|
||||
else return plex
|
||||
}
|
||||
|
||||
@@ -72,11 +72,11 @@ async function drawImages(imageList: string[]) {
|
||||
if (!canvas) return getDefaultImage()
|
||||
|
||||
// 画布参数
|
||||
const POSTER_WIDTH = (canvas.width - 40) / 4 // 左右边框8px + 3个间隔24px = 40px
|
||||
const POSTER_HEIGHT = 256 // 上方海报高256
|
||||
const MARGIN_WIDTH = 8 // 左右间隔为8
|
||||
const MARGIN_HEIGHT = 4 // 海报和倒影之间的间隔为4
|
||||
const REFLECTION_HEIGHT = canvas.height - POSTER_HEIGHT - MARGIN_HEIGHT // 下方倒影使用剩余全部高度
|
||||
const POSTER_WIDTH = (canvas.width - 40) / 4 // 左右边框8px + 3个间隔24px = 40px
|
||||
const POSTER_HEIGHT = 256 // 上方海报高256
|
||||
const MARGIN_WIDTH = 8 // 左右间隔为8
|
||||
const MARGIN_HEIGHT = 4 // 海报和倒影之间的间隔为4
|
||||
const REFLECTION_HEIGHT = canvas.height - POSTER_HEIGHT - MARGIN_HEIGHT // 下方倒影使用剩余全部高度
|
||||
|
||||
// 获取画布上下文
|
||||
const ctx = canvas.getContext('2d')
|
||||
@@ -107,30 +107,20 @@ async function drawImages(imageList: string[]) {
|
||||
}
|
||||
|
||||
const x = MARGIN_WIDTH * index + POSTER_WIDTH * (index - 1)
|
||||
const y = 0 // 海报紧贴顶部
|
||||
const y = 0 // 海报紧贴顶部
|
||||
|
||||
ctx.drawImage(img, x, y, POSTER_WIDTH, POSTER_HEIGHT)
|
||||
|
||||
ctx.save()
|
||||
ctx.translate(0, canvas.height)
|
||||
ctx.scale(1, -1)
|
||||
ctx.drawImage(
|
||||
img,
|
||||
0,
|
||||
0,
|
||||
img.width,
|
||||
img.height,
|
||||
x,
|
||||
0,
|
||||
POSTER_WIDTH,
|
||||
REFLECTION_HEIGHT,
|
||||
)
|
||||
ctx.drawImage(img, 0, 0, img.width, img.height, x, 0, POSTER_WIDTH, REFLECTION_HEIGHT)
|
||||
|
||||
const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height - (POSTER_HEIGHT + MARGIN_HEIGHT))
|
||||
|
||||
gradient.addColorStop(0, 'rgba(0, 0, 0, 1)')
|
||||
gradient.addColorStop(1, 'rgba(0, 0, 0, 0.7)')
|
||||
ctx.globalCompositeOperation = 'destination-out';
|
||||
ctx.globalCompositeOperation = 'destination-out'
|
||||
ctx.fillStyle = gradient
|
||||
ctx.fillRect(x, 0, POSTER_WIDTH, REFLECTION_HEIGHT)
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
<script lang="ts" setup>
|
||||
import noImage from '@images/no-image.jpeg'
|
||||
import tmdbImage from '@images/logos/tmdb.png'
|
||||
import doubanImage from '@images/logos/douban-black.png'
|
||||
import bangumiImage from '@images/logos/bangumi.png'
|
||||
import { getLogoUrl } from '@/utils/imageUtils'
|
||||
import api from '@/api'
|
||||
import { useToast } from 'vue-toastification'
|
||||
import { formatSeason, formatRating } from '@/@core/utils/formatters'
|
||||
@@ -64,9 +62,9 @@ const seasonsSelected = ref<MediaSeason[]>([])
|
||||
|
||||
// 来源角标字典
|
||||
const sourceIconDict: { [key: string]: any } = {
|
||||
themoviedb: tmdbImage,
|
||||
douban: doubanImage,
|
||||
bangumi: bangumiImage,
|
||||
themoviedb: getLogoUrl('tmdb'),
|
||||
douban: getLogoUrl('douban-black'),
|
||||
bangumi: getLogoUrl('bangumi'),
|
||||
}
|
||||
|
||||
// 绑定MediaCard元素
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { MediaServerConf, MediaServerLibrary, MediaStatistic } from '@/api/types'
|
||||
import { useToast } from 'vue-toastification'
|
||||
import emby_image from '@images/logos/emby.png'
|
||||
import jellyfin_image from '@images/logos/jellyfin.png'
|
||||
import plex_image from '@images/logos/plex.png'
|
||||
import trimemedia_image from '@images/logos/trimemedia.png'
|
||||
import custom_image from '@images/logos/mediaserver.png'
|
||||
import { getLogoUrl } from '@/utils/imageUtils'
|
||||
import api from '@/api'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
@@ -109,15 +105,15 @@ function saveMediaServerInfo() {
|
||||
const getIcon = computed(() => {
|
||||
switch (props.mediaserver.type) {
|
||||
case 'emby':
|
||||
return emby_image
|
||||
return getLogoUrl('emby')
|
||||
case 'jellyfin':
|
||||
return jellyfin_image
|
||||
return getLogoUrl('jellyfin')
|
||||
case 'trimemedia':
|
||||
return trimemedia_image
|
||||
return getLogoUrl('trimemedia')
|
||||
case 'plex':
|
||||
return plex_image
|
||||
return getLogoUrl('plex')
|
||||
default:
|
||||
return custom_image
|
||||
return getLogoUrl('mediaserver')
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { NotificationConf } from '@/api/types'
|
||||
import wechat_image from '@images/logos/wechat.png'
|
||||
import telegram_image from '@images/logos/telegram.webp'
|
||||
import vocechat_image from '@images/logos/vocechat.png'
|
||||
import synologychat_image from '@images/logos/synologychat.png'
|
||||
import slack_image from '@images/logos/slack.webp'
|
||||
import chrome_image from '@images/logos/chrome.png'
|
||||
import custom_image from '@images/logos/notification.png'
|
||||
import { getLogoUrl } from '@/utils/imageUtils'
|
||||
import { useToast } from 'vue-toastification'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
@@ -99,19 +93,19 @@ function saveNotificationInfo() {
|
||||
const getIcon = computed(() => {
|
||||
switch (props.notification.type) {
|
||||
case 'wechat':
|
||||
return wechat_image
|
||||
return getLogoUrl('wechat')
|
||||
case 'telegram':
|
||||
return telegram_image
|
||||
return getLogoUrl('telegram')
|
||||
case 'vocechat':
|
||||
return vocechat_image
|
||||
return getLogoUrl('vocechat')
|
||||
case 'synologychat':
|
||||
return synologychat_image
|
||||
return getLogoUrl('synologychat')
|
||||
case 'slack':
|
||||
return slack_image
|
||||
return getLogoUrl('slack')
|
||||
case 'webpush':
|
||||
return chrome_image
|
||||
return getLogoUrl('chrome')
|
||||
default:
|
||||
return custom_image
|
||||
return getLogoUrl('notification')
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useToast } from 'vue-toastification'
|
||||
import VersionHistory from '../misc/VersionHistory.vue'
|
||||
import api from '@/api'
|
||||
import type { Plugin } from '@/api/types'
|
||||
import noImage from '@images/logos/plugin.png'
|
||||
import { getLogoUrl } from '@/utils/imageUtils'
|
||||
import { getDominantColor } from '@/@core/utils/image'
|
||||
import { isNullOrEmptyObject } from '@/@core/utils'
|
||||
import ProgressDialog from '@/components/dialog/ProgressDialog.vue'
|
||||
@@ -103,7 +103,7 @@ async function installPlugin() {
|
||||
|
||||
// 计算图标路径
|
||||
const iconPath: Ref<string> = computed(() => {
|
||||
if (imageLoadError.value) return noImage
|
||||
if (imageLoadError.value) return getLogoUrl('plugin')
|
||||
// 如果是网络图片则使用代理后返回
|
||||
if (props.plugin?.plugin_icon?.startsWith('http'))
|
||||
return `${import.meta.env.VITE_API_BASE_URL}system/img/1?imgurl=${encodeURIComponent(
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useConfirm } from '@/composables/useConfirm'
|
||||
import api from '@/api'
|
||||
import type { Plugin } from '@/api/types'
|
||||
import { isNullOrEmptyObject } from '@core/utils'
|
||||
import noImage from '@images/logos/plugin.png'
|
||||
import { getLogoUrl } from '@/utils/imageUtils'
|
||||
import { getDominantColor } from '@/@core/utils/image'
|
||||
import VersionHistory from '@/components/misc/VersionHistory.vue'
|
||||
import ProgressDialog from '../dialog/ProgressDialog.vue'
|
||||
@@ -167,7 +167,7 @@ async function showPluginConfig() {
|
||||
|
||||
// 计算图标路径
|
||||
const iconPath: Ref<string> = computed(() => {
|
||||
if (imageLoadError.value) return noImage
|
||||
if (imageLoadError.value) return getLogoUrl('plugin')
|
||||
// 如果是网络图片则使用代理后返回
|
||||
if (props.plugin?.plugin_icon?.startsWith('http'))
|
||||
return `${import.meta.env.VITE_API_BASE_URL}system/img/1?imgurl=${encodeURIComponent(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from 'vue'
|
||||
import noImage from '@images/logos/site.webp'
|
||||
import { getLogoUrl } from '@/utils/imageUtils'
|
||||
import { useToast } from 'vue-toastification'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import SiteAddEditDialog from '../dialog/SiteAddEditDialog.vue'
|
||||
@@ -62,7 +62,7 @@ async function getSiteIcon() {
|
||||
try {
|
||||
siteIcon.value = (await api.get(`site/icon/${cardProps.site?.id}`)).data.icon
|
||||
if (!siteIcon.value) {
|
||||
siteIcon.value = noImage
|
||||
siteIcon.value = getLogoUrl('site')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import api from '@/api'
|
||||
import type { Plugin } from '@/api/types'
|
||||
import noImage from '@images/logos/plugin.png'
|
||||
import { getLogoUrl } from '@/utils/imageUtils'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRecentPlugins } from '@/composables/useRecentPlugins'
|
||||
import PluginDataDialog from '@/components/dialog/PluginDataDialog.vue'
|
||||
@@ -137,8 +137,8 @@ const componentOpacity = computed(() => {
|
||||
|
||||
// 计算插件图标路径
|
||||
function getPluginIcon(plugin: Plugin): string {
|
||||
if (!plugin.plugin_icon) return noImage
|
||||
if (pluginIconLoadError.value[plugin.id]) return noImage
|
||||
if (!plugin.plugin_icon) return getLogoUrl('plugin')
|
||||
if (pluginIconLoadError.value[plugin.id]) return getLogoUrl('plugin')
|
||||
|
||||
// 如果是网络图片则使用代理后返回
|
||||
if (plugin?.plugin_icon?.startsWith('http'))
|
||||
|
||||
@@ -1233,7 +1233,7 @@ export default {
|
||||
apiTokenLength: 'API Token must be at least 16 characters',
|
||||
githubToken: 'Github Token',
|
||||
githubTokenFormat: 'ghp_**** or github_pat_****',
|
||||
githubTokenHint: 'Used to increase the rate limit threshold when plugins access Github API',
|
||||
githubTokenHint: 'Used to increase the rate limit threshold when plugins access Github API,it is recommended to configure, otherwise plugins may not work properly',
|
||||
ocrHost: 'OCR Server',
|
||||
ocrHostHint: 'Used for site check-in, updating site cookies and other captcha recognition',
|
||||
advancedSettings: 'Advanced Settings',
|
||||
@@ -2943,7 +2943,7 @@ export default {
|
||||
recognizeSource: 'Recognize Source',
|
||||
recognizeSourceHint: 'Set the default media info recognition data source',
|
||||
apiToken: 'API Token',
|
||||
apiTokenHint: 'System automatically generated API access token',
|
||||
apiTokenHint: 'API Token required for accessing MoviePilot API, please record it for subsequent use',
|
||||
currentUserHint: 'Current user, cannot be modified',
|
||||
passwordOptionalHint: 'Leave blank to keep current password',
|
||||
confirmPasswordHint: 'Confirm new password',
|
||||
|
||||
@@ -1229,7 +1229,7 @@ export default {
|
||||
apiTokenLength: 'API Token不得低于16位',
|
||||
githubToken: 'Github Token',
|
||||
githubTokenFormat: 'ghp_**** 或 github_pat_****',
|
||||
githubTokenHint: '用于提高插件等访问Github API时的限流阈值',
|
||||
githubTokenHint: '用于提高插件等访问Github API时的限流阈值,建议配置,否则插件可能无法正常使用',
|
||||
ocrHost: '验证码识别服务器',
|
||||
ocrHostHint: '用于站点签到、更新站点Cookie等识别验证码',
|
||||
advancedSettings: '高级设置',
|
||||
@@ -2930,7 +2930,7 @@ export default {
|
||||
recognizeSource: '识别数据源',
|
||||
recognizeSourceHint: '设置默认媒体信息识别数据源',
|
||||
apiToken: 'API 令牌',
|
||||
apiTokenHint: '系统自动生成的 API 访问令牌',
|
||||
apiTokenHint: '访问MoviePilot API 需要的访问令牌,请记录下来以便后续使用',
|
||||
currentUserHint: '当前用户,不可修改',
|
||||
passwordOptionalHint: '留空表示不修改密码',
|
||||
confirmPasswordHint: '确认新密码',
|
||||
|
||||
@@ -1217,7 +1217,7 @@ export default {
|
||||
apiTokenLength: 'API Token不得低於16位',
|
||||
githubToken: 'Github Token',
|
||||
githubTokenFormat: 'ghp_**** 或 github_pat_****',
|
||||
githubTokenHint: '用於提高插件等訪問Github API時的限流閾值',
|
||||
githubTokenHint: '用於提高插件等訪問Github API時的限流閾值,建議配置,否則插件可能無法正常使用',
|
||||
ocrHost: '驗證碼識別服務器',
|
||||
ocrHostHint: '用於站點簽到、更新站點Cookie等識別驗證碼',
|
||||
advancedSettings: '高級設置',
|
||||
@@ -2898,7 +2898,7 @@ export default {
|
||||
recognizeSource: '識別資料來源',
|
||||
recognizeSourceHint: '設定預設媒體資訊識別資料來源',
|
||||
apiToken: 'API 權杖',
|
||||
apiTokenHint: '系統自動產生的 API 存取權杖',
|
||||
apiTokenHint: '訪問MoviePilot API 需要的訪問令牌,請記錄下來以便後續使用',
|
||||
currentUserHint: '目前使用者,不可修改',
|
||||
passwordOptionalHint: '留空表示不修改密碼',
|
||||
confirmPasswordHint: '確認新密碼',
|
||||
|
||||
84
src/utils/imageUtils.ts
Normal file
84
src/utils/imageUtils.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* 静态资源导入工具函数
|
||||
* 用于在生产环境中正确引用静态资源
|
||||
*/
|
||||
|
||||
// 导入所有 logo 图标
|
||||
import qbittorrentLogo from '@/assets/images/logos/qbittorrent.png'
|
||||
import transmissionLogo from '@/assets/images/logos/transmission.png'
|
||||
import embyLogo from '@/assets/images/logos/emby.png'
|
||||
import jellyfinLogo from '@/assets/images/logos/jellyfin.png'
|
||||
import plexLogo from '@/assets/images/logos/plex.png'
|
||||
import trimemediaLogo from '@/assets/images/logos/trimemedia.png'
|
||||
import wechatLogo from '@/assets/images/logos/wechat.png'
|
||||
import telegramLogo from '@/assets/images/logos/telegram.webp'
|
||||
import slackLogo from '@/assets/images/logos/slack.webp'
|
||||
import synologychatLogo from '@/assets/images/logos/synologychat.png'
|
||||
import vocechatLogo from '@/assets/images/logos/vocechat.png'
|
||||
import downloaderLogo from '@/assets/images/logos/downloader.png'
|
||||
import mediaserverLogo from '@/assets/images/logos/mediaserver.png'
|
||||
import notificationLogo from '@/assets/images/logos/notification.png'
|
||||
import chromeLogo from '@/assets/images/logos/chrome.png'
|
||||
import doubanLogo from '@/assets/images/logos/douban.png'
|
||||
import githubLogo from '@/assets/images/logos/github.png'
|
||||
import tmdbLogo from '@/assets/images/logos/tmdb.png'
|
||||
import fanartLogo from '@/assets/images/logos/fanart.webp'
|
||||
import pythonLogo from '@/assets/images/logos/python.png'
|
||||
import pluginLogo from '@/assets/images/logos/plugin.png'
|
||||
import siteLogo from '@/assets/images/logos/site.webp'
|
||||
import bangumiLogo from '@/assets/images/logos/bangumi.png'
|
||||
import doubanBlackLogo from '@/assets/images/logos/douban-black.png'
|
||||
|
||||
// 图标映射表
|
||||
const logoMap: Record<string, string> = {
|
||||
qbittorrent: qbittorrentLogo,
|
||||
transmission: transmissionLogo,
|
||||
emby: embyLogo,
|
||||
jellyfin: jellyfinLogo,
|
||||
plex: plexLogo,
|
||||
trimemedia: trimemediaLogo,
|
||||
wechat: wechatLogo,
|
||||
telegram: telegramLogo,
|
||||
slack: slackLogo,
|
||||
synologychat: synologychatLogo,
|
||||
vocechat: vocechatLogo,
|
||||
downloader: downloaderLogo,
|
||||
mediaserver: mediaserverLogo,
|
||||
notification: notificationLogo,
|
||||
chrome: chromeLogo,
|
||||
douban: doubanLogo,
|
||||
github: githubLogo,
|
||||
tmdb: tmdbLogo,
|
||||
fanart: fanartLogo,
|
||||
python: pythonLogo,
|
||||
plugin: pluginLogo,
|
||||
site: siteLogo,
|
||||
bangumi: bangumiLogo,
|
||||
'douban-black': doubanBlackLogo,
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图标 URL
|
||||
* @param logoName 图标名称
|
||||
* @returns 图标的 URL
|
||||
*/
|
||||
export function getLogoUrl(logoName: string): string {
|
||||
return logoMap[logoName] || ''
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有可用的图标名称
|
||||
* @returns 图标名称数组
|
||||
*/
|
||||
export function getAvailableLogos(): string[] {
|
||||
return Object.keys(logoMap)
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查图标是否存在
|
||||
* @param logoName 图标名称
|
||||
* @returns 是否存在
|
||||
*/
|
||||
export function hasLogo(logoName: string): boolean {
|
||||
return logoName in logoMap
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import api from '@/api'
|
||||
import type { Plugin } from '@/api/types'
|
||||
import NoDataFound from '@/components/NoDataFound.vue'
|
||||
import PluginAppCard from '@/components/cards/PluginAppCard.vue'
|
||||
import noImage from '@images/logos/plugin.png'
|
||||
import { getLogoUrl } from '@/utils/imageUtils'
|
||||
import { useDisplay } from 'vuetify'
|
||||
import { isNullOrEmptyObject } from '@/@core/utils'
|
||||
import { getPluginTabs } from '@/router/i18n-menu'
|
||||
@@ -675,7 +675,7 @@ function pluginIconError(item: Plugin) {
|
||||
// 插件图标地址
|
||||
function pluginIcon(item: Plugin) {
|
||||
// 如果图片加载错误
|
||||
if (pluginIconLoaded.value[item.id || '0'] === false) return noImage
|
||||
if (pluginIconLoaded.value[item.id || '0'] === false) return getLogoUrl('plugin')
|
||||
// 如果是网络图片则使用代理后返回
|
||||
if (item?.plugin_icon?.startsWith('http'))
|
||||
return `${import.meta.env.VITE_API_BASE_URL}system/img/1?imgurl=${encodeURIComponent(item?.plugin_icon)}&cache=true`
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useSetupWizard } from '@/composables/useSetupWizard'
|
||||
import { getLogoUrl } from '@/utils/imageUtils'
|
||||
|
||||
const { t } = useI18n()
|
||||
const { wizardData, selectDownloader, validationErrors } = useSetupWizard()
|
||||
@@ -34,7 +35,7 @@ const { wizardData, selectDownloader, validationErrors } = useSetupWizard()
|
||||
@click="selectDownloader('qbittorrent')"
|
||||
>
|
||||
<VCardText class="text-center">
|
||||
<VImg src="/src/assets/images/logos/qbittorrent.png" height="48" width="48" class="mx-auto mb-2" />
|
||||
<VImg :src="getLogoUrl('qbittorrent')" height="48" width="48" class="mx-auto mb-2" />
|
||||
<div class="text-h6">qBittorrent</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
@@ -47,7 +48,7 @@ const { wizardData, selectDownloader, validationErrors } = useSetupWizard()
|
||||
@click="selectDownloader('transmission')"
|
||||
>
|
||||
<VCardText class="text-center">
|
||||
<VImg src="/src/assets/images/logos/transmission.png" height="48" width="48" class="mx-auto mb-2" />
|
||||
<VImg :src="getLogoUrl('transmission')" height="48" width="48" class="mx-auto mb-2" />
|
||||
<div class="text-h6">Transmission</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useSetupWizard } from '@/composables/useSetupWizard'
|
||||
import api from '@/api'
|
||||
import { getLogoUrl } from '@/utils/imageUtils'
|
||||
|
||||
const { t } = useI18n()
|
||||
const { wizardData, selectMediaServer, validationErrors } = useSetupWizard()
|
||||
@@ -96,7 +97,7 @@ watch(
|
||||
@click="selectMediaServerWithLibrary('emby')"
|
||||
>
|
||||
<VCardText class="text-center">
|
||||
<VImg src="/src/assets/images/logos/emby.png" height="48" width="48" class="mx-auto mb-2" />
|
||||
<VImg :src="getLogoUrl('emby')" height="48" width="48" class="mx-auto mb-2" />
|
||||
<div class="text-h6">Emby</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
@@ -109,7 +110,7 @@ watch(
|
||||
@click="selectMediaServerWithLibrary('jellyfin')"
|
||||
>
|
||||
<VCardText class="text-center">
|
||||
<VImg src="/src/assets/images/logos/jellyfin.png" height="48" width="48" class="mx-auto mb-2" />
|
||||
<VImg :src="getLogoUrl('jellyfin')" height="48" width="48" class="mx-auto mb-2" />
|
||||
<div class="text-h6">Jellyfin</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
@@ -122,7 +123,7 @@ watch(
|
||||
@click="selectMediaServerWithLibrary('plex')"
|
||||
>
|
||||
<VCardText class="text-center">
|
||||
<VImg src="/src/assets/images/logos/plex.png" height="48" width="48" class="mx-auto mb-2" />
|
||||
<VImg :src="getLogoUrl('plex')" height="48" width="48" class="mx-auto mb-2" />
|
||||
<div class="text-h6">Plex</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
@@ -135,7 +136,7 @@ watch(
|
||||
@click="selectMediaServerWithLibrary('trimemedia')"
|
||||
>
|
||||
<VCardText class="text-center">
|
||||
<VImg src="/src/assets/images/logos/trimemedia.png" height="48" width="48" class="mx-auto mb-2" />
|
||||
<VImg :src="getLogoUrl('trimemedia')" height="48" width="48" class="mx-auto mb-2" />
|
||||
<div class="text-h6">飞牛影视</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useSetupWizard } from '@/composables/useSetupWizard'
|
||||
import { getLogoUrl } from '@/utils/imageUtils'
|
||||
|
||||
const { t } = useI18n()
|
||||
const { wizardData, selectNotification, validationErrors } = useSetupWizard()
|
||||
@@ -46,7 +47,7 @@ const notificationTypes = [
|
||||
@click="selectNotification('wechat')"
|
||||
>
|
||||
<VCardText class="text-center">
|
||||
<VImg src="/src/assets/images/logos/wechat.png" height="48" width="48" class="mx-auto mb-2" />
|
||||
<VImg :src="getLogoUrl('wechat')" height="48" width="48" class="mx-auto mb-2" />
|
||||
<div class="text-h6">微信</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
@@ -59,7 +60,7 @@ const notificationTypes = [
|
||||
@click="selectNotification('telegram')"
|
||||
>
|
||||
<VCardText class="text-center">
|
||||
<VImg src="/src/assets/images/logos/telegram.webp" height="48" width="48" class="mx-auto mb-2" />
|
||||
<VImg :src="getLogoUrl('telegram')" height="48" width="48" class="mx-auto mb-2" />
|
||||
<div class="text-h6">Telegram</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
@@ -72,7 +73,7 @@ const notificationTypes = [
|
||||
@click="selectNotification('slack')"
|
||||
>
|
||||
<VCardText class="text-center">
|
||||
<VImg src="/src/assets/images/logos/slack.webp" height="48" width="48" class="mx-auto mb-2" />
|
||||
<VImg :src="getLogoUrl('slack')" height="48" width="48" class="mx-auto mb-2" />
|
||||
<div class="text-h6">Slack</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
@@ -85,7 +86,7 @@ const notificationTypes = [
|
||||
@click="selectNotification('synologychat')"
|
||||
>
|
||||
<VCardText class="text-center">
|
||||
<VImg src="/src/assets/images/logos/synologychat.png" height="48" width="48" class="mx-auto mb-2" />
|
||||
<VImg :src="getLogoUrl('synologychat')" height="48" width="48" class="mx-auto mb-2" />
|
||||
<div class="text-h6">Synology Chat</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
@@ -98,7 +99,7 @@ const notificationTypes = [
|
||||
@click="selectNotification('vocechat')"
|
||||
>
|
||||
<VCardText class="text-center">
|
||||
<VImg src="/src/assets/images/logos/vocechat.png" height="48" width="48" class="mx-auto mb-2" />
|
||||
<VImg :src="getLogoUrl('vocechat')" height="48" width="48" class="mx-auto mb-2" />
|
||||
<div class="text-h6">VoceChat</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import api from '@/api'
|
||||
import douban from '@images/logos/douban.png'
|
||||
import github from '@images/logos/github.png'
|
||||
import slack from '@images/logos/slack.webp'
|
||||
import telegram from '@images/logos/telegram.webp'
|
||||
import tmdb from '@images/logos/tmdb.png'
|
||||
import wechat from '@images/logos/wechat.png'
|
||||
import fanart from '@images/logos/fanart.webp'
|
||||
import { getLogoUrl } from '@/utils/imageUtils'
|
||||
import tvdb from '@images/logos/thetvdb.jpeg'
|
||||
import python from '@images/logos/python.png'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 国际化
|
||||
@@ -36,7 +29,7 @@ interface Address {
|
||||
// 测试集
|
||||
const targets = ref<Address[]>([
|
||||
{
|
||||
image: tmdb,
|
||||
image: getLogoUrl('tmdb'),
|
||||
name: 'api.themoviedb.org',
|
||||
url: 'https://api.themoviedb.org/3/movie/550?api_key={TMDBAPIKEY}',
|
||||
proxy: true,
|
||||
@@ -46,7 +39,7 @@ const targets = ref<Address[]>([
|
||||
btndisable: false,
|
||||
},
|
||||
{
|
||||
image: tmdb,
|
||||
image: getLogoUrl('tmdb'),
|
||||
name: 'api.tmdb.org',
|
||||
url: 'https://api.tmdb.org/3/movie/550?api_key={TMDBAPIKEY}',
|
||||
proxy: true,
|
||||
@@ -56,7 +49,7 @@ const targets = ref<Address[]>([
|
||||
btndisable: false,
|
||||
},
|
||||
{
|
||||
image: tmdb,
|
||||
image: getLogoUrl('tmdb'),
|
||||
name: 'www.themoviedb.org',
|
||||
url: 'https://www.themoviedb.org',
|
||||
proxy: true,
|
||||
@@ -76,7 +69,7 @@ const targets = ref<Address[]>([
|
||||
btndisable: false,
|
||||
},
|
||||
{
|
||||
image: fanart,
|
||||
image: getLogoUrl('fanart'),
|
||||
name: 'webservice.fanart.tv',
|
||||
url: 'https://webservice.fanart.tv',
|
||||
proxy: true,
|
||||
@@ -86,7 +79,7 @@ const targets = ref<Address[]>([
|
||||
btndisable: false,
|
||||
},
|
||||
{
|
||||
image: telegram,
|
||||
image: getLogoUrl('telegram'),
|
||||
name: 'api.telegram.org',
|
||||
url: 'https://api.telegram.org',
|
||||
proxy: true,
|
||||
@@ -96,7 +89,7 @@ const targets = ref<Address[]>([
|
||||
btndisable: false,
|
||||
},
|
||||
{
|
||||
image: wechat,
|
||||
image: getLogoUrl('wechat'),
|
||||
name: 'qyapi.weixin.qq.com',
|
||||
url: 'https://qyapi.weixin.qq.com/cgi-bin/gettoken',
|
||||
proxy: false,
|
||||
@@ -106,7 +99,7 @@ const targets = ref<Address[]>([
|
||||
btndisable: false,
|
||||
},
|
||||
{
|
||||
image: douban,
|
||||
image: getLogoUrl('douban'),
|
||||
name: 'frodo.douban.com',
|
||||
url: 'https://frodo.douban.com',
|
||||
proxy: false,
|
||||
@@ -116,7 +109,7 @@ const targets = ref<Address[]>([
|
||||
btndisable: false,
|
||||
},
|
||||
{
|
||||
image: slack,
|
||||
image: getLogoUrl('slack'),
|
||||
name: 'slack.com',
|
||||
url: 'https://slack.com',
|
||||
proxy: false,
|
||||
@@ -126,7 +119,7 @@ const targets = ref<Address[]>([
|
||||
btndisable: false,
|
||||
},
|
||||
{
|
||||
image: python,
|
||||
image: getLogoUrl('python'),
|
||||
name: 'pypi.org',
|
||||
url: '{PIP_PROXY}rsa/',
|
||||
proxy: true,
|
||||
@@ -137,7 +130,7 @@ const targets = ref<Address[]>([
|
||||
include: 'pypi:repository-version',
|
||||
},
|
||||
{
|
||||
image: github,
|
||||
image: getLogoUrl('github'),
|
||||
name: 'github.com',
|
||||
url: '{GITHUB_PROXY}https://github.com/jxxghp/MoviePilot/blob/v2/README.md',
|
||||
proxy: true,
|
||||
@@ -148,7 +141,7 @@ const targets = ref<Address[]>([
|
||||
include: 'MoviePilot',
|
||||
},
|
||||
{
|
||||
image: github,
|
||||
image: getLogoUrl('github'),
|
||||
name: 'codeload.github.com',
|
||||
url: 'https://codeload.github.com',
|
||||
proxy: true,
|
||||
@@ -158,7 +151,7 @@ const targets = ref<Address[]>([
|
||||
btndisable: false,
|
||||
},
|
||||
{
|
||||
image: github,
|
||||
image: getLogoUrl('github'),
|
||||
name: 'api.github.com',
|
||||
url: 'https://api.github.com',
|
||||
proxy: true,
|
||||
@@ -168,7 +161,7 @@ const targets = ref<Address[]>([
|
||||
btndisable: false,
|
||||
},
|
||||
{
|
||||
image: github,
|
||||
image: getLogoUrl('github'),
|
||||
name: 'raw.githubusercontent.com',
|
||||
url: '{GITHUB_PROXY}https://raw.githubusercontent.com/jxxghp/MoviePilot/v2/README.md',
|
||||
proxy: true,
|
||||
@@ -188,7 +181,7 @@ const resolveStatusColor: Status = {
|
||||
}
|
||||
|
||||
const abortControllers = new Set<AbortController>()
|
||||
const isUnmounting = ref(false);
|
||||
const isUnmounting = ref(false)
|
||||
|
||||
// 调用API测试网络连接
|
||||
async function netTest(index: number) {
|
||||
@@ -229,17 +222,16 @@ async function netTest(index: number) {
|
||||
|
||||
// 加载时测试所有连接
|
||||
onMounted(async () => {
|
||||
isUnmounting.value = false;
|
||||
for (let i = 0; !isUnmounting.value && i < targets.value.length; i++)
|
||||
await netTest(i)
|
||||
isUnmounting.value = false
|
||||
for (let i = 0; !isUnmounting.value && i < targets.value.length; i++) await netTest(i)
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
isUnmounting.value = true;
|
||||
isUnmounting.value = true
|
||||
for (const controller of abortControllers) {
|
||||
controller.abort()
|
||||
}
|
||||
abortControllers.clear()
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
Reference in New Issue
Block a user