From 04102f7237efefa744090ed7c25f7b5d0807b679 Mon Sep 17 00:00:00 2001
From: quanwei <419654421@qq.com>
Date: Thu, 05 Feb 2026 18:11:57 +0800
Subject: [PATCH] 完成运营中心提现和运营中心权限管理

---
 mobile/components/diy/groupBuy/groupBuy.vue |  662 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 610 insertions(+), 52 deletions(-)

diff --git a/mobile/components/diy/groupBuy/groupBuy.vue b/mobile/components/diy/groupBuy/groupBuy.vue
index bb161b0..20c1149 100644
--- a/mobile/components/diy/groupBuy/groupBuy.vue
+++ b/mobile/components/diy/groupBuy/groupBuy.vue
@@ -1,77 +1,404 @@
 <template>
 	<view class="diy-groupbuy" :style="{ background: itemData.style.background }">
-		<view class="groupbuy-item" v-for="(supplier, index) in itemData.data" :key="index">
-			<view class="supplier-data" @click="gotoSupplier(supplier.supplier_id)">
-				<!-- 商户名称 -->
-				<view class="supplier-name">
-					{{ supplier.supplier_name || '商户名称' }}
-				</view>
+		<!-- 顶部筛选栏 -->
+		<view class="filter-bar" v-if="itemData.params.is_sort||(itemData.params.category==0&&itemData.params.is_category)||itemData.params.is_filter">
+			<view class="filter-item" v-if="itemData.params.is_sort"  @click="toggleSort">
+				<text class="filter-text">{{ sortOptions[currentSort] ? sortOptions[currentSort].text : '智能排序' }}</text>
+				<text class="filter-icon" :class="{ 'rotate': showSortDropdown }">▼</text>
+			</view>
+			<view class="filter-item" v-if="itemData.params.category==0&&itemData.params.is_category"  @click="toggleCategory">
+				<text class="filter-text">{{ currentCategory ? categoryOptions[currentCategory].name : '分类' }}</text>
+				<text class="filter-icon" :class="{ 'rotate': showCategoryDropdown }">▼</text>
+			</view>
+			<view class="filter-item" v-if="itemData.params.is_filter" @click="toggleFilter">
+				<text class="filter-text">筛选</text>
+				<text class="filter-badge" v-if="hasActiveFilters">●</text>
+			</view>
+		</view>
 
-				<!-- 商户详情 -->
-				<view class="supplier-detail" >
-					<view class="supplier-detail-left">
-						<image v-if="itemData.style.server_score_image" :src="itemData.style.server_score_image" class="supplier-detail-img" mode="aspectFill"></image>
-						<view class="supplier-detail-score">{{ supplier.server_score }} {{ supplier.server_score_text }}</view>
-						<view class="supplier-detail-comment" v-if="supplier.comment > 0">{{ supplier.comment }}条评论</view>
-						<view class="supplier-detail-price" v-if="supplier.average_price > 0">¥{{ supplier.average_price }}/人</view>
-					</view>
-					<view class="supplier-detail-right">
-						<view class="supplier-detail-distance">{{ supplier.distance }}</view>
-					</view>
-				</view>
+		<!-- 排序下拉面板 -->
+		<view class="sort-dropdown" v-if="showSortDropdown" @click.stop>
+			<view class="sort-option" v-for="(option, index) in sortOptions" :key="index" @click="selectSort(index)">
+				<text class="sort-option-text" :class="{ 'active': currentSort === index }">{{ option.text }}</text>
+				<text class="sort-option-check" v-if="currentSort === index">✓</text>
+			</view>
+		</view>
 
-				<!-- 优惠信息 -->
-				<view class="supplier-detail-discount">
-					<view class="discount-left" v-if="supplier.max_reduce_price && supplier.max_reduce_price > 0">
-						<view class="discount-left-text">超值券</view>
-						<view class="discount-left-price">最高减{{ supplier.max_reduce_price }}元</view>
-					</view>
-					<view class="discount-right" v-if="supplier.ranking && supplier.ranking <= 10 && supplier.ranking < 999">
-						好评榜第{{ supplier.ranking }}名
+		<!-- 分类下拉面板 -->
+		<view class="category-dropdown" :class="{ 'align-first': !itemData.params.is_sort }" v-if="showCategoryDropdown" @click.stop>
+			<view class="sort-option" v-for="(option, index) in categoryOptions" :key="index" @click="selectCategory(index)">
+				<text class="sort-option-text" :class="{ 'active': currentCategory === index }">{{ option.name }}</text>
+				<text class="sort-option-check" v-if="currentCategory === index">✓</text>
+			</view>
+		</view>
+
+		<!-- 遮罩层 -->
+		<view class="mask" v-if="showSortDropdown || showCategoryDropdown || showFilterPanel" @click="closeAllDropdowns"></view>
+
+		<!-- 筛选面板 -->
+		<view class="filter-panel" v-if="showFilterPanel" @click.stop>
+			<view class="filter-panel-header">
+				<text class="filter-panel-title">筛选</text>
+				<text class="filter-reset" @click="resetFilters">重置</text>
+			</view>
+
+			<view class="filter-section">
+				<view class="filter-section-title">距离范围</view>
+				<view class="filter-tags">
+					<view class="filter-tag" v-for="(item, index) in distanceOptions" :key="index"
+						:class="{ 'active': selectedDistance === index }" @click="selectDistance(index)">
+						{{ item.label }}
 					</view>
 				</view>
 			</view>
 
-			<!-- 商品列表 -->
-			<scroll-view class="supplier-product" scroll-x="true" show-scrollbar="false">
-				<view class="product-item" v-for="(product, productKey) in supplier.productList" :key="productKey"
-					@click="gotoDetail(product.product_id)">
-					<!-- 商品图片 -->
-					<view class="product-img">
-						<image :src="product.product_image" mode="aspectFill"></image>
-						<!-- 优惠券标签 -->
-						<view class="product-discount" v-if="product.reduce_price > 0">
-							<view class="discount-type">超值券</view>
-							<view class="discount-price">减{{ product.reduce_price }}元</view>
+			<view class="filter-section">
+				<view class="filter-section-title">人均价格</view>
+				<view class="filter-tags">
+					<view class="filter-tag" v-for="(item, index) in priceOptions" :key="index"
+						:class="{ 'active': selectedPrice === index }" @click="selectPrice(index)">
+						{{ item.label }}
+					</view>
+				</view>
+			</view>
+
+			<view class="filter-section">
+				<view class="filter-section-title">服务评分</view>
+				<view class="filter-tags">
+					<view class="filter-tag" v-for="(item, index) in scoreOptions" :key="index"
+						:class="{ 'active': selectedScore === index }" @click="selectScore(index)">
+						{{ item.label }}
+					</view>
+				</view>
+			</view>
+
+			<view class="filter-section">
+				<view class="filter-section-title">优惠类型</view>
+				<view class="filter-tags">
+					<view class="filter-tag" :class="{ 'active': showCouponOnly }" @click="toggleCouponOnly">
+						仅看有券
+					</view>
+					<view class="filter-tag" :class="{ 'active': showTopRanked }" @click="toggleTopRanked">
+						好评榜前10
+					</view>
+				</view>
+			</view>
+
+			<view class="filter-panel-footer">
+				<view class="filter-confirm-btn" @click="applyFilters">确定</view>
+			</view>
+		</view>
+
+		<!-- 团购列表容器 -->
+		<scroll-view
+			class="groupbuy-scroll"
+			scroll-y="true"
+			@scrolltolower="loadMore"
+			lower-threshold="100"
+		>
+			<!-- 团购列表 -->
+			<view class="groupbuy-item" v-for="(supplier, index) in listData" :key="index">
+				<view class="supplier-data" @click="gotoSupplier(supplier.shop_supplier_id)">
+					<!-- 商户名称 -->
+					<view class="supplier-name">
+						{{ supplier.supplier_name || '商户名称' }}
+					</view>
+
+					<!-- 商户详情 -->
+					<view class="supplier-detail" >
+						<view class="supplier-detail-left">
+							<image v-if="itemData.style.server_score_image" :src="itemData.style.server_score_image" class="supplier-detail-img" mode="aspectFill"></image>
+							<view class="supplier-detail-score">{{ supplier.server_score }} {{ supplier.server_score_text }}</view>
+							<view class="supplier-detail-comment" v-if="supplier.comment_count > 0">{{ supplier.comment_count }}条评论</view>
+							<view class="supplier-detail-price" v-if="supplier.average_price > 0">¥{{ supplier.average_price }}/人</view>
+						</view>
+						<view class="supplier-detail-right">
+							<view class="supplier-detail-distance">{{ supplier.distance }}</view>
 						</view>
 					</view>
 
-					<!-- 商品名称 -->
-					<view class="product-name">
-						{{ product.product_name }}
-					</view>
-
-					<!-- 商品价格和购买按钮 -->
-					<view class="product-price">
-						<view class="price">¥{{ product.product_price }}</view>
-						<view class="buy-btn">抢购</view>
+					<!-- 优惠信息 -->
+					<view class="supplier-detail-discount">
+						<view class="discount-left" v-if="supplier.max_reduce_price && supplier.max_reduce_price > 0">
+							<view class="discount-left-text">超值券</view>
+							<view class="discount-left-price">最高减{{ supplier.max_reduce_price }}元</view>
+						</view>
+						<view class="discount-right" v-if="supplier.ranking && supplier.ranking <= 10 && supplier.ranking < 999">
+							好评榜第{{ supplier.ranking }}名
+						</view>
 					</view>
 				</view>
-			</scroll-view>
-		</view>
+
+				<!-- 商品列表 -->
+				<scroll-view class="supplier-product" scroll-x="true" show-scrollbar="false">
+					<view class="product-item" v-for="(product, productKey) in supplier.productList" :key="productKey"
+						@click="gotoDetail(product.product_id)">
+						<!-- 商品图片 -->
+						<view class="product-img">
+							<image :src="product.product_image" mode="aspectFill"></image>
+							<!-- 优惠券标签 -->
+							<view class="product-discount" v-if="product.reduce_price > 0">
+								<view class="discount-type">超值券</view>
+								<view class="discount-price">减{{ product.reduce_price }}元</view>
+							</view>
+						</view>
+
+						<!-- 商品名称 -->
+						<view class="product-name">
+							{{ product.product_name }}
+						</view>
+
+						<!-- 商品价格和购买按钮 -->
+						<view class="product-price">
+							<view class="price">¥{{ product.product_price }}</view>
+							<view class="buy-btn">抢购</view>
+						</view>
+					</view>
+				</scroll-view>
+			</view>
+
+			<!-- 加载状态 -->
+			<view class="load-more" v-if="listData.length > 0">
+				<view v-if="isLoadingMore" class="loading-text">加载中...</view>
+				<view v-else-if="!hasMore" class="loading-text">没有更多了</view>
+			</view>
+
+			<!-- 空状态 -->
+			<view class="empty-state" v-if="listData.length === 0 && !isLoading">
+				<text class="empty-text">暂无符合条件的商户</text>
+			</view>
+		</scroll-view>
 	</view>
 </template>
 
 <script>
 export default {
 	data() {
-		return {};
+		return {
+			showSortDropdown: false,
+			showCategoryDropdown: false,
+			showFilterPanel: false,
+			currentSort: 0,
+			currentCategory: 0,
+			selectedDistance: -1,
+			selectedPrice: -1,
+			selectedScore: -1,
+			showCouponOnly: false,
+			showTopRanked: false,
+			sortOptions: [],
+			categoryOptions: [],
+			distanceOptions: [],
+			priceOptions: [],
+			scoreOptions: [],
+			listData:[],
+			isLoading: false,
+			isLoadingMore: false,
+			hasMore: true,
+			currentPage: 1,
+			param:{
+				longitude:0,
+				latitude:0,
+				list_rows:15
+			}
+		};
 	},
 	props: ['itemData'],
+	
+	computed: {
+		hasActiveFilters() {
+			return this.selectedDistance >= 0 ||
+				   this.selectedPrice >= 0 ||
+				   this.selectedScore >= 0 ||
+				   this.showCouponOnly ||
+				   this.showTopRanked;
+		}
+	},
 	created() {
-		console.log('团购组件数据:', this.itemData);
+		this.getFilterCondition();
+		this.getList();
 	},
 	methods: {
+		// 获取筛选条件
+		getFilterCondition() {
+			let self = this;
+			this._get('supplier.index/getGroupBuyCondition', {}, res => {
+				self.sortOptions = res.data.sortOptions || [];
+				self.categoryOptions = res.data.category || [];
+				self.distanceOptions = res.data.distanceOptions || [];
+				self.priceOptions = res.data.priceOptions || [];
+				self.scoreOptions = res.data.scoreOptions || [];
+			});
+		},
+		toggleSort() {
+			this.showSortDropdown = !this.showSortDropdown;
+			this.showCategoryDropdown = false;
+			this.showFilterPanel = false;
+		},
+		toggleCategory() {
+			this.showCategoryDropdown = !this.showCategoryDropdown;
+			this.showSortDropdown = false;
+			this.showFilterPanel = false;
+		},
+		toggleFilter() {
+			this.showFilterPanel = !this.showFilterPanel;
+			this.showSortDropdown = false;
+			this.showCategoryDropdown = false;
+		},
+		closeAllDropdowns() {
+			this.showSortDropdown = false;
+			this.showCategoryDropdown = false;
+			this.showFilterPanel = false;
+		},
+		selectCategory(index) {
+			this.currentCategory = index;
+			this.showCategoryDropdown = false;
+			// 分类改变后重新请求数据
+			this.resetAndLoad();
+		},
+		selectDistance(index) {
+			this.selectedDistance = this.selectedDistance === index ? -1 : index;
+		},
+		selectPrice(index) {
+			this.selectedPrice = this.selectedPrice === index ? -1 : index;
+		},
+		selectScore(index) {
+			this.selectedScore = this.selectedScore === index ? -1 : index;
+		},
+		toggleCouponOnly() {
+			this.showCouponOnly = !this.showCouponOnly;
+		},
+		toggleTopRanked() {
+			this.showTopRanked = !this.showTopRanked;
+		},
+		resetFilters() {
+			this.selectedDistance = -1;
+			this.selectedPrice = -1;
+			this.selectedScore = -1;
+			this.showCouponOnly = false;
+			this.showTopRanked = false;
+		},
+		applyFilters() {
+			this.showFilterPanel = false;
+			// 应用筛选后重新请求数据
+			this.resetAndLoad();
+		},
+		selectSort(index) {
+			this.currentSort = index;
+			this.showSortDropdown = false;
+			// 排序改变后重新请求数据
+			this.resetAndLoad();
+		},
+		parseDistance(distanceStr) {
+			if (!distanceStr) return 99999;
+			const match = distanceStr.match(/(\d+\.?\d*)/);
+			return match ? parseFloat(match[1]) : 99999;
+		},
+		resetAndLoad() {
+			// 重置分页状态
+			this.currentPage = 1;
+			this.hasMore = true;
+			this.listData = [];
+			// 重新加载数据
+			this.getList();
+		},
+		getList(isLoadMore = false) {
+			if (this.isLoading || this.isLoadingMore) {
+				return;
+			}
+
+			// 加载更多时检查是否还有更多数据
+			if (isLoadMore && !this.hasMore) {
+				return;
+			}
+
+			// 设置加载状态
+			if (isLoadMore) {
+				this.isLoadingMore = true;
+			} else {
+				this.isLoading = true;
+			}
+
+			let self = this;
+			let param = {
+				...this.param,
+				page: this.currentPage,
+				longitude: uni.getStorageSync('longitude') || 0,
+				latitude: uni.getStorageSync('latitude') || 0,
+				sortType: this.sortOptions[this.currentSort] ? this.sortOptions[this.currentSort].value : 'smart'
+			};
+      if (this.itemData.params.category>0){
+        param.category_id = this.itemData.params.category;
+      }
+      param.product_num= this.itemData.params.product_num
+      // 添加分类筛选
+			if (this.categoryOptions[this.currentCategory] && this.categoryOptions[this.currentCategory].category_id > 0) {
+				param.category_id = this.categoryOptions[this.currentCategory].category_id;
+			}
+
+			// 添加筛选条件到参数
+			if (this.selectedDistance >= 0) {
+				const distanceValue = this.distanceOptions[this.selectedDistance].value;
+				// 距离"不限"选项的value是-1,不传递参数
+				if (distanceValue > 0) {
+					param.max_distance = distanceValue;
+				}
+			}
+
+			if (this.selectedPrice >= 0) {
+				const range = this.priceOptions[this.selectedPrice].value;
+				// 如果是"不限"选项(value=-1),不传递价格参数
+				if (typeof range === 'object' && range.min !== undefined) {
+					param.price_min = range.min;
+					param.price_max = range.max;
+				}
+			}
+
+			if (this.selectedScore >= 0) {
+				const scoreValue = this.scoreOptions[this.selectedScore].value;
+				// 评分"不限"选项的value是-1,不传递参数
+				if (scoreValue > 0) {
+					param.min_score = scoreValue;
+				}
+			}
+
+			if (this.showCouponOnly) {
+				param.has_coupon = 1;
+			}
+
+			if (this.showTopRanked) {
+				param.top_ranked = 1;
+			}
+
+			this._get('supplier.index/getGroupBuyList', param, function(res) {
+				const newData = res.data.list.data || [];
+				const total = res.data.list.total || 0;
+
+				if (isLoadMore) {
+					// 加载更多,追加数据
+					self.listData = [...self.listData, ...newData];
+				} else {
+					// 首次加载,替换数据
+					self.listData = newData;
+				}
+
+				// 判断是否还有更多数据
+				const loadedCount = self.listData.length;
+				self.hasMore = loadedCount < total;
+
+				// 清除加载状态
+				if (isLoadMore) {
+					self.isLoadingMore = false;
+				} else {
+					self.isLoading = false;
+				}
+			});
+		},
+		loadMore() {
+			if (this.hasMore && !this.isLoadingMore && !this.isLoading) {
+				this.currentPage++;
+				this.getList(true);
+			}
+		},
 		/**
 		 * 跳转商品详情
 		 */
@@ -79,8 +406,9 @@
 			let url = '/pages/product/detail/detail?product_id=' + productId;
 			this.gotoPage(url);
 		},
-        gotoSupplier(productId) {
-			let url = '/pages/shop/shop?supplier_id=' + productId;
+		gotoSupplier(supplierId) {
+			let url = '/pages/shop/shop?shop_supplier_id=' + supplierId;
+				uni.setStorageSync('shop_supplier_id',supplierId)
 			this.gotoPage(url);
 		}
 	}
@@ -89,9 +417,225 @@
 
 <style scoped>
 .diy-groupbuy {
+	position: relative;
 	padding: 24rpx;
+	padding-top: 0;
 }
 
+/* 列表滚动容器 */
+.groupbuy-scroll {
+	height: calc(100vh - 88rpx);
+	width: 100%;
+}
+
+/* 加载更多状态 */
+.load-more {
+	padding: 30rpx 0;
+	text-align: center;
+}
+
+.loading-text {
+	font-size: 28rpx;
+	color: #999;
+}
+
+/* 筛选栏 */
+.filter-bar {
+	position: sticky;
+	top: 0;
+	z-index: 100;
+	display: flex;
+	background: #ffffff;
+	padding: 20rpx 24rpx;
+	border-bottom: 1rpx solid #f0f0f0;
+	justify-content: space-between;
+}
+
+.filter-item {
+	display: flex;
+	align-items: center;
+	gap: 8rpx;
+	padding: 10rpx 20rpx;
+	margin-right: 20rpx;
+	background: #f8f8f8;
+	border-radius: 30rpx;
+	font-size: 28rpx;
+	color: #333;
+}
+
+.filter-text {
+	font-size: 28rpx;
+	color: #333;
+}
+
+.filter-icon {
+	font-size: 20rpx;
+	color: #999;
+	transition: transform 0.3s;
+}
+
+.filter-icon.rotate {
+	transform: rotate(180deg);
+}
+
+.filter-badge {
+	width: 12rpx;
+	height: 12rpx;
+	background: #c73a4e;
+	border-radius: 50%;
+	font-size: 0;
+}
+
+/* 排序下拉面板 */
+.sort-dropdown,
+.category-dropdown {
+	position: absolute;
+	top: 88rpx;
+	z-index: 200;
+	width: 200rpx;
+	background: #ffffff;
+	border-radius: 16rpx;
+	box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15);
+	overflow: hidden;
+}
+
+.sort-dropdown {
+	left: 24rpx;
+}
+
+.category-dropdown {
+	left: calc(24rpx + 200rpx + 20rpx);
+}
+
+.category-dropdown.align-first {
+	left: 24rpx;
+}
+
+.sort-option {
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	padding: 24rpx 30rpx;
+	border-bottom: 1rpx solid #f5f5f5;
+}
+
+.sort-option:last-child {
+	border-bottom: none;
+}
+
+.sort-option-text {
+	font-size: 28rpx;
+	color: #333;
+}
+
+.sort-option-text.active {
+	color: #c73a4e;
+	font-weight: bold;
+}
+
+.sort-option-check {
+	color: #c73a4e;
+	font-size: 28rpx;
+	font-weight: bold;
+}
+
+/* 遮罩层 */
+.mask {
+	position: fixed;
+	top: 0;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	background: rgba(0, 0, 0, 0.5);
+	z-index: 150;
+}
+
+/* 筛选面板 */
+.filter-panel {
+	position: fixed;
+	bottom: 0;
+	left: 0;
+	right: 0;
+	z-index: 200;
+	background: #ffffff;
+	border-radius: 32rpx 32rpx 0 0;
+	max-height: 80vh;
+	overflow-y: auto;
+	padding-bottom: env(safe-area-inset-bottom);
+}
+
+.filter-panel-header {
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	padding: 30rpx 24rpx;
+	border-bottom: 1rpx solid #f5f5f5;
+}
+
+.filter-panel-title {
+	font-size: 32rpx;
+	font-weight: bold;
+	color: #333;
+}
+
+.filter-reset {
+	font-size: 28rpx;
+	color: #999;
+}
+
+.filter-section {
+	padding: 30rpx 24rpx;
+	border-bottom: 1rpx solid #f5f5f5;
+}
+
+.filter-section-title {
+	font-size: 28rpx;
+	font-weight: bold;
+	color: #333;
+	margin-bottom: 20rpx;
+}
+
+.filter-tags {
+	display: flex;
+	flex-wrap: wrap;
+	gap: 16rpx;
+}
+
+.filter-tag {
+	padding: 16rpx 32rpx;
+	background: #f8f8f8;
+	border-radius: 8rpx;
+	font-size: 26rpx;
+	color: #666;
+	white-space: nowrap;
+}
+
+.filter-tag.active {
+	background: #fff5f6;
+	color: #c73a4e;
+	border: 1rpx solid #c73a4e;
+}
+
+.filter-panel-footer {
+	padding: 24rpx;
+	border-top: 1rpx solid #f5f5f5;
+	padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
+}
+
+.filter-confirm-btn {
+	width: 100%;
+	height: 88rpx;
+	background: linear-gradient(to right, #c73a4e, #e74c3c);
+	border-radius: 44rpx;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	color: #ffffff;
+	font-size: 32rpx;
+	font-weight: bold;
+}
+
+/* 团购列表 */
 .groupbuy-item {
 	background: #ffffff;
 	margin-bottom: 20rpx;
@@ -298,4 +842,18 @@
 .buy-btn:active {
 	opacity: 0.8;
 }
+
+/* 空状态 */
+.empty-state {
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	justify-content: center;
+	padding: 100rpx 0;
+}
+
+.empty-text {
+	font-size: 28rpx;
+	color: #999;
+}
 </style>

--
Gitblit v1.9.2