mcwl-pc/app/components/PictureList.vue

258 lines
7.0 KiB
Vue

<template>
<div class="flex flex-wrap w-full">
<div class="grid grid-cols-2 lg:grid-cols-4 xl:grid-cols-5 2xl:grid-cols-7 gap-4 p-4">
<div
v-for="item in dataList"
:key="item.id"
@click="onEditPicture(item)"
class="relative rounded-lg overflow-hidden"
>
<!-- 图片 -->
<div class="relative border border-solid border-[#e5e7eb] h-[300px] overflow-hidden rounded-lg group">
<img
:src="item.imagePaths"
class="w-full h-full object-cover rounded-lg cursor-pointer"
alt=""
/>
<div
class="px-2 py-1 absolute top-0 left-0 w-full h-full hidden group-hover:block bg-black bg-opacity-40 cursor-pointer"
>
<div class="flex justify-between w-full">
<div class="flex mt-2">
<div class="w-5 h-5 border border-white mr-2 rounded-full">
<img :src="item.avatar" class="w-full h-full rounded-full" alt="" />
</div>
<span class="text-sm text-white truncate">{{ item.nickName }}</span>
</div>
<div class="p-2 rounded-full bg-white flex items-center cursor-pointer">
<n-icon
class="mr-2"
size="20"
:color="item.isLike === 0 ? '#ccc' : '#ff0000'"
@click.stop="onLike(item)"
>
<Heart />
</n-icon>
{{ item.likeNum }}
</div>
</div>
</div>
<!-- 左上角标签 -->
<!-- <div
class="absolute top-2 left-2 bg-black/50 text-white text-xs px-2 py-1 rounded"
>
{{ item.type }}
</div> -->
<!-- 底部数据统计 -->
<!-- <div
class="absolute bottom-0 left-0 right-0 flex items-center gap-2 p-2 text-xs text-white"
>
<div class="flex items-center">
<component :is="Play" class="h-[14px] w-[14px] text-white menu-icon m-1" />
{{ item.reals || 0 }}
</div>
<div class="flex items-center">
<component
:is="Download"
class="h-[14px] w-[14px] text-white menu-icon m-1"
/>
{{ item.numbers || 0 }}
</div>
</div> -->
</div>
<!-- 作者信息条 -->
<!-- <div class="mt-1 px-2 py-1">
<div>
{{ item.modelName }}
</div>
<div class="flex mt-2">
<img :src="item.avatar" class="w-5 h-5 rounded-full mr-2" alt="" />
<span class="text-sm text-gray-500 truncate">{{ item.nickName }}</span>
</div>
</div> -->
</div>
</div>
<div class="w-full flex justify-center" v-if="!loading && dataList.length === 0">
<Empty></Empty>
</div>
<div
ref="loadingTrigger"
class="h-20 w-full text-center text-gray-500 flex justify-center items-center"
>
<div v-if="loading">加载中...</div>
<div v-if="finished && dataList.length >= 20">没有更多数据了</div>
</div>
<NConfigProvider>
<NMessageProvider>
<div v-if="isShowEditorPicture">
<PictureDetail @close-editor-picture="closeEditorPicture" ref="editUserInfoRef" :item="currentPicture" @update-like="updateLike"/>
</div>
</NMessageProvider>
</NConfigProvider>
</div>
</template>
<script setup lang="ts">
import { Heart } from "@vicons/ionicons5";
import { NConfigProvider, NMessageProvider } from "naive-ui";
const emit = defineEmits(['imageTotal'])
import { nextTick, onMounted, onUnmounted, ref } from "vue";
const loading = ref(false);
const finished = ref(false);
const total = ref(0); //
const loadingTrigger = ref(null);
const observer = ref<IntersectionObserver | null>(null);
const message = useMessage();
const props = defineProps({
params: {
type: Object,
default: () => {},
},
});
const listParams = ref({
...props.params,
pageNumber: 1,
pageSize: 20,
});
function initPageNUm() {
listParams.value.pageNumber = 1;
finished.value = false; // 重置加载完成状态
listParams.value = Object.assign({}, listParams.value, props.params);
getDataList();
}
const dataList = ref([]);
async function getDataList() {
if (loading.value || finished.value) return;
loading.value = true;
try {
const res = await request.get("/image/imageList", { ...listParams.value });
if (res.code === 200) {
// 如果是第一页,直接赋值,否则追加数据
if (listParams.value.pageNumber === 1) {
dataList.value = res.data.list;
} else {
dataList.value = [...dataList.value, ...res.data.list];
}
total.value = res.data.total; // 假设接口返回了总条数
// 判断是否加载完所有数据
if (dataList.value.length >= total.value) {
finished.value = true;
}
// 自动增加页码
listParams.value.pageNumber++;
emit('imageTotal', total.value)
}
} catch (err) {
dataList.value = [];
finished.value = true;
console.log(err);
} finally {
loading.value = false;
}
}
getDataList();
onMounted(() => {
window.addEventListener("scroll", topedRefresh);
observer.value = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting && !loading.value && !finished.value) {
getDataList();
}
},
{
threshold: 0.1,
}
);
if (loadingTrigger.value) {
observer.value.observe(loadingTrigger.value);
}
});
onUnmounted(() => {
window.removeEventListener("scroll", topedRefresh);
if (observer.value) {
observer.value.disconnect();
}
});
async function topedRefresh() {
if (import.meta.client) {
await nextTick();
window.scrollTo({
top: 0,
behavior: "smooth",
});
}
initPageNUm();
}
async function onLike(item: any) {
try {
const res = await request.get(`/image/imageLike?id=${item.id}`);
if (res.code === 200) {
if (item.isLike === 1) {
item.isLike = 0;
item.likeNum -= 1;
message.success("取消点赞成功");
} else {
item.isLike = 1;
item.likeNum += 1;
message.success("点赞成功");
}
}
} catch (err) {
console.log(err);
}
}
// 显示图片的编辑
const currentPicture = ref({})
const isShowEditorPicture = ref(false)
interface EditUserInfoType {
isVisible: boolean
}
const editUserInfoRef = ref<EditUserInfoType | null>(null)
function onEditPicture(item:any) {
currentPicture.value = item
isShowEditorPicture.value = true
nextTick(()=>{
if(editUserInfoRef.value){
editUserInfoRef.value.isVisible = true
}
})
}
function closeEditorPicture(){
isShowEditorPicture.value = false
}
function updateLike(type:number){
// if (props.item.isLike === 1) {
// props.item.isLike = 0;
// props.item.likeNum -= 1;
// } else {
// props.item.isLike = 1;
// props.item.likeNum += 1;
// }
}
defineExpose({
initPageNUm,
});
</script>
<style scoped></style>