Files
satori/pages/gallery.vue

146 lines
5.1 KiB
Vue

<template lang="pug">
.flex.flex-col
// 上传图像按钮悬浮在右上角
.fixed.top-1.flex.flex-row.items-center.justify-center.h-16.px-4.bg-gray-100(
class="rounded-full left-3/4"
v-if="account.online"
)
.flex.flex-row.items-center.justify-center.gap-1
label.text-gray-500.text-sm.font-bold.px-2.py-1.bg-gray-200.rounded-md.cursor-pointer(
for="file"
) 上传图片
input#file.hidden(type="file", accept="image/*", multiple="multiple", @change="upload")
.flex-1.flex.flex-col.justify-center.items-center.text-center
.text-gray-500.text-sm.font-bold.px-2.py-1.bg-gray-200.rounded-md.cursor-pointer(
@click="refresh"
) 刷新
.relative.mt-24.transition-opacity.duration-700.ease-in-out(
ref="PUB",
v-if="!pending",
:class="{ 'opacity-100': !pending, 'opacity-10': pending }"
)
.absolute.transition-all.duration-700.ease-in-out.left-0.top-2000.bg-gray-100(
v-for="item in data.list" :key="item.image",
:data-w="item.width",
:data-h="item.height",
class="hover:bg-gray-200"
)
NuxtLink(:to="`/gallery/${item.id}`")
//img.w-full(:src="`${item.image}?w=${WIDTH}`" loading="lazy")
img.w-full(:src="item.image+'@w480.webp'" loading="lazy")
.absolute.top-0.left-0.right-0.text-white.overflow-hidden.break-words.pb-4(
style="background: linear-gradient(to top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.25))"
)
p.p-2 {{ item.width }} x {{ item.height }}
// 删除按钮
.absolute.top-0.right-0.flex.flex-row.items-center.justify-center.px-2.bg-gray-100(
class="rounded-full cursor-pointer opacity-0 transition-all ease-in-out duration-300 hover:opacity-100"
@click.stop="remove(item.id)"
v-if="account.online"
) 删除
RouterView
</template>
<script setup>
const { data, pending, refresh } = useFetch("/api/gallery?page=1&pageSize=40")
const PUB = ref(null)
const WIDTH = ref(320)
const account = useState('account')
const upload = async event => {
let body = new FormData()
for (let file of event.target.files) body.append("image", file)
await $fetch(`/api/gallery`, { method: "POST", body }).then(rest => {
data.value.list.unshift(...rest.list)
})
}
const remove = async id => {
await $fetch(`/api/gallery/${id}`, { method: "DELETE" }).then(rest => {
const index = data.value.list.findIndex(item => item.id === id)
if (index !== -1) data.value.list.splice(index, 1)
})
}
const 屏幕宽高重置 = () => {
let 容器宽度 = document.body.clientWidth
let 高分屏 = window.devicePixelRatio === 1 && 容器宽度 > 1280
let 列宽 = 高分屏 ? 480 : 320
let 间距 = 高分屏 ? 16 : 8
let 列数 = parseInt(容器宽度 / (列宽 + 间距)) || 1
let 边距 = (容器宽度 - 列数 * 列宽 - (列数 - 1) * 间距) / 2
let 各列高度 = new Array(列数).fill(0)
Array.from(PUB.value?.children ?? []).forEach((item, index) => {
let 最低 = Math.min(...各列高度)
let 列号 = 各列高度.indexOf(最低)
let 位置 = (列宽 + 间距) * 列号 + 边距
let 元素宽 = parseInt(item.getAttribute("data-w"))
let 元素高 = parseInt(item.getAttribute("data-h"))
let 缩放比 = 元素宽 / 列宽
let 缩放高 = parseInt(元素高 / 缩放比)
item.style.top = 最低 + "px"
item.style.left = 位置 + "px"
item.style.width = 列宽 + "px"
item.style.height = 缩放高 + "px"
item.style.transitionDelay = `${index * 40}ms`
各列高度[列号] += 缩放高 + 间距
})
if (PUB.value) PUB.value.style.height = Math.max(...各列高度) + "px"
WIDTH.value = 列宽
};
const disabled = ref(false); // 上锁
const inadvance = ref(400); // 距离
const page = ref(3); // 页码
//const nextPage = () => {
// fetch(`/api/text?page=${page.value}`).then((res) => {
// page.value = page.value + 1;
// disabled.value = false;
// if (res.status === 200) {
// res.json().then((rest) => {
// console.log(rest);
// rest.list.forEach((item) => {
// if (!item.width || !item.height) {
// console.log("没有宽高");
// let img = new Image();
// img.src = item.image;
// img.onload = () => {
// console.log("width:" + img.width + ",height:" + img.height);
// item.width = img.width;
// item.height = img.height;
// };
// }
// });
// data.value.list = data.value.list.concat(rest.list);
// });
// }
// });
//};
const handleScroll = () => {
if (disabled.value) return;
const { scrollHeight, scrollTop, clientHeight } = document.documentElement;
if (scrollHeight - scrollTop - clientHeight <= inadvance.value) {
console.log("scroll to bottom");
disabled.value = true; // 加载期间上锁
inadvance.value = 1280; // 加高判定值使卡顿感减弱
//nextPage();
}
}
onBeforeUnmount(() => {
document.removeEventListener("scroll", handleScroll)
})
onMounted(() => {
屏幕宽高重置()
window.onresize = 屏幕宽高重置
document.addEventListener("scroll", handleScroll)
})
onUpdated(() => {
屏幕宽高重置()
})
</script>