Commit 5c798291 authored by shirlyn.guo's avatar shirlyn.guo 🤡

chore: 推荐模板优化

parent 0dc81b62
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted, ref, watch, useTemplateRef, watchEffect } from 'vue' import { computed, onMounted, ref, watch, useTemplateRef } from 'vue'
import TemplatePreviewModal from './template-preview-modal.vue' import TemplatePreviewModal from './template-preview-modal.vue'
import { useScroll } from '@vueuse/core' import { useScroll } from '@vueuse/core'
import { DigitalTemplate, TemplateType } from '@/store/types/template' import { DigitalTemplate, TemplateType } from '@/store/types/template'
...@@ -20,8 +20,10 @@ const router = useRouter() ...@@ -20,8 +20,10 @@ const router = useRouter()
const previewModalVisible = ref(false) const previewModalVisible = ref(false)
const selectedTemplate = ref<DigitalTemplate>({} as DigitalTemplate) const selectedTemplate = ref<DigitalTemplate>({} as DigitalTemplate)
const checkedClassifyValue = ref('') const checkedClassifyValue = ref('')
const templateList = ref<DigitalTemplate[]>([])
const newTemplateList = ref<(DigitalTemplate & { position: { top: number; left: number } })[]>([]) const templateList = ref<(DigitalTemplate & { position?: { top: number; left: number } })[]>([])
const alreadyCountPositionsList: { id: number; top: number; left: number; height: number; columnIndex: number }[] = []
const pagingInfo = ref({ const pagingInfo = ref({
pageNo: 1, pageNo: 1,
totalPages: 1, totalPages: 1,
...@@ -30,9 +32,8 @@ const pagingInfo = ref({ ...@@ -30,9 +32,8 @@ const pagingInfo = ref({
}) })
const columnHeights = ref<number[]>([]) const columnHeights = ref<number[]>([])
const waterfallHeight = ref(900) const waterfallHeight = ref(900)
const templateClassifyIsLoading = ref(false) const templateClassifyIsLoading = ref(true)
const templateBottomIsLoading = ref(false) const templateBottomIsLoading = ref(false)
const smooth = ref(false) const smooth = ref(false)
const behavior = computed(() => (smooth.value ? 'smooth' : 'auto')) const behavior = computed(() => (smooth.value ? 'smooth' : 'auto'))
...@@ -48,14 +49,16 @@ const templateClassify = [ ...@@ -48,14 +49,16 @@ const templateClassify = [
watch(checkedClassifyValue, () => { watch(checkedClassifyValue, () => {
templateClassifyIsLoading.value = true templateClassifyIsLoading.value = true
templateList.value = [] templateList.value = []
newTemplateList.value = []
pagingInfo.value.pageNo = 1 pagingInfo.value.pageNo = 1
alreadyCountPositionsList.length = 0
columnHeights.value = Array(6).fill(0) columnHeights.value = Array(6).fill(0)
getTemplateList(true) getTemplateList(true)
}) })
watchEffect(() => { watch(
() => arrivedState.bottom,
() => {
if (arrivedState.bottom && !templateBottomIsLoading.value) { if (arrivedState.bottom && !templateBottomIsLoading.value) {
if (pagingInfo.value.pageNo < pagingInfo.value.totalPages) { if (pagingInfo.value.pageNo < pagingInfo.value.totalPages) {
templateBottomIsLoading.value = true templateBottomIsLoading.value = true
...@@ -63,7 +66,8 @@ watchEffect(() => { ...@@ -63,7 +66,8 @@ watchEffect(() => {
getTemplateList() getTemplateList()
} }
} }
}) },
)
onMounted(() => { onMounted(() => {
getTemplateList(true) getTemplateList(true)
...@@ -76,50 +80,84 @@ async function getTemplateList(refresh = false) { ...@@ -76,50 +80,84 @@ async function getTemplateList(refresh = false) {
} }
fetchDigitalHumanTemplateStatusList<DigitalTemplate[]>(checkedClassifyValue.value, pagingInfo.value) fetchDigitalHumanTemplateStatusList<DigitalTemplate[]>(checkedClassifyValue.value, pagingInfo.value)
.then((res) => { .then(async (res) => {
if (res.code !== 0) return if (res.code !== 0) return
templateList.value = refresh ? res.data : [...templateList.value, ...res.data] templateList.value = refresh ? res.data : [...templateList.value, ...res.data]
return calculatePositions(templateList.value).then((positions) => { templateClassifyIsLoading.value = false
newTemplateList.value = templateList.value.map((template, index) => ({ const newTemplateList = res.data
...template, const newTemplateListPositions = await calculatePositions(newTemplateList, alreadyCountPositionsList)
position: positions[index],
}))
pagingInfo.value = res.pagingInfo as PagingInfo templateList.value = templateList.value.map((template) => {
const itemWithNoPosition = newTemplateList.find((item) => item.id === template.id)
if (itemWithNoPosition) {
return {
...template,
position: newTemplateListPositions[newTemplateList.indexOf(itemWithNoPosition)],
}
}
return template
}) })
pagingInfo.value = res.pagingInfo as PagingInfo
}) })
.finally(() => { .finally(() => {
templateClassifyIsLoading.value = false
templateBottomIsLoading.value = false templateBottomIsLoading.value = false
arrivedState.bottom = false
}) })
} }
async function calculatePositions(templates: any[]) {
const columnHeights = Array(6).fill(0)
const positions: { top: any; left: number; height: unknown }[] = []
const heightPromises = templates.map(async (template) => { async function calculatePositions(
return await calculateImageHeight(template) templates: any[],
alreadyPositionsList: { id: number; top: number; left: number; height: number }[],
) {
const columnWidths = 170
const columnHeights = Array(6).fill(0)
const positions: { id: number; top: number; left: number; height: number; columnIndex: number }[] = []
const imgHeights = await Promise.all(
templates.map(async (template) => ({
id: template.id,
imgHeight: await calculateImageHeight(template),
})),
)
alreadyPositionsList.forEach((pos) => {
const columnIndex = Math.floor(pos.left / columnWidths)
columnHeights[columnIndex] = Math.max(columnHeights[columnIndex], pos.top + 20 + pos.height)
}) })
const imgHeights = await Promise.all(heightPromises) imgHeights.forEach(({ id, imgHeight }) => {
const minColumnIndex = getMinColumnHeight(columnHeights)
imgHeights.forEach((imgHeight) => {
const minColumnIndex = getMincColumnHeight(columnHeights)
const itemTop = columnHeights[minColumnIndex] const itemTop = columnHeights[minColumnIndex]
let itemLeft = minColumnIndex * 170 const itemLeft = minColumnIndex * columnWidths + minColumnIndex * 20
if (itemLeft !== 0) itemLeft += 20
if (itemLeft === 360) itemLeft += 20
if (itemLeft === 530) itemLeft += 40
if (itemLeft === 700) itemLeft += 60
if (itemLeft === 870) itemLeft += 80
columnHeights[minColumnIndex] += imgHeight + 20 columnHeights[minColumnIndex] += imgHeight + 20
waterfallHeight.value = Math.max(...columnHeights) waterfallHeight.value = Math.max(...columnHeights)
positions.push({ top: itemTop, left: itemLeft, height: imgHeight }) positions.push({ id, top: itemTop, left: itemLeft, height: imgHeight, columnIndex: minColumnIndex })
})
alreadyCountPositionsList.push(...positions)
const columnMap = new Map<number, { id: number; top: number; left: number; height: number; totalValue: number }[]>()
alreadyCountPositionsList.forEach(({ id, top, left, height, columnIndex }) => {
if (!columnMap.has(columnIndex)) {
columnMap.set(columnIndex, [])
}
columnMap.get(columnIndex)?.push({ id, top, left, height, totalValue: top + height })
})
alreadyCountPositionsList.length = 0
columnMap.forEach((items, columnIndex) => {
const maxItem = items.reduce((prev, current) => (prev.totalValue > current.totalValue ? prev : current))
alreadyCountPositionsList.push({
id: maxItem.id,
top: maxItem.top,
left: maxItem.left,
height: maxItem.height,
columnIndex,
})
}) })
return positions return positions
...@@ -134,6 +172,11 @@ function calculateImageHeight(template: { videoParams: { width: number; height: ...@@ -134,6 +172,11 @@ function calculateImageHeight(template: { videoParams: { width: number; height:
}) })
} }
function getMinColumnHeight(arr: number[]) {
let min = Math.min(...arr)
return arr.indexOf(min)
}
function handleOpenPreviewModal(template: DigitalTemplate) { function handleOpenPreviewModal(template: DigitalTemplate) {
if (template) { if (template) {
selectedTemplate.value = { ...template } selectedTemplate.value = { ...template }
...@@ -141,11 +184,6 @@ function handleOpenPreviewModal(template: DigitalTemplate) { ...@@ -141,11 +184,6 @@ function handleOpenPreviewModal(template: DigitalTemplate) {
} }
} }
function getMincColumnHeight(arr: number[]) {
let min = Math.min(...arr)
return arr.indexOf(min)
}
function handleToCreation(template: DigitalTemplate) { function handleToCreation(template: DigitalTemplate) {
router.push({ router.push({
name: 'Creation', name: 'Creation',
...@@ -153,6 +191,7 @@ function handleToCreation(template: DigitalTemplate) { ...@@ -153,6 +191,7 @@ function handleToCreation(template: DigitalTemplate) {
}) })
} }
</script> </script>
<template> <template>
<div class="sticky top-0 z-10 mx-auto mt-[16px] min-h-[900px] overscroll-contain rounded-t-[16px] bg-white"> <div class="sticky top-0 z-10 mx-auto mt-[16px] min-h-[900px] overscroll-contain rounded-t-[16px] bg-white">
<div class="sticky top-[-1px] z-10 rounded-t-[16px] bg-white px-[24px] pb-[16px] pt-[24px]"> <div class="sticky top-[-1px] z-10 rounded-t-[16px] bg-white px-[24px] pb-[16px] pt-[24px]">
...@@ -179,10 +218,10 @@ function handleToCreation(template: DigitalTemplate) { ...@@ -179,10 +218,10 @@ function handleToCreation(template: DigitalTemplate) {
class="page-main relative h-auto min-h-[900px] w-full" class="page-main relative h-auto min-h-[900px] w-full"
:style="{ height: waterfallHeight + 'px' }" :style="{ height: waterfallHeight + 'px' }"
> >
<div v-for="item in templateList" :key="item.id">
<div <div
v-for="item in newTemplateList" v-if="item.position"
:key="item.id" :style="{ position: 'absolute', top: item.position!.top + 'px', left: item.position!.left + 'px' }"
:style="{ position: 'absolute', top: item.position.top + 'px', left: item.position.left + 'px' }"
> >
<n-card class="mb-[20px] box-content w-[170px] overflow-hidden"> <n-card class="mb-[20px] box-content w-[170px] overflow-hidden">
<template #cover> <template #cover>
...@@ -211,6 +250,7 @@ function handleToCreation(template: DigitalTemplate) { ...@@ -211,6 +250,7 @@ function handleToCreation(template: DigitalTemplate) {
</n-card> </n-card>
</div> </div>
</div> </div>
</div>
<div class="flex justify-center"> <div class="flex justify-center">
<n-spin v-show="templateClassifyIsLoading" size="large" /> <n-spin v-show="templateClassifyIsLoading" size="large" />
</div> </div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment