265 lines
6.2 KiB
Vue
265 lines
6.2 KiB
Vue
<template>
|
||
<view class="order-list-container">
|
||
<!-- z-paging组件 -->
|
||
<z-paging
|
||
ref="paging"
|
||
v-model="dataList"
|
||
:refresher-enabled="true"
|
||
:refresher-threshold="45"
|
||
refresher-default-text="下拉刷新"
|
||
refresher-pulling-text="下拉刷新"
|
||
refresher-refreshing-text="正在刷新..."
|
||
refresher-complete-text="刷新完成"
|
||
:loading-more-enabled="true"
|
||
loading-more-default-text="点击加载更多"
|
||
loading-more-loading-text="正在加载..."
|
||
loading-more-no-more-text="没有更多了"
|
||
loading-more-fail-text="加载失败,点击重试"
|
||
:empty-view-text="emptyText"
|
||
:empty-view-img="emptyIcon"
|
||
:auto="false"
|
||
:use-virtual-list="false"
|
||
:virtual-list-height="virtualListHeight"
|
||
:cell-height-mode="cellHeightMode"
|
||
:fixed-height="fixedHeight"
|
||
:safe-area-inset-top="true"
|
||
:use-page-scroll="true"
|
||
:top-offset="120"
|
||
@query="queryList"
|
||
@emptyViewReload="handleEmptyReload"
|
||
>
|
||
<!-- 非虚拟列表模式下的数据渲染 -->
|
||
<view class="order-list-content">
|
||
<OrderCard
|
||
v-for="(item, index) in currentDataList"
|
||
:key="item.id || index"
|
||
:orderData="item"
|
||
@click="handleOrderClick"
|
||
@call="handleOrderCall"
|
||
@complete="handleOrderComplete"
|
||
/>
|
||
</view>
|
||
|
||
<!-- 虚拟列表模式下的数据渲染 -->
|
||
<template #cell="{ item }" v-if="useVirtualList">
|
||
<OrderCard
|
||
:orderData="item"
|
||
@click="handleOrderClick"
|
||
@call="handleOrderCall"
|
||
@complete="handleOrderComplete"
|
||
/>
|
||
</template>
|
||
|
||
<!-- 自定义空状态 -->
|
||
<template #empty v-if="customEmptyView">
|
||
<view class="custom-empty">
|
||
<image :src="emptyIcon" class="empty-icon" />
|
||
<text class="empty-text">{{ emptyText }}</text>
|
||
<button
|
||
class="refresh-btn"
|
||
@click="handleEmptyReload"
|
||
v-if="showRefreshBtn"
|
||
>
|
||
刷新重试
|
||
</button>
|
||
</view>
|
||
</template>
|
||
</z-paging>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, defineProps, watch, onMounted, computed, nextTick } from "vue";
|
||
import OrderCard from "../OrderCard/index.vue";
|
||
|
||
// Props
|
||
const props = defineProps({
|
||
// 工单数据列表
|
||
orderList: {
|
||
type: Array,
|
||
default: () => [],
|
||
},
|
||
// 是否有更多数据
|
||
hasMore: {
|
||
type: Boolean,
|
||
default: true,
|
||
},
|
||
// 是否正在加载
|
||
isLoading: {
|
||
type: Boolean,
|
||
default: false,
|
||
},
|
||
// 空状态文案
|
||
emptyText: {
|
||
type: String,
|
||
default: "暂无工单数据",
|
||
},
|
||
// 空状态图标
|
||
emptyIcon: {
|
||
type: String,
|
||
default: "/static/images/empty.png",
|
||
},
|
||
// 是否显示刷新按钮
|
||
showRefreshBtn: {
|
||
type: Boolean,
|
||
default: true,
|
||
},
|
||
// 当前Tab类型
|
||
currentTab: {
|
||
type: String,
|
||
default: "all",
|
||
},
|
||
// 是否启用虚拟列表
|
||
useVirtualList: {
|
||
type: Boolean,
|
||
default: true,
|
||
},
|
||
// 虚拟列表高度
|
||
virtualListHeight: {
|
||
type: [String, Number],
|
||
default: "100%",
|
||
},
|
||
// 单元格高度模式
|
||
cellHeightMode: {
|
||
type: String,
|
||
default: "auto", // auto | fixed
|
||
},
|
||
// 固定高度(当cellHeightMode为fixed时使用)
|
||
fixedHeight: {
|
||
type: Number,
|
||
default: 120,
|
||
},
|
||
// 是否使用自定义空状态
|
||
customEmptyView: {
|
||
type: Boolean,
|
||
default: false,
|
||
},
|
||
});
|
||
|
||
// Emits
|
||
const emit = defineEmits([
|
||
"refresh",
|
||
"loadMore",
|
||
"orderClick",
|
||
"orderCall",
|
||
"orderComplete",
|
||
]);
|
||
|
||
// 响应式数据
|
||
const paging = ref(null);
|
||
const dataList = ref([]);
|
||
const pageNum = ref(1);
|
||
const pageSize = ref(10);
|
||
|
||
// 计算属性
|
||
const currentDataList = computed(() => {
|
||
return props.orderList || [];
|
||
});
|
||
|
||
// 查询列表数据
|
||
const queryList = async (pageNo, pageSize, from) => {
|
||
console.log("z-paging查询:", { pageNo, pageSize, from });
|
||
|
||
try {
|
||
// 触发父组件的数据加载事件
|
||
if (pageNo === 1) {
|
||
// 下拉刷新
|
||
emit("refresh");
|
||
} else {
|
||
// 上拉加载更多
|
||
emit("loadMore");
|
||
}
|
||
|
||
// 等待数据更新
|
||
await nextTick();
|
||
|
||
// 直接使用当前的orderList数据
|
||
const currentData = props.orderList || [];
|
||
|
||
// 在非虚拟列表模式下,z-paging主要用于下拉刷新和上拉加载
|
||
// 数据渲染通过模板中的v-for完成
|
||
paging.value?.complete(currentData, !props.hasMore);
|
||
|
||
} catch (error) {
|
||
console.error("查询列表失败:", error);
|
||
paging.value?.complete(false);
|
||
}
|
||
};
|
||
|
||
// 处理空状态重新加载
|
||
const handleEmptyReload = () => {
|
||
console.log("空状态重新加载");
|
||
paging.value?.reload();
|
||
};
|
||
|
||
// 处理工单点击
|
||
const handleOrderClick = (orderData) => {
|
||
emit("orderClick", orderData);
|
||
};
|
||
|
||
// 处理工单呼叫
|
||
const handleOrderCall = (orderData) => {
|
||
emit("orderCall", orderData);
|
||
};
|
||
|
||
// 处理工单完成
|
||
const handleOrderComplete = (orderData) => {
|
||
emit("orderComplete", orderData);
|
||
};
|
||
|
||
// 监听orderList变化,更新z-paging数据
|
||
watch(
|
||
() => props.orderList,
|
||
(newList) => {
|
||
if (newList && newList.length >= 0) {
|
||
dataList.value = [...newList];
|
||
// 在非虚拟列表模式下,主要是通知z-paging数据已更新
|
||
if (paging.value) {
|
||
paging.value.complete(newList, !props.hasMore);
|
||
}
|
||
}
|
||
},
|
||
{ immediate: true, deep: true }
|
||
);
|
||
|
||
// 监听Tab切换,重新加载数据
|
||
watch(
|
||
() => props.currentTab,
|
||
() => {
|
||
nextTick(() => {
|
||
paging.value?.reload();
|
||
});
|
||
}
|
||
);
|
||
|
||
// 组件挂载后初始化
|
||
onMounted(() => {
|
||
nextTick(() => {
|
||
// 初始化数据
|
||
if (currentDataList.value.length > 0) {
|
||
dataList.value = [...currentDataList.value];
|
||
// 手动触发z-paging的数据更新
|
||
if (paging.value) {
|
||
paging.value.complete(currentDataList.value, !props.hasMore);
|
||
}
|
||
} else {
|
||
// 如果没有初始数据,触发第一次查询
|
||
if (paging.value) {
|
||
paging.value.reload();
|
||
}
|
||
}
|
||
});
|
||
});
|
||
|
||
// 暴露方法
|
||
defineExpose({
|
||
reload: () => paging.value?.reload(),
|
||
refresh: () => paging.value?.reload(),
|
||
complete: (data, noMore) => paging.value?.complete(data, noMore),
|
||
getPaging: () => paging.value,
|
||
});
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
@import "./styles/index.scss";
|
||
</style> |