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