mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-07-10 23:13:20 +08:00
style: Update DownloaderCard and MediaServerCard to improve UI consistency
This commit is contained in:
@@ -120,7 +120,7 @@ onUnmounted(() => {
|
||||
<VIcon class="cursor-move" icon="mdi-drag" />
|
||||
</IconBtn>
|
||||
</span>
|
||||
<VCardText class="flex justify-space-between align-center gap-3">
|
||||
<VCardText class="flex justify-space-between align-center gap-4">
|
||||
<div class="align-self-start">
|
||||
<div class="flex items-center">
|
||||
<VBadge
|
||||
@@ -130,11 +130,14 @@ onUnmounted(() => {
|
||||
color="success"
|
||||
class="me-1"
|
||||
/>
|
||||
<span class="text-h6 mb-1">{{ downloader.name }}</span>
|
||||
<span class="text-h6">{{ downloader.name }}</span>
|
||||
</div>
|
||||
<div class="text-body-1 mt-5 flex flex-wrap text-sm" v-if="props.downloader.enabled">
|
||||
<span class="me-2">{{ `↑ ${formatFileSize(upload_rate, 1)}/s ` }}</span>
|
||||
<span>{{ `↓ ${formatFileSize(download_rate, 1)}/s` }}</span>
|
||||
</div>
|
||||
<div class="text-body-1 mb-3" v-if="props.downloader.enabled">{{ getSpeedText }}</div>
|
||||
</div>
|
||||
<VImg :src="getIcon" cover class="mt-10" max-width="4rem" />
|
||||
<VImg :src="getIcon" cover class="mt-7" max-width="3rem" />
|
||||
</VCardText>
|
||||
</VCard>
|
||||
<VDialog v-model="downloaderInfoDialog" scrollable max-width="40rem">
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { MediaServerConf } from '@/api/types'
|
||||
import { MediaServerConf, MediaStatistic } from '@/api/types'
|
||||
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 api from '@/api'
|
||||
|
||||
// 定义输入
|
||||
const props = defineProps({
|
||||
@@ -15,6 +16,25 @@ const props = defineProps({
|
||||
// 定义触发的自定义事件
|
||||
const emit = defineEmits(['close', 'change'])
|
||||
|
||||
// 媒体统计数据
|
||||
const infoItems = ref([
|
||||
{
|
||||
avatar: 'mdi-movie-roll',
|
||||
title: '电影',
|
||||
amount: '0',
|
||||
},
|
||||
{
|
||||
avatar: 'mdi-television-box',
|
||||
title: '电视剧',
|
||||
amount: '0',
|
||||
},
|
||||
{
|
||||
avatar: 'mdi-account',
|
||||
title: '用户',
|
||||
amount: '0',
|
||||
},
|
||||
])
|
||||
|
||||
// 媒体服务器详情弹窗
|
||||
const mediaServerInfoDialog = ref(false)
|
||||
|
||||
@@ -59,6 +79,43 @@ const getIcon = computed(() => {
|
||||
function onClose() {
|
||||
emit('close')
|
||||
}
|
||||
|
||||
// 调用API加载媒体统计数据
|
||||
async function loadMediaStatistic() {
|
||||
try {
|
||||
const res: MediaStatistic = await api.get('dashboard/statistic', {
|
||||
params: {
|
||||
name: props.mediaserver.name,
|
||||
},
|
||||
})
|
||||
|
||||
if (res) {
|
||||
infoItems.value = [
|
||||
{
|
||||
avatar: 'mdi-movie-roll',
|
||||
title: '电影',
|
||||
amount: res.movie_count.toLocaleString(),
|
||||
},
|
||||
{
|
||||
avatar: 'mdi-television-box',
|
||||
title: '电视剧',
|
||||
amount: res.tv_count.toLocaleString(),
|
||||
},
|
||||
{
|
||||
avatar: 'mdi-account',
|
||||
title: '用户',
|
||||
amount: res.user_count.toLocaleString(),
|
||||
},
|
||||
]
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadMediaStatistic()
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
@@ -67,9 +124,13 @@ function onClose() {
|
||||
<VCardText class="flex justify-space-between align-center gap-3">
|
||||
<div class="align-self-start">
|
||||
<div class="text-h6 mb-1">{{ mediaserver.name }}</div>
|
||||
<div class="text-body-1 mb-3"></div>
|
||||
<div class="text-body-1 mt-5 flex flex-wrap">
|
||||
<span v-for="item in infoItems" :key="item.title" class="me-2 mb-1">
|
||||
<VIcon rounded :icon="item.avatar" class="me-1" />{{ item.amount }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<VImg :src="getIcon" cover class="mt-5 me-7" max-width="4rem" />
|
||||
<VImg :src="getIcon" cover class="mt-5 me-3" max-width="4rem" />
|
||||
</VCardText>
|
||||
</VCard>
|
||||
<VDialog v-model="mediaServerInfoDialog" scrollable max-width="40rem">
|
||||
|
||||
@@ -32,6 +32,16 @@ const notificationInfo = ref<NotificationConf>({
|
||||
config: {},
|
||||
})
|
||||
|
||||
// 各通知类型的名称字典
|
||||
const notificationTypeNames: { [key: string]: string } = {
|
||||
wechat: '企业微信',
|
||||
telegram: 'Telegram',
|
||||
vocechat: 'VoceChat',
|
||||
synologychat: 'Synology Chat',
|
||||
slack: 'Slack',
|
||||
webpush: 'WebPush',
|
||||
}
|
||||
|
||||
// 打开详情弹窗
|
||||
function openNotificationInfoDialog() {
|
||||
notificationInfo.value = props.notification
|
||||
@@ -77,10 +87,13 @@ function onClose() {
|
||||
<DialogCloseBtn @click="onClose" />
|
||||
<VCardText class="flex justify-space-between align-center gap-3">
|
||||
<div class="align-self-start">
|
||||
<h5 class="text-h6 mb-1">{{ notification.name }}</h5>
|
||||
<div class="text-body-1 mb-3">{{ notification.type }}</div>
|
||||
<div class="flex items-center">
|
||||
<VBadge v-if="props.notification.enabled" dot inline color="success" class="me-1" />
|
||||
<span class="text-h6">{{ props.notification.name }}</span>
|
||||
</div>
|
||||
<div class="text-body-1 mb-3">{{ notificationTypeNames[notification.type] }}</div>
|
||||
</div>
|
||||
<VImg :src="getIcon" cover class="mt-5 me-7" max-width="4rem" />
|
||||
<VImg :src="getIcon" cover class="mt-5 me-7" max-width="3rem" />
|
||||
</VCardText>
|
||||
</VCard>
|
||||
<VDialog v-model="notificationInfoDialog" scrollable max-width="40rem">
|
||||
|
||||
Reference in New Issue
Block a user