vue3 下拉刷新
<script setup lang="ts">
import { Empty } from 'ant-design-vue';
const props = withDefaults(defineProps<{
modelValue: any[] // 重要: 外部在使用这个的时候,不要修改,要通过endSuccess这些方法来修改
defaultPageSize: number
defaultPage: number
}>(), {
modelValue: () => [],
defaultPageSize: 10,
defaultPage: 1,
});
const emit = defineEmits<{
(e: 'update:modelValue', val: any[]): void
(e: 'load', val: { page: number, pageSize: number }): void
}>();
const simpleImage = Empty.PRESENTED_IMAGE_SIMPLE;
const dataSource = ref<any[]>([]);
const page = ref(props.defaultPage);
const pageSize = ref(props.defaultPageSize);
const noMoreData = ref(false); // 是否有更多数据
const loading = ref(false); // 是否正在加载中
let lockFlag = false; // 锁,用于保证一次加载只能调用一次回调方法
watch(() => props.modelValue, () => {
dataSource.value = props.modelValue || [];
}, { immediate: true });
onMounted(() => {
// dataSource.value = [];
// page.value = props.defaultPage;
// pageSize.value = props.defaultPageSize;
// noMoreData.value = false;
// loading.value = false;
nextTick(() => {
lockFlag = false;
emit('load', { page: page.value, pageSize: pageSize.value });
});
});
/**
* 加载更多
*/
function loadMore() {
if (noMoreData.value) {
return;
}
if (loading.value) {
return;
}
loading.value = true;
lockFlag = false;
emit('load', { page: page.value, pageSize: pageSize.value });
}
function endSuccess(data: any[]) {
if (lockFlag) {
return;
}
lockFlag = true;
if (page.value === 1) {
dataSource.value = data;
}
else {
dataSource.value = [...dataSource.value, ...data];
}
if (data.length < pageSize.value) {
noMoreData.value = true;
}
else {
noMoreData.value = false;
page.value += 1;
}
emit('update:modelValue', [...dataSource.value]);
loading.value = false;
}
function endError() {
if (lockFlag) {
return;
}
lockFlag = true;
loading.value = false;
}
function reload() {
if (loading.value && page.value === props.defaultPage) {
return;
}
dataSource.value = [];
page.value = props.defaultPage;
pageSize.value = props.defaultPageSize;
noMoreData.value = false;
loading.value = false;
emit('update:modelValue', []);
lockFlag = false;
emit('load', { page: page.value, pageSize: pageSize.value });
}
defineExpose({
endSuccess,
endError,
reload,
});
</script>
<template>
<div class="loadmore-list">
<ScrollLoad class="loadmore-list-body" @load-more="loadMore">
<div v-if="!dataSource.length">
<a-empty :image="simpleImage" />
</div>
<template v-else>
<slot />
</template>
</ScrollLoad>
</div>
</template>
<style lang="less" scoped>
.loadmore-list {
width: 100%;
height: 100%;
overflow: hidden;
.loadmore-list-body {
width: 100%;
height: 100%;
// overflow: auto;
overflow-x:hidden;
overflow-y:auto;
}
}
</style>
<script setup lang="ts"> import loadMoreList from '@/views/components/loadMoreList.vue'; import eventsave from "./eventsave.vue"; import { TYPE, LEVEL, STATUS, levleText, imgUrl } from './enums.ts' const props = defineProps({ isupdata: { type: Boolean, default: false } }); watch(() => props.isupdata, () => { if (props.isupdata) { _getEventPageQuery() } }, { deep: true }); const list: any = ref([ ]) const formpramas = ref({ pageQueryDTO: { currentPage: 1, pageSize: 3, districtCode: '', typ: '', level: '' } }) const loadMoreListRef = ref() const emit = defineEmits(['detail', 'listfirst', 'leftupdata']); function _getEventPageQuery() { getEventPageQuery(formpramas.value).then(res => { if (res.success) { let d = res.data?.records || []; if (d && d.length > 0) { (window as any).cMap.glowWayline.addRiskBillboard(d); } if (d && d.length) { d.forEach((item) => { item.title = levleText(item.level) item.imgUrl = imgUrl(item.type) }) // list.value = d; loadMoreListRef.value.endSuccess(d); emit('listfirst', list.value[0]) } } else { loadMoreListRef.value.endError(); } }) } //详情 function detail(item: any) { emit('detail', item) } //加载更多 function getList(pageConfig: { page: number, pageSize: number }) { formpramas.value.pageQueryDTO.currentPage = pageConfig.page; formpramas.value.pageQueryDTO.pageSize = pageConfig.pageSize; _getEventPageQuery() } const eventsaveRef = ref(); //应急救援告警接收 function add() { eventsaveRef.value.show(); } function getsaveupdata() { //保存成功了 emit('leftupdata') } </script> <template> <div class="w-full h-full"> <div class="tt-text" @click="add"> <span>应急救援告警接收</span> </div> <div class="list-box h-full"> <loadMoreList ref="loadMoreListRef" v-model="list" @load="getList" :default-page-size="3" :default-page="1"> <div class="sub" v-for="item in list" @click="detail(item)"> <div class="tit"> <span class="s-text"> <img :src="item.imgUrl" alt=""> {{ TYPE[item.type] }} </span> <span class="s-status" :class="`color${item.level}`"> {{ LEVEL[item.level] }} <a-tooltip placement="right" :title="item.title" v-if="item.level"> <PubSvgIcon name="wenhao" size="12" class="cursor-pointer ml-0.5" /> </a-tooltip> </span> </div> <div class="cont"> <div class="cont-sub mt-[6px] justify-between"> <div> 关联飞行计划: </div> <div> <a-tooltip placement="right" :title="item.planName"> <span>{{ item.planName }}</span> </a-tooltip> </div> <div> <span :class="`color${item.status}`"> {{ STATUS[item.status] }} </span> </div> </div> <div class="cont-sub"> <div> 事故发生时间: </div> <div> {{ item.accidentTime }} </div> </div> <div class="cont-sub"> <div> 事故地点: </div> <div class="hidd-cla"> <a-tooltip placement="right" :title="item.place"> <span>{{ item.place }}</span> </a-tooltip> </div> </div> <div class="cont-sub"> <div> 管理单位: </div> <div> {{ item.orgName }} </div> </div> </div> </div> </loadMoreList> </div> <!-- 保存应急救援告警接收 --> <eventsave ref="eventsaveRef" @saveupdata="getsaveupdata"></eventsave> </div> </template> <style lang="less" scoped> .tt-text { position: absolute; right: 0; top: -4px; background: url(@/assets/images/rescue/left2-titbg.png)no-repeat center center; background-size: 100% 100%; width: 130px; // height: 24px; line-height: 24px; text-align: center; cursor: pointer; span { font-family: youshe; font-size: 14px; color: #FFFFFF; text-align: center; text-shadow: 0 0 8px #46B5FF; } } .list-box { overflow-y: auto; overflow-x: hidden; // overflow: hidden; .sub { padding: 10px 10px 12px 16px; background: url(@/assets/images/rescue/left2-listsub-bg.png)no-repeat center center; background-size: 100% 100%; width: 344px; height: 158px; margin-bottom: 9px; cursor: pointer; .tit { display: flex; justify-content: space-between; height: 21px; .s-text { display: flex; align-items: center; img { width: 15px; height: 15px; margin-right: 5px; } font-family: youshe; font-size: 16px; color: #FFFFFF; text-shadow: 0 2px 4px #21538480; } .s-status { font-family: PingFangSC-Regular; font-weight: 400; font-size: 12px; color: #FFFFFF; text-align: center; display: flex; width: 50px; height: 20px; border-radius: 4px; align-items: center; justify-content: center; &.color1 { background-image: radial-gradient(circle at 13% 20%, #93ffec99 0%, #39f1ff00 38%), linear-gradient(248deg, #4decff1a 0%, #00efffcc 100%); box-shadow: inset 6px -6px 8px 0 #40fff652; } &.color2 { background-image: radial-gradient(circle at 13% 20%, #FFD293 0%, #ffa83900 38%), linear-gradient(248deg, #ff9b4d1a 0%, #FF9600 100%); box-shadow: inset 6px -6px 8px 0 #ff404052; } &.color3 { background-image: radial-gradient(circle at 13% 20%, #FF9393 0%, #ff393900 38%), linear-gradient(248deg, #ff4d4d1a 0%, #D70000 100%); box-shadow: inset 6px -6px 8px 0 #ff404052; } } } .cont { height: 112px; .cont-sub { display: flex; font-family: PingFangSC-Regular; font-weight: 400; font-size: 14px; margin-bottom: 4px; // height: 20px; line-height: 20px; // justify-content: space-between; div:nth-of-type(1) { // width: 98px; color: #F7F7F7; } div:nth-of-type(2) { width: 160px; color: #ffffffb3; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; text-overflow: ellipsis; } div:nth-of-type(3) { span { font-family: PingFangSC-Regular; font-weight: 400; font-size: 12px; color: #FFFFFF; text-align: center; display: flex; width: 50px; height: 20px; border-radius: 4px; align-items: center; justify-content: center; &.color1 { background-image: radial-gradient(circle at 13% 20%, #FF9393 0%, #ff393900 38%), linear-gradient(248deg, #ff4d4d1a 0%, #D70000 100%); box-shadow: inset 6px -6px 8px 0 #ff404052; } &.color2 { background-image: radial-gradient(circle at 13% 20%, #FFD293 0%, #ffa83900 38%), linear-gradient(248deg, #ff9b4d1a 0%, #FF9600 100%); box-shadow: inset 6px -6px 8px 0 #ff404052; } &.color3 { background-image: radial-gradient(circle at 13% 20%, #93ffec99 0%, #39f1ff00 38%), linear-gradient(248deg, #4decff1a 0%, #00efffcc 100%); box-shadow: inset 6px -6px 8px 0 #40fff652; } } } .hidd-cla { width: 180px !important; -webkit-line-clamp: 1 !important; } } } } } </style>