258 lines
7.0 KiB
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>
|