<template>
	<view class="common-list">
		<!-- 头部插槽：父组件可插入独立的Tab、筛选组件等 -->
		<slot name="header"></slot>

		<!-- 核心列表区域（scroll-view 实现刷新加载） -->
		<scroll-view ref="listScrollRef" :scroll-top="scrollTop" class="list-scroll" scroll-y
			:style="{ height: listScrollHeight }" :refresher-enabled="refresherEnabled" :refresher-triggered="isRefreshing"
			@refresherrefresh="handleRefresh" @scrolltolower="handleLoadMore" :show-scrollbar="false"
			:refresher-threshold="20" lower-threshold="130">
			<!-- 滑动区域头部插槽：父组件可插入独立的Tab、筛选组件等 -->
			<slot name="headerScroll"></slot>
			<!-- 列表项插槽：父组件自定义列表内容 -->
			<view class="list-container" v-if="listData.length">
				<slot name="listData" :list="listData"></slot>
			</view>

			<!-- 空数据插槽：父组件自定义空状态 -->
			<slot name="empty" v-else></slot>

			<!-- 加载提示 -->
			<view class="load-tips" v-if="listData.length">
				<text v-if="hasMore && !isLoading">{{ loadingText }}</text>
				<text v-else>{{ !hasMore ? noMoreText : "已加载完成" }}</text>
			</view>
		</scroll-view>
	</view>
</template>

<script>
	import request from "@/utils/request";

	export default {
		name: "CommonList",
		props: {
			//是否开启下拉刷新
			refresherEnabled: {
				type: Boolean,
				default: true,
			},
			// 必需：列表数据请求地址
			apiUrl: {
				type: String,
				required: true,
				default: "",
			},
			// 初始查询参数（如分页、筛选条件等，由父组件传入）
			initialQuery: {
				type: Object,
				default: () => ({}),
			},
			// 列表滚动高度（父组件根据布局动态计算）
			listScrollHeight: {
				type: String,
				default: "calc(100vh - 200rpx)",
			},
			// 自定义提示文本（可选）
			loadingText: {
				type: String,
				default: "加载中...",
			},
			noMoreText: {
				type: String,
				default: "～暂时只有这些了～",
			},
			// 分页配置（可选，默认page=1，limit=10）
			pageConfig: {
				type: Object,
				default: () => ({
					pageKey: "page", // 接口分页参数名（如“page”）
					limitKey: "limit", // 接口每页条数参数名（如“limit”）
					page: 1, // 初始页码
					limit: 10, // 每页条数
				}),
			},
			// 接口数据结构映射（适配不同接口返回格式）
			responseMap: {
				type: Object,
				default: () => ({
					list: "data", // 列表数据在响应中的字段名
					total: "count", // 总条数在响应中的字段名
				}),
			},
		},
		data() {
			const {
				pageKey,
				limitKey,
				page,
				limit
			} = this.pageConfig;
			return {
				queryData: {
					[pageKey]: page,
					[limitKey]: limit,
					...this.initialQuery,
				},
				scrollTop: 0,
				listData: [], // 列表数据
				isRefreshing: false, // 下拉刷新状态（控制动画）
				isLoading: false, // 加载中状态（防止重复请求）
				hasMore: true, // 是否有更多数据
			};
		},
		created() {
			// 初始化加载列表
			// this.fetchListData();
		},
		methods: {
			/** 核心：请求列表数据 */
			async fetchListData() {
				// 防止重复请求
				if (this.isLoading) return;
				this.isLoading = true;

				try {
					const res = await request.post(this.apiUrl, this.queryData);
					const {
						list: listField,
						total: totalField
					} = this.responseMap;
					// 从响应中提取列表数据和总条数（适配不同接口格式）

					let list = res[listField] || [];
					let total = res[totalField] || 0;
					if (list.list) {
						total = list[totalField] || 0;
						list = list.list || [];
					}

					// 分页逻辑：第一页重置，后续页追加
					if (this.queryData[this.pageConfig.pageKey] === 1) {
						this.scrollToTop();
						this.listData = list;
					} else {
						this.listData = [...this.listData, ...list];
					}
					// 判断是否有更多数据（当前列表长度 >= 总条数则无更多）
					this.hasMore = this.listData.length < total;

					// 向父组件传递加载成功事件
					this.$emit("load-success", {
						list: this.listData,
						total,
						currentPage: this.queryData[this.pageConfig.pageKey],
					});
					this.$emit("load-success-all", res);
				} catch (err) {
					this.$emit("load-fail", err);
					console.error("列表请求失败：", err);
				} finally {
					// 关键修复：用$nextTick确保状态更新同步到DOM
					this.$nextTick(() => {
						this.isRefreshing = false; // 结束下拉刷新动画
						this.isLoading = false; // 结束加载状态
					});
				}
			},

			/** 下拉刷新：重置页码为1，重新加载 */
			handleRefresh() {
				// 关键修复：明确开启刷新状态（与scroll-view双向绑定同步）
				this.isRefreshing = true;
				// 重置页码为1
				this.queryData[this.pageConfig.pageKey] = 1;
				// 触发数据请求
				this.fetchListData();
			},

			/** 上拉加载更多：页码+1，追加数据 */
			handleLoadMore() {
				// 无更多数据/正在加载/正在刷新时，不触发加载
				if (!this.hasMore || this.isLoading || this.isRefreshing) return;
				this.queryData[this.pageConfig.pageKey] += 1;
				this.fetchListData();
			},

			/** 对外暴露：手动刷新列表（父组件可通过ref调用） */
			manualRefresh(newQuery = {}) {
				this.queryData = {
					...this.queryData,
					[this.pageConfig.pageKey]: 1, // 重置为第一页
					...newQuery,
				};
				this.fetchListData();
			},

			/** 对外暴露：清空列表数据 */
			clearList() {
				this.listData = [];
				this.queryData[this.pageConfig.pageKey] = 1;
				this.hasMore = true;
			},
			/** 工具方法：滚动到顶部（复用逻辑） */
			scrollToTop() {
				if (this.scrollTop == 0) {
					this.scrollTop = 0.1;
				} else {
					this.scrollTop = 0;
				}
			},
		},
	};
</script>

<style scoped>
	.common-list {
		width: 100%;
		background-color: #fff;
		padding-bottom: 30rpx;
	}

	/* 列表滚动容器 */
	.list-scroll {
		width: 100%;
		margin-top: 16rpx;
	}

	/* 列表容器 */
	.list-container {
		padding: 0 20rpx;
	}

	/* 加载提示 */
	.load-tips {
		text-align: center;
		font-size: 24rpx;
		color: #cecece;
		padding: 24rpx 0;
		margin-top: 30rpx;
	}
</style>