mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-09 01:36:45 +08:00
Make dashboard media grids responsive to screen size
This commit is contained in:
@@ -1,4 +1,16 @@
|
|||||||
import { computed, nextTick, onActivated, onMounted, onUnmounted, ref, watch, type ComputedRef, type Ref } from 'vue'
|
import {
|
||||||
|
computed,
|
||||||
|
nextTick,
|
||||||
|
onActivated,
|
||||||
|
onMounted,
|
||||||
|
onUnmounted,
|
||||||
|
ref,
|
||||||
|
toValue,
|
||||||
|
watch,
|
||||||
|
type ComputedRef,
|
||||||
|
type MaybeRefOrGetter,
|
||||||
|
type Ref,
|
||||||
|
} from 'vue'
|
||||||
|
|
||||||
interface DashboardMediaGridCapacityOptions {
|
interface DashboardMediaGridCapacityOptions {
|
||||||
contentSelector?: string
|
contentSelector?: string
|
||||||
@@ -6,7 +18,7 @@ interface DashboardMediaGridCapacityOptions {
|
|||||||
horizontalPadding?: number
|
horizontalPadding?: number
|
||||||
maxCount?: number
|
maxCount?: number
|
||||||
minItemWidth: number
|
minItemWidth: number
|
||||||
rows?: number
|
rows?: MaybeRefOrGetter<number>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DashboardMediaGridCapacityState {
|
interface DashboardMediaGridCapacityState {
|
||||||
@@ -20,7 +32,7 @@ const DEFAULT_DASHBOARD_MEDIA_GRID_GAP = 16
|
|||||||
const DEFAULT_DASHBOARD_MEDIA_GRID_ROWS = 2
|
const DEFAULT_DASHBOARD_MEDIA_GRID_ROWS = 2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据仪表盘媒体卡片容器宽度计算可铺满指定行数的请求数量。
|
* 根据仪表盘媒体卡片容器宽度和响应式行数计算请求数量。
|
||||||
*
|
*
|
||||||
* @param options 网格尺寸参数,需要与实际 ProgressiveCardGrid 参数保持一致
|
* @param options 网格尺寸参数,需要与实际 ProgressiveCardGrid 参数保持一致
|
||||||
* @returns 容器引用、列数、请求数量和手动刷新方法
|
* @returns 容器引用、列数、请求数量和手动刷新方法
|
||||||
@@ -36,7 +48,11 @@ export function useDashboardMediaGridCapacity(options: DashboardMediaGridCapacit
|
|||||||
const safeHorizontalPadding = computed(() => Math.max(0, options.horizontalPadding ?? 0))
|
const safeHorizontalPadding = computed(() => Math.max(0, options.horizontalPadding ?? 0))
|
||||||
const safeMaxCount = computed(() => Math.max(0, Math.floor(options.maxCount ?? Number.POSITIVE_INFINITY)))
|
const safeMaxCount = computed(() => Math.max(0, Math.floor(options.maxCount ?? Number.POSITIVE_INFINITY)))
|
||||||
const safeMinItemWidth = computed(() => Math.max(1, options.minItemWidth))
|
const safeMinItemWidth = computed(() => Math.max(1, options.minItemWidth))
|
||||||
const safeRows = computed(() => Math.max(1, Math.floor(options.rows ?? DEFAULT_DASHBOARD_MEDIA_GRID_ROWS)))
|
const safeRows = computed(() => {
|
||||||
|
const rows = options.rows === undefined ? DEFAULT_DASHBOARD_MEDIA_GRID_ROWS : toValue(options.rows)
|
||||||
|
|
||||||
|
return Math.max(1, Math.floor(rows))
|
||||||
|
})
|
||||||
|
|
||||||
const columnCount = computed(() => {
|
const columnCount = computed(() => {
|
||||||
if (measuredWidth.value <= 0) return 0
|
if (measuredWidth.value <= 0) return 0
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ import PosterCard from '@/components/cards/PosterCard.vue'
|
|||||||
import ProgressiveCardGrid from '@/components/misc/ProgressiveCardGrid.vue'
|
import ProgressiveCardGrid from '@/components/misc/ProgressiveCardGrid.vue'
|
||||||
import { useDashboardMediaGridCapacity } from '@/composables/useDashboardMediaGridCapacity'
|
import { useDashboardMediaGridCapacity } from '@/composables/useDashboardMediaGridCapacity'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { useDisplay } from 'vuetify'
|
||||||
|
|
||||||
// 国际化
|
// 国际化
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
const display = useDisplay()
|
||||||
|
|
||||||
const LATEST_CARD_MIN_WIDTH = 144
|
const LATEST_CARD_MIN_WIDTH = 144
|
||||||
const MEDIA_GRID_HORIZONTAL_PADDING = 40
|
const MEDIA_GRID_HORIZONTAL_PADDING = 40
|
||||||
@@ -18,7 +20,10 @@ const latestList = ref<{ [key: string]: MediaServerPlayItem[] }>({})
|
|||||||
// 所有媒体服务器设置
|
// 所有媒体服务器设置
|
||||||
const mediaServers = ref<MediaServerConf[]>([])
|
const mediaServers = ref<MediaServerConf[]>([])
|
||||||
|
|
||||||
// 最近入库两行网格容量
|
// 小屏幕纵向空间更紧凑,展示三行;桌面端保持两行横向铺满。
|
||||||
|
const mediaGridRows = computed(() => (display.smAndDown.value ? 3 : 2))
|
||||||
|
|
||||||
|
// 最近入库网格容量
|
||||||
const {
|
const {
|
||||||
containerRef: mediaGridContainerRef,
|
containerRef: mediaGridContainerRef,
|
||||||
itemCount: latestItemCount,
|
itemCount: latestItemCount,
|
||||||
@@ -27,6 +32,7 @@ const {
|
|||||||
contentSelector: '.dashboard-media-content',
|
contentSelector: '.dashboard-media-content',
|
||||||
horizontalPadding: MEDIA_GRID_HORIZONTAL_PADDING,
|
horizontalPadding: MEDIA_GRID_HORIZONTAL_PADDING,
|
||||||
minItemWidth: LATEST_CARD_MIN_WIDTH,
|
minItemWidth: LATEST_CARD_MIN_WIDTH,
|
||||||
|
rows: mediaGridRows,
|
||||||
})
|
})
|
||||||
|
|
||||||
let latestLoadId = 0
|
let latestLoadId = 0
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ import PlayingBackdropCard from '@/components/cards/PlayingBackdropCard.vue'
|
|||||||
import ProgressiveCardGrid from '@/components/misc/ProgressiveCardGrid.vue'
|
import ProgressiveCardGrid from '@/components/misc/ProgressiveCardGrid.vue'
|
||||||
import { useDashboardMediaGridCapacity } from '@/composables/useDashboardMediaGridCapacity'
|
import { useDashboardMediaGridCapacity } from '@/composables/useDashboardMediaGridCapacity'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { useDisplay } from 'vuetify'
|
||||||
|
|
||||||
// 国际化
|
// 国际化
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
const display = useDisplay()
|
||||||
|
|
||||||
const PLAYING_CARD_MIN_WIDTH = 240
|
const PLAYING_CARD_MIN_WIDTH = 240
|
||||||
const MEDIA_GRID_HORIZONTAL_PADDING = 40
|
const MEDIA_GRID_HORIZONTAL_PADDING = 40
|
||||||
@@ -18,7 +20,10 @@ const playingList = ref<MediaServerPlayItem[]>([])
|
|||||||
// 所有媒体服务器设置
|
// 所有媒体服务器设置
|
||||||
const mediaServers = ref<MediaServerConf[]>([])
|
const mediaServers = ref<MediaServerConf[]>([])
|
||||||
|
|
||||||
// 继续观看两行网格容量
|
// 小屏幕纵向空间更紧凑,展示三行;桌面端保持两行横向铺满。
|
||||||
|
const mediaGridRows = computed(() => (display.smAndDown.value ? 3 : 2))
|
||||||
|
|
||||||
|
// 继续观看网格容量
|
||||||
const {
|
const {
|
||||||
containerRef: mediaGridContainerRef,
|
containerRef: mediaGridContainerRef,
|
||||||
itemCount: playingItemCount,
|
itemCount: playingItemCount,
|
||||||
@@ -27,6 +32,7 @@ const {
|
|||||||
contentSelector: '.dashboard-media-content',
|
contentSelector: '.dashboard-media-content',
|
||||||
horizontalPadding: MEDIA_GRID_HORIZONTAL_PADDING,
|
horizontalPadding: MEDIA_GRID_HORIZONTAL_PADDING,
|
||||||
minItemWidth: PLAYING_CARD_MIN_WIDTH,
|
minItemWidth: PLAYING_CARD_MIN_WIDTH,
|
||||||
|
rows: mediaGridRows,
|
||||||
})
|
})
|
||||||
|
|
||||||
const displayedPlayingList = computed(() => playingList.value.slice(0, playingItemCount.value))
|
const displayedPlayingList = computed(() => playingList.value.slice(0, playingItemCount.value))
|
||||||
|
|||||||
Reference in New Issue
Block a user