Commit 4bab7c9a authored by shirlyn.guo's avatar shirlyn.guo 🤡

chore: 推荐模板布局优化

parent 4e2512d2
<script setup lang="ts">
import { computed, onMounted, ref, watch, useTemplateRef } from 'vue'
import { computed, ref, watch, useTemplateRef } from 'vue'
import TemplatePreviewModal from './template-preview-modal.vue'
import { useScroll } from '@vueuse/core'
import { DigitalTemplate, TemplateType } from '@/store/types/template'
......@@ -21,16 +21,13 @@ const previewModalVisible = ref(false)
const selectedTemplate = ref<DigitalTemplate>({} as DigitalTemplate)
const checkedClassifyValue = ref('')
const templateList = ref<(DigitalTemplate & { position?: { top: number; left: number } })[]>([])
const alreadyCountPositionsList: { id: number; top: number; left: number; height: number; columnIndex: number }[] = []
const templateColumnMap = ref(createDefaultDigitalTemplate())
const pagingInfo = ref({
pageNo: 1,
totalPages: 1,
pageSize: 30,
totalRows: 2,
})
const columnHeights = ref<number[]>([])
const waterfallHeight = ref(900)
const templateClassifyIsLoading = ref(true)
const templateBottomIsLoading = ref(false)
......@@ -48,12 +45,9 @@ const templateClassify = [
watch(checkedClassifyValue, () => {
templateClassifyIsLoading.value = true
templateList.value = []
templateColumnMapReset()
pagingInfo.value.pageNo = 1
alreadyCountPositionsList.length = 0
columnHeights.value = Array(6).fill(0)
getTemplateList(true)
getTemplateList()
})
watch(
......@@ -68,37 +62,32 @@ watch(
}
},
)
;(function () {
getTemplateList()
})()
onMounted(() => {
getTemplateList(true)
columnHeights.value = Array(6).fill(0)
})
function createDefaultDigitalTemplate(): { height: number; list: DigitalTemplate[] }[] {
return Array.from({ length: 6 }, () => ({
height: 0,
list: [],
}))
}
async function getTemplateList(refresh = false) {
if (templateBottomIsLoading.value) {
if (templateClassifyIsLoading.value) return
}
function getTemplateList() {
if (templateBottomIsLoading.value && templateClassifyIsLoading.value) return
fetchDigitalHumanTemplateStatusList<DigitalTemplate[]>(checkedClassifyValue.value, pagingInfo.value)
.then(async (res) => {
if (res.code !== 0) return
templateList.value = refresh ? res.data : [...templateList.value, ...res.data]
templateClassifyIsLoading.value = false
const newTemplateList = res.data
const newTemplateListPositions = await calculatePositions(newTemplateList, alreadyCountPositionsList)
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
res.data.forEach((item) => {
templateItemInsertColumn(item)
})
const maxHeight = Math.max(...templateColumnMap.value.map((column) => column.height))
waterfallHeight.value = maxHeight + 20
pagingInfo.value = res.pagingInfo as PagingInfo
})
.finally(() => {
......@@ -106,75 +95,19 @@ async function getTemplateList(refresh = false) {
})
}
async function calculatePositions(
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)
})
imgHeights.forEach(({ id, imgHeight }) => {
const minColumnIndex = getMinColumnHeight(columnHeights)
const itemTop = columnHeights[minColumnIndex]
const itemLeft = minColumnIndex * columnWidths + minColumnIndex * 20
function templateItemInsertColumn(item: DigitalTemplate) {
if (!item.videoParams) return
columnHeights[minColumnIndex] += imgHeight + 20
waterfallHeight.value = Math.max(...columnHeights)
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 }[]>()
const itemHeight = (item.videoParams.height / item.videoParams.width) * 170
const columnHeights = templateColumnMap.value.map((column) => column.height)
const minColumnIndex = columnHeights.indexOf(Math.min(...columnHeights))
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
}
function calculateImageHeight(template: { videoParams: { width: number; height: number } }): Promise<number> {
return new Promise((resolve) => {
const renderWidth = 170
const renderHeight = (template.videoParams.height / template.videoParams.width) * renderWidth
resolve(renderHeight)
})
templateColumnMap.value[minColumnIndex].list.push(item)
templateColumnMap.value[minColumnIndex].height += itemHeight + 20
}
function getMinColumnHeight(arr: number[]) {
let min = Math.min(...arr)
return arr.indexOf(min)
function templateColumnMapReset() {
templateColumnMap.value = createDefaultDigitalTemplate()
}
function handleOpenPreviewModal(template: DigitalTemplate) {
......@@ -215,14 +148,12 @@ function handleToCreation(template: DigitalTemplate) {
>
<div
v-show="!templateClassifyIsLoading"
class="page-main relative h-auto min-h-[900px] w-full"
:style="{ height: waterfallHeight + 'px' }"
>
<div v-for="item in templateList" :key="item.id">
<div
v-if="item.position"
:style="{ position: 'absolute', top: item.position!.top + 'px', left: item.position!.left + 'px' }"
class="page-main relative flex h-auto min-h-[900px] w-full justify-between"
:style="{ height: waterfallHeight + 40 + 'px' }"
>
<div v-for="(column, index) in templateColumnMap" :key="index">
<div v-for="item in column.list" :key="item.id">
<div>
<n-card class="mb-[20px] box-content w-[170px] overflow-hidden">
<template #cover>
<div class="relative flex h-auto w-[170px] items-center justify-center overflow-hidden bg-[#f0f0f0]">
......@@ -251,12 +182,13 @@ function handleToCreation(template: DigitalTemplate) {
</div>
</div>
</div>
</div>
<div class="flex justify-center">
<n-spin v-show="templateClassifyIsLoading" size="large" />
</div>
<div
v-show="pagingInfo.pageNo === pagingInfo.totalPages || pagingInfo.totalPages === 0"
class="mb-[50px] mt-[20px] flex justify-center text-center text-[14px] text-[#a9b4cc]"
class="mb-[50px] mt-[30px] flex justify-center text-center text-[14px] text-[#a9b4cc]"
>
<div class="relative top-[10px] h-[1px] w-[14px] bg-[#a9b4cc]"></div>
<div class="mb-[8px] w-[80px]">已經到底啦</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