<template>
|
|
<view class="container">
|
|
<!-- 顶部banner -->
|
|
<banner-swiper :banner-list="bannerList" height="320rpx" :fallback-image="recycle_banner"
|
|
video-id-prefix="recycle-video"></banner-swiper>
|
|
|
|
|
|
<!-- 商品列表 -->
|
|
<view class="goods-list">
|
|
<!-- 左侧分类导航 -->
|
|
<view class="category-nav">
|
|
<view v-for="(category, index) in categories" :key="category.id || index" class="category-item"
|
|
:class="{ active: currentCategory === index }" @click="switchCategory(index)">
|
|
<view class="category-dot" v-if="getCategoryItemCount(index) > 0">{{ getCategoryItemCount(index) }}</view>
|
|
{{ category.title }}
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 右侧商品列表 -->
|
|
<scroll-view class="goods-content" scroll-y @scrolltolower="loadMoreGoods">
|
|
<view class="goods-section">
|
|
<view class="goods-item" v-for="(item, index) in recycleList" :key="index">
|
|
<view class="goods-img-container">
|
|
<image v-if="item.image" :src="item.image" class="goods-item-img" mode="aspectFit" />
|
|
<!-- 品牌标签 -->
|
|
<view class="brand-tag" v-if="item.isPin === 'Y'">品牌</view>
|
|
</view>
|
|
<view class="goods-info-wrap">
|
|
<view class="goods-header">
|
|
<text class="goods-name">{{ item.name }}</text>
|
|
</view>
|
|
<text class="goods-desc">{{ item.service }}</text>
|
|
<view class="rules-brand-row">
|
|
<view class="rules-link" @click="showRules(item)" v-if="item.isRecycleRules == '1'">
|
|
<view class="rules">
|
|
<text>回收规则</text>
|
|
<uni-icons type="right" size="14" color="#999"></uni-icons>
|
|
</view>
|
|
</view>
|
|
<!-- <view class="brand-check-placeholder" v-if="item.isPin === 'Y'">
|
|
<view class="brand-check" @click="checkBrand(index)">
|
|
<text>查看品牌</text>
|
|
<uni-icons type="right" size="12" color="#ff7a0e"></uni-icons>
|
|
</view>
|
|
</view> -->
|
|
</view>
|
|
<view class="goods-info">
|
|
<view class="price-info">
|
|
<text class="price-symbol">¥</text>
|
|
<text class="price-value" v-if="!item.maxPrice || item.maxPrice == item.price">{{ item.price }}</text>
|
|
<text class="price-value" v-else>{{ item.price }}-{{ item.maxPrice }}</text>
|
|
<text class="price-unit">/{{ item.unit || '件' }}</text>
|
|
</view>
|
|
<view class="quantity-control">
|
|
<button class="btn-minus" @click="updateQuantity(index, -1)">-</button>
|
|
<text class="quantity">{{ getItemTotalQuantity(item) }}</text>
|
|
<button class="btn-plus" @click="updateQuantity(index, 1)">+</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 不可回收商品 -->
|
|
<view class="other-unrecycle-card">
|
|
<!-- 使用商品分类数据中的icon -->
|
|
<image class="other-unrecycle-img" :src="categories[currentCategory]?.icon" mode="aspectFit" />
|
|
<view class="other-unrecycle-info">
|
|
<!-- 主标题和副标题用接口返回的otherTitle和otherSubTitle -->
|
|
<view class="other-unrecycle-title">{{ categories[currentCategory]?.otherTitle }}</view>
|
|
<view class="other-unrecycle-desc">{{ categories[currentCategory]?.otherSubTitle }}</view>
|
|
<view class="other-unrecycle-price-row">
|
|
<text class="other-unrecycle-price">¥ — /{{ categories[currentCategory]?.unit || '件' }}</text>
|
|
</view>
|
|
</view>
|
|
<button class="other-unrecycle-btn" open-type="contact">+</button>
|
|
</view>
|
|
<view v-if="loadingMore" class="loading-more">加载中...</view>
|
|
<view v-else-if="finished" class="loading-more">没有更多了</view>
|
|
</scroll-view>
|
|
</view>
|
|
|
|
<!-- 固定底部区域 -->
|
|
<view class="fixed-bottom-wrap" v-if="!showDetailPanel">
|
|
<view class="green-tip-bar">
|
|
回收范围仅支持回收以上品类,按件回收预计比称重回收多
|
|
<text class="tip-highlight"> {{ extraRecycleAmount.display }}</text>
|
|
</view>
|
|
<view class="bottom-bar">
|
|
<view class="bottom-left">
|
|
<view class="summary-row">
|
|
<text class="summary-label">已选 <text class="summary-count">{{ totalCount }}</text> {{ totalUnitText }}
|
|
预计回收可得</text>
|
|
<uni-icons type="help" size="18" color="#b2b2b2" style="margin: 0 8rpx;" @tap="showPriceInfoPopups" />
|
|
</view>
|
|
<view class="amount-row" @click="toggleDetailPanel">
|
|
<uni-icons :type="showDetailPanel ? 'up' : 'down'" size="18" color="#5e5e5e"
|
|
style="margin-right: 8rpx;vertical-align: middle;" />
|
|
<text class="amount" v-if="priceRange.min === priceRange.max">¥{{ priceRange.min }}</text>
|
|
<text class="amount" v-else>¥{{ priceRange.min }}-{{ priceRange.max }}</text>
|
|
</view>
|
|
</view>
|
|
<button class="submit-btn" @click="submitOrder">预约上门取件</button>
|
|
</view>
|
|
<view class="bottom-bar-divider"></view>
|
|
</view>
|
|
|
|
<!-- 明细弹窗遮罩和弹窗 -->
|
|
<view v-if="showDetailPanel" class="detail-popup-mask" @click.self="toggleDetailPanel">
|
|
<view class="detail-popup" @click.stop>
|
|
<view class="detail-popup-close" @click="toggleDetailPanel">×</view>
|
|
<view class="green-tip-bar popup-green-tip">
|
|
回收范围仅支持回收以上品类,按件回收预计比称重回收多
|
|
<text class="tip-highlight"> {{ extraRecycleAmount.display }}</text>
|
|
</view>
|
|
<view class="panel-header">
|
|
<text class="panel-title">已选商品明细</text>
|
|
</view>
|
|
<scroll-view class="panel-list popup-panel-list" scroll-y>
|
|
<!-- @click="openProductDetail(item)" -->
|
|
<view v-for="(item, idx) in selectedProducts" :key="item.uniqueKey || idx"
|
|
class="panel-item">
|
|
<view class="panel-img-container">
|
|
<image v-if="item.styleImage || item.image" :src="item.styleImage || item.image" class="panel-item-img" mode="aspectFit" />
|
|
<!-- 品牌标签 -->
|
|
<view class="panel-brand-tag" v-if="item.brandId">品牌</view>
|
|
</view>
|
|
<view class="panel-item-info">
|
|
<!-- <text class="panel-item-name">{{ item.name }}</text> -->
|
|
<!-- <text class="panel-item-desc" v-if="item.brandName && item.styleName">品牌:{{ item.brandName }} | 款式:{{ item.styleName }}</text> -->
|
|
<text class="panel-item-name">{{ item.brandName || item.name }}</text>
|
|
<text class="panel-item-desc" v-if="item.styleName">{{ item.styleName }}</text>
|
|
<text class="panel-item-desc" v-else>{{ item.service }}</text>
|
|
<text class="panel-item-price" v-if="!item.maxPrice || item.maxPrice == item.price">¥{{ item.price }}/{{
|
|
item.unit || '件' }}</text>
|
|
<text class="panel-item-price" v-else>¥{{ item.price }}-{{ item.maxPrice }}/{{ item.unit || '件' }}</text>
|
|
</view>
|
|
<view class="panel-quantity-control">
|
|
<button class="btn-minus" @click.stop="updateQuantityByProduct(item, -1)">-</button>
|
|
<!-- <button class="btn-minus">-</button> -->
|
|
<text class="quantity">{{ item.quantity }}</text>
|
|
<button class="btn-plus" @click.stop="updateQuantityByProduct(item, 1)">+</button>
|
|
<!-- <button class="btn-plus">+</button> -->
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
<view class="popup-bottom-bar">
|
|
<view class="bottom-left">
|
|
<view class="summary-row">
|
|
<text class="summary-label">已选 <text class="summary-count">{{ totalCount }}</text> {{ totalUnitText }}
|
|
预计回收可得</text>
|
|
<uni-icons type="help" size="18" color="#b2b2b2" style="margin: 0 8rpx;" @tap="showPriceInfoPopups" />
|
|
</view>
|
|
<view class="amount-row" @click="toggleDetailPanel">
|
|
<uni-icons :type="showDetailPanel ? 'up' : 'down'" size="18" color="#5e5e5e"
|
|
style="margin-right: 8rpx;vertical-align: middle;" />
|
|
<text class="amount" v-if="priceRange.min === priceRange.max">¥{{ priceRange.min }}</text>
|
|
<text class="amount" v-else>¥{{ priceRange.min }}-{{ priceRange.max }}</text>
|
|
</view>
|
|
</view>
|
|
<button class="submit-btn" @click="submitOrder">预约上门取件</button>
|
|
</view>
|
|
|
|
<!-- 添加衣物浮窗按钮 -->
|
|
<view class="floating-add-btn" @click="addMoreItems">
|
|
<text class="floating-btn-text">添加衣物</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 价格说明弹窗 -->
|
|
<view v-if="showPriceInfoPopup" class="price-info-popup-mask" @click.self="closePriceInfoPopup">
|
|
<view class="price-info-popup">
|
|
<view class="price-info-popup-title">回收规则</view>
|
|
<scroll-view class="price-info-popup-content" scroll-y>
|
|
<!-- <view class="price-info-section">
|
|
<view class="price-info-heading">关于旧衣质检</view>
|
|
<view class="price-info-text">请确认本次回收旧衣是可以进行二次穿着的程度,如回收旧衣有破损磨损、开线变形、起球发黄、染色污渍、配饰脱落或款式老旧等问题,无法通过质检。</view>
|
|
</view>
|
|
<view class="price-info-section">
|
|
<view class="price-info-heading">质检报告</view>
|
|
<view class="price-info-text">回收商收到衣后1-3个工作日内完成衣质检报告。</view>
|
|
</view>
|
|
<view class="price-info-section">
|
|
<view class="price-info-heading">质检结果与回收价格</view>
|
|
<view class="price-info-text">若回收旧衣质检通过,质检价格与用户提交订单时的预估价格一致,回收商将按照预估价打款至您的小程序账户余额。</view>
|
|
</view> -->
|
|
<uv-parse :content="huodong_text"></uv-parse>
|
|
</scroll-view>
|
|
<button class="price-info-popup-btn" @click="closePriceInfoPopup">我知道了</button>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 根据角色显示不同的导航栏 -->
|
|
<tabbar v-if="ishow" select="recycle"></tabbar>
|
|
|
|
<!-- 品牌选择组件 -->
|
|
<brand-selector ref="brandSelector" @brand-confirm="onBrandConfirm" @reduce-select="onReduceSelect"
|
|
@close="onBrandSelectorClose" @get-existing-quantities="getExistingQuantities"></brand-selector>
|
|
|
|
<!-- 规则弹窗组件 -->
|
|
<rule-popup ref="rulePopup" :confirm-content="recycle_toast" @rule-confirm="onRuleConfirm"
|
|
@pickup-cancel="handlePickupCancel" @pickup-confirm="handlePickupAgree"></rule-popup>
|
|
|
|
<!-- 商品明细弹窗组件 -->
|
|
<product-detail-popup ref="productDetailPopup" @confirm-changes="onDetailConfirmChanges" @close="onDetailPopupClose"></product-detail-popup>
|
|
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import tabBarMixin from '../mixins/tabBarMixin.js'
|
|
import { pinyin } from '../../utils/pinyin.js'
|
|
import tabbar from '../../compoent/base/tabbar.vue'
|
|
import brandSelector from '../../compoent/recycle/brand-selector.vue'
|
|
import bannerSwiper from '../../compoent/base/banner-swiper.vue'
|
|
import rulePopup from '../../compoent/base/rule-popup.vue'
|
|
import productDetailPopup from '../../compoent/recycle/product-detail-popup.vue'
|
|
export default {
|
|
mixins: [tabBarMixin],
|
|
components: {
|
|
tabbar,
|
|
brandSelector,
|
|
bannerSwiper,
|
|
rulePopup,
|
|
productDetailPopup
|
|
},
|
|
data() {
|
|
return {
|
|
value: 1,
|
|
ishow: true,
|
|
// 动态数据
|
|
allProducts: {}, // { [categoryId]: [商品数组] }
|
|
allProductsPage: {}, // { [categoryId]: 当前已加载页码 }
|
|
allProductsTotal: {}, // { [categoryId]: 总数 }
|
|
pageSize: 10,
|
|
currentCategory: 0,
|
|
tabbarHeight: 0,
|
|
showDetailPanel: false,
|
|
ruleImgUrl: '/static/回收/回收规则.png',
|
|
brandCache: {}, // 为每个商品缓存品牌信息 { productId: [brandList] }
|
|
loadingMore: false,
|
|
finished: false,
|
|
pendingBrandIndex: null, // 记录待加一的品牌商品index
|
|
showPriceInfoPopup: false,
|
|
isWaitingForBrandSelection: false, // 等待品牌选择的标志
|
|
reduceItem: null, // 待减少数量的商品
|
|
viewedRuleItems: new Set(), // 已查看过规则的商品ID集合
|
|
loadOptions: null, // 保存options参数
|
|
userInfo: null, // 用户信息
|
|
isUserBlacklisted: false, // 用户是否被拉黑
|
|
currentProductId: null, // 当前查看品牌的商品ID
|
|
searchTimer: null, // 搜索防抖定时器
|
|
isFromPickupFlow: false // 标记是否来自预约流程
|
|
}
|
|
},
|
|
computed: {
|
|
recycle_banner() {
|
|
const item = getApp().globalData.configData.find(i => i.keyName === 'recycle_banner')
|
|
return item ? item.keyContent : ''
|
|
},
|
|
re_key_numer() {
|
|
const item = getApp().globalData.configData.find(i => i.keyName === 're_key_numer')
|
|
return item ? parseFloat(item.keyContent) : 0.066
|
|
},
|
|
recycle_toast() {
|
|
const item = getApp().globalData.configData.find(i => i.keyName === 'recycle_toast')
|
|
return item ? item.keyContent : ''
|
|
},
|
|
huodong_text() {
|
|
const item = getApp().globalData.configData.find(i => i.keyName === 'huodong_text')
|
|
return item ? item.keyContent : ''
|
|
},
|
|
// 当前分类的商品列表
|
|
recycleList() {
|
|
const currentCategoryId = this.categories[this.currentCategory]?.id
|
|
return this.allProducts[currentCategoryId] || []
|
|
},
|
|
// 计算总数量
|
|
totalCount() {
|
|
return Object.values(this.allProducts).reduce((total, categoryItems) => {
|
|
return total + categoryItems.reduce((sum, item) => {
|
|
// 如果商品有品牌款式数量,汇总所有品牌款式的数量
|
|
if (item.brandStyleQuantities && Object.keys(item.brandStyleQuantities).length > 0) {
|
|
return sum + Object.values(item.brandStyleQuantities).reduce((styleSum, qty) => styleSum + qty, 0)
|
|
}
|
|
// 如果商品有品牌数量,汇总所有品牌的数量
|
|
if (item.brandQuantities && Object.keys(item.brandQuantities).length > 0) {
|
|
return sum + Object.values(item.brandQuantities).reduce((brandSum, qty) => brandSum + qty, 0)
|
|
}
|
|
// 否则使用原来的quantity字段
|
|
return sum + (item.quantity || 0)
|
|
}, 0)
|
|
}, 0)
|
|
},
|
|
// 计算总单位文本
|
|
totalUnitText() {
|
|
// 获取所有已选商品的单位
|
|
const units = new Set()
|
|
Object.values(this.allProducts).forEach(categoryItems => {
|
|
categoryItems.forEach(item => {
|
|
let hasQuantity = false
|
|
if (item.brandStyleQuantities && Object.keys(item.brandStyleQuantities).length > 0) {
|
|
hasQuantity = Object.values(item.brandStyleQuantities).some(qty => qty > 0)
|
|
} else if (item.brandQuantities && Object.keys(item.brandQuantities).length > 0) {
|
|
hasQuantity = Object.values(item.brandQuantities).some(qty => qty > 0)
|
|
} else {
|
|
hasQuantity = (item.quantity || 0) > 0
|
|
}
|
|
|
|
if (hasQuantity) {
|
|
units.add(item.unit || '件')
|
|
}
|
|
})
|
|
})
|
|
|
|
// 如果只有一种单位,显示单位;如果混合多种单位,显示"项"
|
|
if (units.size === 0) return '件'
|
|
if (units.size === 1) return Array.from(units)[0]
|
|
return '项'
|
|
},
|
|
// 计算总价格范围
|
|
totalPriceRange() {
|
|
const result = Object.values(this.allProducts).reduce((categoryTotal, categoryItems) => {
|
|
return categoryItems.reduce((sum, item) => {
|
|
// 如果商品有品牌款式数量,使用款式价格计算
|
|
if (item.brandStyleQuantities && Object.keys(item.brandStyleQuantities).length > 0) {
|
|
Object.entries(item.brandStyleQuantities).forEach(([uniqueKey, quantity]) => {
|
|
if (quantity > 0 && item.styleCache && item.styleCache[uniqueKey]) {
|
|
const styleInfo = item.styleCache[uniqueKey].styleInfo
|
|
const minPrice = Number(styleInfo.minPrice) || 0
|
|
const maxPrice = Number(styleInfo.maxPrice) || Number(styleInfo.minPrice) || 0
|
|
sum.min += quantity * minPrice
|
|
sum.max += quantity * maxPrice
|
|
}
|
|
})
|
|
} else {
|
|
let itemQuantity = 0
|
|
// 如果商品有品牌数量,汇总所有品牌的数量
|
|
if (item.brandQuantities && Object.keys(item.brandQuantities).length > 0) {
|
|
itemQuantity = Object.values(item.brandQuantities).reduce((brandSum, qty) => brandSum + qty, 0)
|
|
} else {
|
|
itemQuantity = item.quantity || 0
|
|
}
|
|
|
|
if (itemQuantity > 0) {
|
|
const minPrice = Number(item.price) || 0
|
|
const maxPrice = Number(item.maxPrice) || Number(item.price) || 0
|
|
sum.min += itemQuantity * minPrice
|
|
sum.max += itemQuantity * maxPrice
|
|
}
|
|
}
|
|
|
|
return sum
|
|
}, categoryTotal)
|
|
}, { min: 0, max: 0 })
|
|
|
|
return {
|
|
min: result.min.toFixed(1),
|
|
max: result.max.toFixed(1)
|
|
}
|
|
},
|
|
// 计算总价格 (保持兼容性,使用最低价格)
|
|
totalPrice() {
|
|
return this.totalPriceRange.min
|
|
},
|
|
// 计算价格范围
|
|
priceRange() {
|
|
if (this.totalCount === 0) {
|
|
return {
|
|
min: '0.0',
|
|
max: '0.0'
|
|
}
|
|
}
|
|
return this.totalPriceRange
|
|
},
|
|
selectedProducts() {
|
|
// 返回所有分类下所有已选商品,按品牌款式分组
|
|
const products = []
|
|
Object.values(this.allProducts).flat().forEach(item => {
|
|
if (item.brandStyleQuantities && Object.keys(item.brandStyleQuantities).length > 0) {
|
|
// 按品牌款式分别添加
|
|
Object.entries(item.brandStyleQuantities).forEach(([uniqueKey, quantity]) => {
|
|
if (quantity > 0 && item.styleCache && item.styleCache[uniqueKey]) {
|
|
const { brandInfo, styleInfo } = item.styleCache[uniqueKey]
|
|
products.push({
|
|
...item,
|
|
quantity: quantity,
|
|
brandId: brandInfo.id,
|
|
brandName: brandInfo.name,
|
|
brandImage: brandInfo.logo,
|
|
styleId: styleInfo.id,
|
|
styleName: styleInfo.name,
|
|
styleImage: styleInfo.image,
|
|
price: styleInfo.minPrice, // 使用款式价格
|
|
maxPrice: styleInfo.maxPrice,
|
|
name: item.name, // 保持原商品名称
|
|
uniqueKey: `${item.id}_${uniqueKey}` // 用于区分同商品不同品牌款式
|
|
})
|
|
}
|
|
})
|
|
} else if (item.brandQuantities && Object.keys(item.brandQuantities).length > 0) {
|
|
// 按品牌分别添加(兼容旧数据)
|
|
Object.entries(item.brandQuantities).forEach(([brandId, quantity]) => {
|
|
if (quantity > 0) {
|
|
const brandInfo = this.getBrandInfo(brandId)
|
|
products.push({
|
|
...item,
|
|
quantity: quantity,
|
|
brandId: brandId,
|
|
brandName: brandInfo ? brandInfo.name : '未知品牌',
|
|
brandImage: brandInfo ? brandInfo.logo : '',
|
|
uniqueKey: `${item.id}_${brandId}` // 用于区分同商品不同品牌
|
|
})
|
|
}
|
|
})
|
|
} else if (item.quantity > 0) {
|
|
// 没有品牌的商品
|
|
products.push({
|
|
...item,
|
|
uniqueKey: item.id
|
|
})
|
|
}
|
|
})
|
|
return products
|
|
},
|
|
|
|
bannerList() {
|
|
return getApp().globalData.bannerList || []
|
|
},
|
|
categories() {
|
|
const list = getApp().globalData.pricePreviewList || []
|
|
return list.sort((a, b) => a.sort - b.sort)
|
|
// return list.filter(item => item.pid === '0').sort((a, b) => a.sort - b.sort)
|
|
},
|
|
minMoney() {
|
|
const config = getApp().globalData.configData || [];
|
|
const item = config.find(i => i.keyName === 'min_money');
|
|
return item ? parseFloat(item.keyContent) : 0;
|
|
},
|
|
minMumber() {
|
|
const config = getApp().globalData.configData || [];
|
|
const item = config.find(i => i.keyName === 'min_number');
|
|
return item ? parseFloat(item.keyContent) : 0;
|
|
},
|
|
// 计算比预计回收多的金额(商品回收价格 - (商品回收价格 * 0.066))
|
|
extraRecycleAmount() {
|
|
const minPrice = parseFloat(this.priceRange.min) || 0;
|
|
const maxPrice = parseFloat(this.priceRange.max) || 0;
|
|
|
|
if (minPrice === 0 && maxPrice === 0) {
|
|
return {
|
|
min: '0.00',
|
|
max: '0.00',
|
|
display: '0.00元'
|
|
};
|
|
}
|
|
|
|
let re_key_numer = this.re_key_numer || 0.066
|
|
|
|
// 计算减去6.6%后的金额
|
|
const minExtra = minPrice - (minPrice * re_key_numer);
|
|
const maxExtra = maxPrice - (maxPrice * re_key_numer);
|
|
|
|
// 如果最小值和最大值相等,显示单个值
|
|
if (minPrice === maxPrice) {
|
|
return {
|
|
min: minExtra.toFixed(2),
|
|
max: maxExtra.toFixed(2),
|
|
display: `${minExtra.toFixed(2)}元`
|
|
};
|
|
}
|
|
|
|
// 显示区间
|
|
return {
|
|
min: minExtra.toFixed(2),
|
|
max: maxExtra.toFixed(2),
|
|
display: `${minExtra.toFixed(2)}-${maxExtra.toFixed(2)}元`
|
|
};
|
|
},
|
|
|
|
},
|
|
methods: {
|
|
showPriceInfoPopups() {
|
|
console.log('showPriceInfoPopup called');
|
|
this.isFromPickupFlow = false // 标记是从帮助按钮触发
|
|
this.showPriceInfoPopup = true
|
|
},
|
|
getSelectKey() {
|
|
const keys = ['home', 'recycle', 'my']
|
|
return keys[this.value] || 'recycle'
|
|
},
|
|
fetchGoodsList(categoryId, page = 1, callback) {
|
|
this.$api('getClassGoodsList', {
|
|
classId: categoryId,
|
|
pageNo: page,
|
|
pageSize: this.pageSize
|
|
}, res => {
|
|
if (res.code === 200 && res.result && Array.isArray(res.result.records)) {
|
|
const oldList = this.allProducts[categoryId] || []
|
|
const newList = page === 1 ? res.result.records : oldList.concat(res.result.records)
|
|
this.$set(this.allProducts, categoryId, newList)
|
|
this.$set(this.allProductsPage, categoryId, page)
|
|
this.$set(this.allProductsTotal, categoryId, res.result.total)
|
|
}
|
|
if (callback) callback()
|
|
})
|
|
},
|
|
// 获取分类商品总数
|
|
getCategoryItemCount(index) {
|
|
const categoryId = this.categories[index]?.id
|
|
const categoryItems = this.allProducts[categoryId] || []
|
|
return categoryItems.reduce((sum, item) => {
|
|
if (item.brandStyleQuantities && Object.keys(item.brandStyleQuantities).length > 0) {
|
|
return sum + Object.values(item.brandStyleQuantities).reduce((styleSum, qty) => styleSum + qty, 0)
|
|
}
|
|
if (item.brandQuantities && Object.keys(item.brandQuantities).length > 0) {
|
|
return sum + Object.values(item.brandQuantities).reduce((brandSum, qty) => brandSum + qty, 0)
|
|
}
|
|
return sum + (item.quantity || 0)
|
|
}, 0)
|
|
},
|
|
// 切换分类
|
|
switchCategory(index) {
|
|
this.currentCategory = index
|
|
this.loadingMore = false
|
|
this.finished = false
|
|
const categoryId = this.categories[index]?.id
|
|
// console.log(categoryId,'switchCategory')
|
|
if (!this.allProducts[categoryId]) {
|
|
this.fetchGoodsList(categoryId, 1)
|
|
}
|
|
},
|
|
// 更新商品数量
|
|
updateQuantity(index, delta) {
|
|
const categoryId = this.categories[this.currentCategory]?.id
|
|
const item = this.allProducts[categoryId]?.[index]
|
|
if (!item) return
|
|
|
|
// 如果是减少数量且delta为负数
|
|
if (delta < 0) {
|
|
// 检查是否有多个品牌款式
|
|
if (item.brandStyleQuantities && Object.keys(item.brandStyleQuantities).length > 1) {
|
|
// 有多个品牌款式,显示选择弹窗
|
|
this.reduceItem = { item, index, delta }
|
|
const reduceStyleList = Object.entries(item.brandStyleQuantities)
|
|
.filter(([uniqueKey, quantity]) => quantity > 0)
|
|
.map(([uniqueKey, quantity]) => {
|
|
const cacheInfo = item.styleCache[uniqueKey]
|
|
return {
|
|
uniqueKey,
|
|
quantity,
|
|
name: cacheInfo ? `${cacheInfo.brandInfo.name} - ${cacheInfo.styleInfo.name}` : '未知款式',
|
|
logo: cacheInfo ? cacheInfo.brandInfo.logo : ''
|
|
}
|
|
})
|
|
this.$refs.brandSelector.openReducePopup(reduceStyleList)
|
|
return
|
|
} else if (item.brandStyleQuantities && Object.keys(item.brandStyleQuantities).length === 1) {
|
|
// 只有一个品牌款式,直接减少
|
|
const uniqueKey = Object.keys(item.brandStyleQuantities)[0]
|
|
const currentQty = item.brandStyleQuantities[uniqueKey] || 0
|
|
const newQty = Math.max(0, currentQty + delta)
|
|
this.$set(item.brandStyleQuantities, uniqueKey, newQty)
|
|
|
|
// 如果数量为0,删除该品牌款式
|
|
if (newQty === 0) {
|
|
delete item.brandStyleQuantities[uniqueKey]
|
|
if (item.styleCache && item.styleCache[uniqueKey]) {
|
|
delete item.styleCache[uniqueKey]
|
|
}
|
|
}
|
|
return
|
|
} else if (item.brandQuantities && Object.keys(item.brandQuantities).length > 1) {
|
|
// 有多个品牌,显示选择弹窗(兼容旧数据)
|
|
this.reduceItem = { item, index, delta }
|
|
const reduceBrandList = Object.entries(item.brandQuantities)
|
|
.filter(([brandId, quantity]) => quantity > 0)
|
|
.map(([brandId, quantity]) => {
|
|
const brandInfo = this.getBrandInfo(brandId)
|
|
return {
|
|
brandId,
|
|
quantity,
|
|
name: brandInfo ? brandInfo.name : '未知品牌',
|
|
logo: brandInfo ? brandInfo.logo : ''
|
|
}
|
|
})
|
|
this.$refs.brandSelector.openReducePopup(reduceBrandList)
|
|
return
|
|
} else if (item.brandQuantities && Object.keys(item.brandQuantities).length === 1) {
|
|
// 只有一个品牌,直接减少(兼容旧数据)
|
|
const brandId = Object.keys(item.brandQuantities)[0]
|
|
const currentQty = item.brandQuantities[brandId] || 0
|
|
const newQty = Math.max(0, currentQty + delta)
|
|
this.$set(item.brandQuantities, brandId, newQty)
|
|
|
|
// 如果数量为0,删除该品牌
|
|
if (newQty === 0) {
|
|
delete item.brandQuantities[brandId]
|
|
}
|
|
return
|
|
} else {
|
|
// 没有品牌数量,使用原来的逻辑
|
|
let newQuantity = (item.quantity || 0) + delta
|
|
if (newQuantity < 0) newQuantity = 0
|
|
this.$set(item, 'quantity', newQuantity)
|
|
return
|
|
}
|
|
}
|
|
|
|
// 品牌商品且数量为0且加一时
|
|
if (item.isPin === 'Y' && (item.quantity || 0) === 0 && delta > 0) {
|
|
this.pendingBrandIndex = index
|
|
// 检查是否需要显示回收规则
|
|
if (item.isRecycleRules === 'Y') {
|
|
this.isWaitingForBrandSelection = true;
|
|
this.showRules(item); // 先显示回收规则
|
|
} else {
|
|
// 不需要显示规则,直接打开品牌选择
|
|
this.$refs.brandSelector.open(item.id)
|
|
}
|
|
return
|
|
}
|
|
// 无品牌商品,数量为0且加一时
|
|
if (item.isPin !== 'Y' && (item.quantity || 0) === 0 && delta > 0) {
|
|
this.pendingBrandIndex = index
|
|
// 检查是否需要显示回收规则
|
|
if (item.isRecycleRules === 'Y') {
|
|
this.isWaitingForBrandSelection = false; // 标记为无品牌
|
|
this.showRules(item)
|
|
} else {
|
|
// 不需要显示规则,直接加数量
|
|
let newQuantity = (item.quantity || 0) + delta
|
|
if (newQuantity < 0) newQuantity = 0
|
|
this.$set(item, 'quantity', newQuantity)
|
|
this.pendingBrandIndex = null
|
|
}
|
|
return
|
|
}
|
|
// 其它情况直接加数量
|
|
let newQuantity = (item.quantity || 0) + delta
|
|
if (newQuantity < 0) newQuantity = 0
|
|
this.$set(item, 'quantity', newQuantity)
|
|
},
|
|
// 处理品牌确认事件(新的款式选择流程)
|
|
onBrandConfirm(data) {
|
|
if (this.pendingBrandIndex !== null) {
|
|
const categoryId = this.categories[this.currentCategory]?.id
|
|
const item = this.allProducts[categoryId]?.[this.pendingBrandIndex]
|
|
if (item && data.selectedStyles && data.selectedStyles.length > 0) {
|
|
// 初始化品牌款式数量对象
|
|
if (!item.brandStyleQuantities) {
|
|
this.$set(item, 'brandStyleQuantities', {})
|
|
}
|
|
|
|
// 清理当前品牌的所有款式数据
|
|
const brandPrefix = `${data.brandInfo.id}_`
|
|
Object.keys(item.brandStyleQuantities).forEach(key => {
|
|
if (key.startsWith(brandPrefix)) {
|
|
delete item.brandStyleQuantities[key]
|
|
if (item.styleCache && item.styleCache[key]) {
|
|
delete item.styleCache[key]
|
|
}
|
|
}
|
|
})
|
|
|
|
// 为每个选中的款式设置数量(只保存有数量的款式)
|
|
data.selectedStyles.forEach(style => {
|
|
if (style.quantity > 0) {
|
|
const uniqueKey = `${data.brandInfo.id}_${style.id}`
|
|
this.$set(item.brandStyleQuantities, uniqueKey, style.quantity)
|
|
|
|
// 缓存款式信息用于后续显示
|
|
if (!item.styleCache) {
|
|
this.$set(item, 'styleCache', {})
|
|
}
|
|
this.$set(item.styleCache, uniqueKey, {
|
|
brandInfo: data.brandInfo,
|
|
styleInfo: style
|
|
})
|
|
}
|
|
})
|
|
|
|
// 清除原来的quantity和brandQuantities(如果存在)
|
|
if (item.quantity) {
|
|
this.$set(item, 'quantity', 0)
|
|
}
|
|
if (item.brandQuantities) {
|
|
this.$set(item, 'brandQuantities', {})
|
|
}
|
|
|
|
// 品牌选择完成后自动打开商品明细弹窗
|
|
this.$nextTick(() => {
|
|
this.showDetailPanel = true
|
|
})
|
|
}
|
|
this.pendingBrandIndex = null
|
|
}
|
|
},
|
|
|
|
// 处理减少品牌选择事件
|
|
onReduceSelect(selectInfo) {
|
|
const { item, index, delta } = this.reduceItem
|
|
|
|
if (selectInfo.uniqueKey) {
|
|
// 新的品牌款式减少逻辑
|
|
const currentQty = item.brandStyleQuantities[selectInfo.uniqueKey] || 0
|
|
const newQty = Math.max(0, currentQty + delta)
|
|
|
|
this.$set(item.brandStyleQuantities, selectInfo.uniqueKey, newQty)
|
|
|
|
// 如果数量为0,删除该品牌款式
|
|
if (newQty === 0) {
|
|
delete item.brandStyleQuantities[selectInfo.uniqueKey]
|
|
if (item.styleCache && item.styleCache[selectInfo.uniqueKey]) {
|
|
delete item.styleCache[selectInfo.uniqueKey]
|
|
}
|
|
}
|
|
} else if (selectInfo.brandId) {
|
|
// 兼容旧的品牌减少逻辑
|
|
const currentQty = item.brandQuantities[selectInfo.brandId] || 0
|
|
const newQty = Math.max(0, currentQty + delta)
|
|
|
|
this.$set(item.brandQuantities, selectInfo.brandId, newQty)
|
|
|
|
// 如果数量为0,删除该品牌
|
|
if (newQty === 0) {
|
|
delete item.brandQuantities[selectInfo.brandId]
|
|
}
|
|
}
|
|
|
|
this.reduceItem = null
|
|
},
|
|
|
|
// 处理品牌选择器关闭事件
|
|
onBrandSelectorClose() {
|
|
// 如果用户取消品牌选择,重置状态
|
|
this.pendingBrandIndex = null
|
|
this.isWaitingForBrandSelection = false
|
|
},
|
|
|
|
// 获取已有的款式数量
|
|
getExistingQuantities(brandId, callback) {
|
|
if (this.pendingBrandIndex !== null) {
|
|
const categoryId = this.categories[this.currentCategory]?.id
|
|
const item = this.allProducts[categoryId]?.[this.pendingBrandIndex]
|
|
if (item && item.brandStyleQuantities) {
|
|
// 过滤出当前品牌的款式数量
|
|
const existingQuantities = {}
|
|
Object.entries(item.brandStyleQuantities).forEach(([uniqueKey, quantity]) => {
|
|
if (uniqueKey.startsWith(`${brandId}_`)) {
|
|
existingQuantities[uniqueKey] = quantity
|
|
}
|
|
})
|
|
callback(existingQuantities)
|
|
} else {
|
|
callback({})
|
|
}
|
|
} else {
|
|
callback({})
|
|
}
|
|
},
|
|
|
|
// 打开商品明细弹窗
|
|
openProductDetail(selectedItem) {
|
|
if (!selectedItem.brandId || !selectedItem.styleId) {
|
|
uni.showToast({
|
|
title: '该商品无法查看明细',
|
|
icon: 'none'
|
|
})
|
|
return
|
|
}
|
|
|
|
// 查找原始商品信息
|
|
const originalItem = this.findOriginalItem(selectedItem.id)
|
|
if (!originalItem) {
|
|
uni.showToast({
|
|
title: '商品信息不存在',
|
|
icon: 'none'
|
|
})
|
|
return
|
|
}
|
|
|
|
// 构建商品信息
|
|
const productInfo = {
|
|
id: originalItem.id,
|
|
name: originalItem.name,
|
|
image: originalItem.image
|
|
}
|
|
|
|
// 构建品牌信息
|
|
const brandInfo = {
|
|
id: selectedItem.brandId,
|
|
name: selectedItem.brandName,
|
|
logo: selectedItem.brandImage
|
|
}
|
|
|
|
// 获取该品牌下的所有款式数量
|
|
const existingQuantities = {}
|
|
if (originalItem.brandStyleQuantities) {
|
|
Object.entries(originalItem.brandStyleQuantities).forEach(([uniqueKey, quantity]) => {
|
|
if (uniqueKey.startsWith(`${selectedItem.brandId}_`)) {
|
|
existingQuantities[uniqueKey] = quantity
|
|
}
|
|
})
|
|
}
|
|
|
|
// 打开商品明细弹窗
|
|
this.$refs.productDetailPopup.open(productInfo, brandInfo, existingQuantities, originalItem.styleCache || {})
|
|
},
|
|
|
|
// 处理商品明细确认修改事件
|
|
onDetailConfirmChanges(data) {
|
|
const { productInfo, brandInfo, updatedStyles } = data
|
|
|
|
// 查找原始商品
|
|
const originalItem = this.findOriginalItem(productInfo.id)
|
|
if (!originalItem) return
|
|
|
|
// 清理当前品牌的所有款式数据
|
|
const brandPrefix = `${brandInfo.id}_`
|
|
if (originalItem.brandStyleQuantities) {
|
|
Object.keys(originalItem.brandStyleQuantities).forEach(key => {
|
|
if (key.startsWith(brandPrefix)) {
|
|
delete originalItem.brandStyleQuantities[key]
|
|
if (originalItem.styleCache && originalItem.styleCache[key]) {
|
|
delete originalItem.styleCache[key]
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
// 重新设置款式数据
|
|
if (!originalItem.brandStyleQuantities) {
|
|
this.$set(originalItem, 'brandStyleQuantities', {})
|
|
}
|
|
if (!originalItem.styleCache) {
|
|
this.$set(originalItem, 'styleCache', {})
|
|
}
|
|
|
|
updatedStyles.forEach(style => {
|
|
if (style.quantity > 0) {
|
|
const uniqueKey = `${brandInfo.id}_${style.id}`
|
|
this.$set(originalItem.brandStyleQuantities, uniqueKey, style.quantity)
|
|
this.$set(originalItem.styleCache, uniqueKey, {
|
|
brandInfo: brandInfo,
|
|
styleInfo: style
|
|
})
|
|
}
|
|
})
|
|
|
|
// uni.showToast({
|
|
// title: '修改成功',
|
|
// icon: 'success'
|
|
// })
|
|
},
|
|
|
|
// 处理商品明细弹窗关闭事件
|
|
onDetailPopupClose() {
|
|
// 弹窗关闭时的处理逻辑
|
|
},
|
|
|
|
// 处理规则确认事件
|
|
onRuleConfirm() {
|
|
// 如果是在等待品牌选择的状态下关闭规则弹窗,则接着打开品牌选择
|
|
if (this.isWaitingForBrandSelection) {
|
|
this.isWaitingForBrandSelection = false; // 清除等待状态
|
|
const categoryId = this.categories[this.currentCategory]?.id;
|
|
const item = this.allProducts[categoryId]?.[this.pendingBrandIndex];
|
|
// 记录该商品的规则已被查看
|
|
this.viewedRuleItems.add(item.id);
|
|
this.$refs.brandSelector.open(item.id); // 打开品牌索引弹窗
|
|
} else if (this.pendingBrandIndex !== null) {
|
|
// 无品牌商品,规则弹窗关闭后加数量
|
|
const categoryId = this.categories[this.currentCategory]?.id;
|
|
const item = this.allProducts[categoryId]?.[this.pendingBrandIndex];
|
|
if (item) {
|
|
let newQuantity = (item.quantity || 0) + 1
|
|
this.$set(item, 'quantity', newQuantity)
|
|
}
|
|
this.pendingBrandIndex = null
|
|
}
|
|
},
|
|
// 获取品牌信息
|
|
getBrandInfo(brandId) {
|
|
// 从所有商品的品牌缓存中查找品牌信息
|
|
for (const productId in this.brandCache) {
|
|
const brandInfo = this.brandCache[productId].find(brand => brand.id === brandId)
|
|
if (brandInfo) {
|
|
return brandInfo
|
|
}
|
|
}
|
|
// 如果缓存中没有找到,也从当前brandList中查找(兼容性)
|
|
return this.brandList.find(brand => brand.id === brandId)
|
|
},
|
|
// 获取商品的总数量(所有品牌款式)
|
|
getItemTotalQuantity(item) {
|
|
if (item.brandStyleQuantities && Object.keys(item.brandStyleQuantities).length > 0) {
|
|
return Object.values(item.brandStyleQuantities).reduce((sum, qty) => sum + qty, 0)
|
|
}
|
|
if (item.brandQuantities && Object.keys(item.brandQuantities).length > 0) {
|
|
return Object.values(item.brandQuantities).reduce((sum, qty) => sum + qty, 0)
|
|
}
|
|
return item.quantity || 0
|
|
},
|
|
// 显示回收规则
|
|
showRules(item) {
|
|
// 检查是否需要显示回收规则
|
|
if (item.isRecycleRules !== 'Y') {
|
|
// 不需要显示规则,直接添加数量
|
|
if (item.isPin === 'Y') {
|
|
// 品牌商品,直接打开品牌选择
|
|
this.pendingBrandIndex = this.recycleList.findIndex(i => i.id === item.id)
|
|
this.$refs.brandSelector.open(item.id)
|
|
} else {
|
|
// 非品牌商品,直接加数量
|
|
let newQuantity = (item.quantity || 0) + 1
|
|
this.$set(item, 'quantity', newQuantity)
|
|
}
|
|
return
|
|
}
|
|
|
|
// isPin=Y: 弹规则,读到底部后自动弹品牌;isPin=N: 只弹规则
|
|
if (item.isPin === 'Y') {
|
|
// 检查该商品是否已经查看过规则
|
|
if (this.viewedRuleItems.has(item.id)) {
|
|
// 如果已经查看过,直接跳过规则弹窗,进入品牌选择
|
|
this.isWaitingForBrandSelection = false;
|
|
this.$refs.brandSelector.open(item.id);
|
|
return;
|
|
}
|
|
// 获取回收规则富文本
|
|
this.$api('getGoodsRecycleRule', { goodsId: item.id }, res => {
|
|
const ruleContent = (res.code === 200 && res.result) ? res.result : '<p>暂无回收规则</p>'
|
|
this.$refs.rulePopup.openRulePopup(ruleContent)
|
|
// 规则弹窗关闭后自动弹品牌弹窗逻辑在onRuleConfirm已实现
|
|
})
|
|
} else {
|
|
// isPin=N 只弹规则
|
|
this.$api('getGoodsRecycleRule', { goodsId: item.id }, res => {
|
|
const ruleContent = (res.code === 200 && res.result) ? res.result : '<p>暂无回收规则</p>'
|
|
this.$refs.rulePopup.openRulePopup(ruleContent)
|
|
// 不弹品牌弹窗
|
|
this.isWaitingForBrandSelection = false;
|
|
})
|
|
}
|
|
},
|
|
showMore() {
|
|
uni.showToast({
|
|
title: '更多规则请咨询客服',
|
|
icon: 'none'
|
|
})
|
|
},
|
|
submitOrder() {
|
|
// 检查用户是否被拉入黑名单
|
|
if (this.isUserBlacklisted) {
|
|
uni.showModal({
|
|
title: '提示',
|
|
content: '您的账户已被限制使用回收服务,如有疑问请联系客服。',
|
|
showCancel: false,
|
|
confirmText: '我知道了'
|
|
})
|
|
return
|
|
}
|
|
|
|
if (this.totalCount < this.minMumber || Number(this.totalPrice) < this.minMoney) {
|
|
uni.showToast({
|
|
title: `各品类混合需要满${this.minMumber}${this.totalUnitText}并且各品类混合需要满${this.minMoney}元才能回收哦`,
|
|
icon: 'none'
|
|
})
|
|
return
|
|
}
|
|
this.$refs.rulePopup.openConfirmPopup();
|
|
},
|
|
handlePickupCancel() {
|
|
// 取消回收的处理逻辑
|
|
},
|
|
handlePickupAgree() {
|
|
// 显示总的回收规则弹窗
|
|
this.showGeneralRulesPopup()
|
|
},
|
|
|
|
// 显示总的回收规则弹窗
|
|
showGeneralRulesPopup() {
|
|
this.isFromPickupFlow = true // 标记是从预约流程触发
|
|
this.showPriceInfoPopup = true
|
|
},
|
|
|
|
// 关闭价格说明弹窗的方法
|
|
closePriceInfoPopup() {
|
|
console.log('closePriceInfoPopup called');
|
|
this.showPriceInfoPopup = false
|
|
// 如果是从预约流程触发的,关闭弹窗后执行跳转逻辑
|
|
if (this.isFromPickupFlow) {
|
|
this.isFromPickupFlow = false // 重置标志
|
|
this.executePickupFlow()
|
|
}
|
|
},
|
|
|
|
// 执行预约流程
|
|
executePickupFlow() {
|
|
uni.showLoading({
|
|
title: '提交中...'
|
|
})
|
|
setTimeout(() => {
|
|
uni.hideLoading()
|
|
uni.showToast({
|
|
title: '预约成功',
|
|
icon: 'success'
|
|
})
|
|
this.goToPickup()
|
|
}, 1500)
|
|
},
|
|
goToPickup() {
|
|
// 获取所有选中的衣物(所有分类)
|
|
const selectedItems = this.selectedProducts.map(item => {
|
|
let desc = '允许脏破烂,160码以上'
|
|
if (item.brandName && item.styleName) {
|
|
desc = `品牌:${item.brandName} | 款式:${item.styleName}`
|
|
} else if (item.brandName) {
|
|
desc = `品牌:${item.brandName}`
|
|
} else if (item.styleName) {
|
|
desc = `款式:${item.styleName}`
|
|
}
|
|
|
|
const baseItem = {
|
|
id: item.id,
|
|
name: item.name,
|
|
icon: item.image,
|
|
quantity: item.quantity,
|
|
unitPrice: item.price,
|
|
maxPrice: item.maxPrice,
|
|
desc: desc
|
|
}
|
|
|
|
// 如果有品牌信息,添加品牌相关字段
|
|
if (item.brandId) {
|
|
baseItem.brandId = item.brandId
|
|
baseItem.brandName = item.brandName
|
|
baseItem.brandImage = item.brandImage
|
|
}
|
|
|
|
// 如果有款式信息,添加款式相关字段
|
|
if (item.styleId) {
|
|
baseItem.styleId = item.styleId
|
|
baseItem.styleName = item.styleName
|
|
baseItem.styleImage = item.styleImage
|
|
}
|
|
|
|
return baseItem
|
|
})
|
|
const itemsStr = encodeURIComponent(JSON.stringify(selectedItems))
|
|
uni.navigateTo({
|
|
url: `/pages/subcomponent/pickup?fromRecycle=true&items=${itemsStr}`
|
|
})
|
|
},
|
|
checkBrand(index) {
|
|
const categoryId = this.categories[this.currentCategory]?.id
|
|
const item = this.allProducts[categoryId]?.[index]
|
|
if (item?.id) {
|
|
this.pendingBrandIndex = index
|
|
this.$refs.brandSelector.open(item.id)
|
|
}
|
|
},
|
|
|
|
// 添加下拉刷新方法
|
|
async refreshData() {
|
|
try {
|
|
// 这里可以添加刷新数据的逻辑,比如重新获取商品列表等
|
|
// 示例:重新初始化数据
|
|
this.currentCategory = 0
|
|
Object.values(this.allProducts).forEach(categoryItems => {
|
|
categoryItems.forEach(item => {
|
|
item.quantity = 0
|
|
if (item.brandQuantities) {
|
|
item.brandQuantities = {}
|
|
}
|
|
if (item.brandStyleQuantities) {
|
|
item.brandStyleQuantities = {}
|
|
}
|
|
if (item.styleCache) {
|
|
item.styleCache = {}
|
|
}
|
|
})
|
|
})
|
|
// 清空已查看规则的记录
|
|
this.viewedRuleItems.clear()
|
|
|
|
// 清空品牌缓存
|
|
this.brandCache = {}
|
|
|
|
// 模拟网络请求延迟
|
|
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
|
|
uni.showToast({
|
|
title: '刷新成功',
|
|
icon: 'success'
|
|
})
|
|
} catch (error) {
|
|
uni.showToast({
|
|
title: '刷新失败',
|
|
icon: 'none'
|
|
})
|
|
} finally {
|
|
// 停止下拉刷新动画
|
|
uni.stopPullDownRefresh()
|
|
}
|
|
},
|
|
toggleDetailPanel() {
|
|
this.showDetailPanel = !this.showDetailPanel
|
|
},
|
|
|
|
// 添加更多衣物
|
|
addMoreItems() {
|
|
this.showDetailPanel = false
|
|
},
|
|
fetchUserInfo() {
|
|
if (uni.getStorageSync('token')) {
|
|
this.login_status = getApp().globalData.login_status;
|
|
this.$api("getUserByToken", {}, (res) => {
|
|
if (res.code == 200) {
|
|
this.userInfo = res.result
|
|
// 检查用户是否被拉入黑名单
|
|
this.isUserBlacklisted = res.result.isBlack === 'Y'
|
|
// isTuiType 为0用户,1推广达人,2推广大使
|
|
}
|
|
})
|
|
} else {
|
|
this.login_status = false;
|
|
}
|
|
},
|
|
updateQuantityByProduct(item, delta) {
|
|
// 在明细弹窗中更新数量
|
|
if (item.brandId && item.styleId) {
|
|
// 有品牌和款式ID的商品(新的品牌款式逻辑)
|
|
const originalItem = this.findOriginalItem(item.id)
|
|
if (originalItem && originalItem.brandStyleQuantities) {
|
|
const uniqueKey = `${item.brandId}_${item.styleId}`
|
|
const currentQty = originalItem.brandStyleQuantities[uniqueKey] || 0
|
|
const newQty = Math.max(0, currentQty + delta)
|
|
|
|
if (newQty > 0) {
|
|
this.$set(originalItem.brandStyleQuantities, uniqueKey, newQty)
|
|
} else {
|
|
// 如果数量为0,删除该品牌款式
|
|
delete originalItem.brandStyleQuantities[uniqueKey]
|
|
if (originalItem.styleCache && originalItem.styleCache[uniqueKey]) {
|
|
delete originalItem.styleCache[uniqueKey]
|
|
}
|
|
}
|
|
|
|
// 同步更新显示的数量
|
|
item.quantity = newQty
|
|
}
|
|
} else if (item.brandId) {
|
|
// 有品牌ID但没有款式ID的商品(兼容旧逻辑)
|
|
const originalItem = this.findOriginalItem(item.id)
|
|
if (originalItem && originalItem.brandQuantities) {
|
|
const currentQty = originalItem.brandQuantities[item.brandId] || 0
|
|
const newQty = Math.max(0, currentQty + delta)
|
|
|
|
if (newQty > 0) {
|
|
this.$set(originalItem.brandQuantities, item.brandId, newQty)
|
|
} else {
|
|
// 如果数量为0,删除该品牌
|
|
delete originalItem.brandQuantities[item.brandId]
|
|
}
|
|
|
|
// 同步更新显示的数量
|
|
item.quantity = newQty
|
|
}
|
|
} else {
|
|
// 没有品牌的商品
|
|
if (!item.quantity) item.quantity = 0
|
|
item.quantity = Math.max(0, item.quantity + delta)
|
|
|
|
// 同步到原商品
|
|
const originalItem = this.findOriginalItem(item.id)
|
|
if (originalItem) {
|
|
this.$set(originalItem, 'quantity', item.quantity)
|
|
}
|
|
}
|
|
},
|
|
|
|
// 查找原始商品对象
|
|
findOriginalItem(itemId) {
|
|
for (const categoryItems of Object.values(this.allProducts)) {
|
|
const item = categoryItems.find(i => i.id === itemId)
|
|
if (item) return item
|
|
}
|
|
return null
|
|
},
|
|
|
|
loadMoreGoods() {
|
|
const categoryId = this.categories[this.currentCategory]?.id
|
|
const page = (this.allProductsPage[categoryId] || 1) + 1
|
|
const total = this.allProductsTotal[categoryId] || 0
|
|
const loaded = (this.allProducts[categoryId] || []).length
|
|
|
|
if (this.loadingMore || this.finished) return
|
|
|
|
if (loaded < total) {
|
|
this.loadingMore = true
|
|
this.fetchGoodsList(categoryId, page, () => {
|
|
this.loadingMore = false
|
|
// 判断是否加载完
|
|
const newLoaded = (this.allProducts[categoryId] || []).length
|
|
this.finished = newLoaded >= (this.allProductsTotal[categoryId] || 0)
|
|
})
|
|
} else {
|
|
this.finished = true
|
|
}
|
|
},
|
|
|
|
// 初始化页面数据的方法
|
|
initializePageData() {
|
|
const options = this.loadOptions || {}
|
|
|
|
if (options && options.categoryId) {
|
|
const idx = this.categories.findIndex(c => c.id == options.categoryId)
|
|
if (idx !== -1) this.currentCategory = idx
|
|
}
|
|
|
|
if (this.categories.length > 0) {
|
|
this.fetchGoodsList(this.categories[this.currentCategory].id, 1)
|
|
}
|
|
|
|
uni.$on('bannerListUpdated', () => {
|
|
this.$forceUpdate && this.$forceUpdate()
|
|
})
|
|
|
|
if (getApp().globalData.bannerList && getApp().globalData.bannerList.length > 0) {
|
|
this.$forceUpdate && this.$forceUpdate()
|
|
}
|
|
|
|
// 检查全局清空标志(兼容 reLaunch)
|
|
if (getApp().globalData.shouldClearRecycle) {
|
|
Object.values(this.allProducts).forEach(categoryItems => {
|
|
categoryItems.forEach(item => {
|
|
this.$set(item, 'quantity', 0)
|
|
if (item.brandQuantities) {
|
|
this.$set(item, 'brandQuantities', {})
|
|
}
|
|
if (item.brandStyleQuantities) {
|
|
this.$set(item, 'brandStyleQuantities', {})
|
|
}
|
|
if (item.styleCache) {
|
|
this.$set(item, 'styleCache', {})
|
|
}
|
|
})
|
|
})
|
|
// 清空已查看规则的记录
|
|
this.viewedRuleItems.clear()
|
|
this.showDetailPanel = false
|
|
this.brandCache = {} // 清空品牌缓存
|
|
this.$forceUpdate()
|
|
getApp().globalData.shouldClearRecycle = false
|
|
}
|
|
},
|
|
|
|
},
|
|
created() {
|
|
this.currentCategory = 0
|
|
this.$nextTick(() => {
|
|
if (this.categories.length > 0) {
|
|
const firstCategoryId = this.categories[0]?.id
|
|
if (firstCategoryId) {
|
|
this.fetchGoodsList(firstCategoryId, 1)
|
|
}
|
|
}
|
|
})
|
|
},
|
|
mounted() {
|
|
this.$nextTick(() => {
|
|
const query = uni.createSelectorQuery().in(this)
|
|
query.select('.uv-tabbar').boundingClientRect(rect => {
|
|
if (rect && rect.height) {
|
|
this.tabbarHeight = rect.height
|
|
} else {
|
|
this.tabbarHeight = uni.upx2px ? uni.upx2px(95) : 45
|
|
}
|
|
// console.log(this.tabbarHeight,'tabbarHeight')
|
|
}).exec()
|
|
})
|
|
},
|
|
onLoad(options) {
|
|
// 保存options参数
|
|
this.loadOptions = options
|
|
|
|
// 检查App数据是否已经准备好
|
|
if (!getApp().globalData.isAppDataReady) {
|
|
// 显示加载状态
|
|
uni.showLoading({
|
|
title: '加载中...',
|
|
mask: true
|
|
})
|
|
|
|
// 监听App数据准备完成事件
|
|
uni.$on('appDataReady', () => {
|
|
uni.hideLoading()
|
|
this.initializePageData()
|
|
})
|
|
} else {
|
|
// App数据已经准备好,直接初始化页面数据
|
|
this.initializePageData()
|
|
}
|
|
},
|
|
|
|
onUnload() {
|
|
uni.$off('bannerListUpdated')
|
|
// 移除事件监听
|
|
uni.$off('clearRecycleOrderData')
|
|
},
|
|
onShow() {
|
|
// 获取用户信息,检查黑名单状态
|
|
this.fetchUserInfo()
|
|
|
|
const id = getApp().globalData.targetRecycleCategoryId
|
|
if (id) {
|
|
const trySwitch = () => {
|
|
if (this.categories.length > 0) {
|
|
const idx = this.categories.findIndex(c => String(c.id) === String(id))
|
|
if (idx !== -1) {
|
|
this.currentCategory = idx
|
|
const categoryId = this.categories[idx]?.id
|
|
if (categoryId && !this.allProducts[categoryId]) {
|
|
this.loadingMore = false
|
|
this.finished = false
|
|
this.fetchGoodsList(categoryId, 1)
|
|
}
|
|
}
|
|
getApp().globalData.targetRecycleCategoryId = null
|
|
} else {
|
|
setTimeout(trySwitch, 100)
|
|
}
|
|
}
|
|
trySwitch()
|
|
}
|
|
// 检查全局清空标志
|
|
if (getApp().globalData.shouldClearRecycle) {
|
|
Object.values(this.allProducts).forEach(categoryItems => {
|
|
categoryItems.forEach(item => {
|
|
this.$set(item, 'quantity', 0)
|
|
if (item.brandQuantities) {
|
|
this.$set(item, 'brandQuantities', {})
|
|
}
|
|
if (item.brandStyleQuantities) {
|
|
this.$set(item, 'brandStyleQuantities', {})
|
|
}
|
|
if (item.styleCache) {
|
|
this.$set(item, 'styleCache', {})
|
|
}
|
|
})
|
|
})
|
|
// 清空已查看规则的记录
|
|
this.viewedRuleItems.clear()
|
|
this.showDetailPanel = false
|
|
this.brandCache = {} // 清空品牌缓存
|
|
this.$forceUpdate()
|
|
getApp().globalData.shouldClearRecycle = false
|
|
}
|
|
// 监听清除订单数据的事件
|
|
uni.$on('clearRecycleOrderData', () => {
|
|
// 清除所有商品的选中数量,保证响应式
|
|
Object.values(this.allProducts).forEach(categoryItems => {
|
|
categoryItems.forEach(item => {
|
|
this.$set(item, 'quantity', 0)
|
|
if (item.brandQuantities) {
|
|
this.$set(item, 'brandQuantities', {})
|
|
}
|
|
if (item.brandStyleQuantities) {
|
|
this.$set(item, 'brandStyleQuantities', {})
|
|
}
|
|
if (item.styleCache) {
|
|
this.$set(item, 'styleCache', {})
|
|
}
|
|
})
|
|
})
|
|
// 清空已查看规则的记录
|
|
this.viewedRuleItems.clear()
|
|
// 清空品牌缓存
|
|
this.brandCache = {}
|
|
// 重置其他相关数据
|
|
this.showDetailPanel = false
|
|
this.$forceUpdate()
|
|
})
|
|
},
|
|
watch: {
|
|
categories(newVal) {
|
|
const id = getApp().globalData.targetRecycleCategoryId
|
|
const idx = newVal.findIndex(c => String(c.id) === String(id))
|
|
if (id && newVal.length > 0 && idx !== -1) {
|
|
this.currentCategory = idx
|
|
getApp().globalData.targetRecycleCategoryId = null
|
|
// 自动加载右侧商品
|
|
const categoryId = newVal[idx]?.id
|
|
if (categoryId && !this.allProducts[categoryId]) {
|
|
this.loadingMore = false
|
|
this.finished = false
|
|
this.fetchGoodsList(categoryId, 1)
|
|
}
|
|
}
|
|
}
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 100vh;
|
|
background-color: #f5f5f5;
|
|
overflow: hidden;
|
|
}
|
|
|
|
|
|
|
|
.goods-list {
|
|
// flex: 1;
|
|
display: flex;
|
|
position: relative;
|
|
height: calc(110vh - 320rpx - 160rpx - env(safe-area-inset-bottom));
|
|
/* 减去banner、底部栏和绿色提示条的高度 */
|
|
margin-top: -10rpx;
|
|
z-index: 2;
|
|
border-radius: 20rpx 20rpx 0 0;
|
|
overflow: hidden;
|
|
padding: 30rpx;
|
|
box-shadow: 0 -4rpx 8rpx rgba(0, 0, 0, 0.05);
|
|
background: linear-gradient(to bottom, #fff7e8, 20%, #ffffff);
|
|
|
|
.category-nav {
|
|
width: 20%;
|
|
background: #ffffff;
|
|
height: 100%;
|
|
border-right: 1rpx solid rgba(255, 126, 14, 0.1);
|
|
margin: 1rpx;
|
|
border-radius: 20rpx 0 0 0;
|
|
margin-right: 20rpx;
|
|
overflow-y: auto;
|
|
scrollbar-width: none;
|
|
/* Firefox */
|
|
-ms-overflow-style: none;
|
|
|
|
/* IE and Edge */
|
|
&::-webkit-scrollbar {
|
|
width: 0 !important;
|
|
display: none;
|
|
/* Chrome, Safari, Opera */
|
|
}
|
|
|
|
.category-item {
|
|
position: relative;
|
|
padding: 28rpx 20rpx;
|
|
text-align: center;
|
|
font-family: PingFang SC;
|
|
font-weight: 600;
|
|
font-size: 15px;
|
|
line-height: 100%;
|
|
letter-spacing: 0px;
|
|
color: #666;
|
|
|
|
.category-dot {
|
|
position: absolute;
|
|
top: 15rpx;
|
|
right: 15rpx;
|
|
min-width: 32rpx;
|
|
height: 32rpx;
|
|
padding: 0 6rpx;
|
|
background: #ff7a0e;
|
|
border-radius: 16rpx;
|
|
color: #fff;
|
|
font-size: 20rpx;
|
|
text-align: center;
|
|
line-height: 32rpx;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
&.active {
|
|
color: #ff7a0e;
|
|
font-weight: bold;
|
|
background: #fff7e8;
|
|
position: relative;
|
|
|
|
&::before {
|
|
content: '';
|
|
position: absolute;
|
|
left: 0;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
width: 6rpx;
|
|
height: 36rpx;
|
|
background: #ff7a0e;
|
|
border-radius: 3rpx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.goods-content {
|
|
flex: 1;
|
|
height: 100%;
|
|
padding: 0 0 180rpx 0;
|
|
/* 添加底部padding,为固定底部栏预留空间 */
|
|
background: #ffffff;
|
|
width: 70%;
|
|
margin: 1rpx;
|
|
margin-left: 0;
|
|
border-radius: 0 20rpx 0 0;
|
|
overflow-y: auto;
|
|
box-sizing: border-box;
|
|
scrollbar-width: none;
|
|
/* Firefox */
|
|
-ms-overflow-style: none;
|
|
|
|
/* IE and Edge */
|
|
&::-webkit-scrollbar {
|
|
width: 0 !important;
|
|
display: none;
|
|
/* Chrome, Safari, Opera */
|
|
}
|
|
}
|
|
}
|
|
|
|
.goods-item {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
padding: 30rpx 0;
|
|
border-bottom: 1rpx solid #f5f5f5;
|
|
|
|
.goods-img-container {
|
|
position: relative;
|
|
width: 180rpx;
|
|
height: 180rpx;
|
|
margin-right: 28rpx;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.goods-item-img {
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 24rpx;
|
|
background: #f8f8f8;
|
|
object-fit: contain;
|
|
}
|
|
|
|
.brand-tag {
|
|
position: absolute;
|
|
top: 0rpx;
|
|
left: 0rpx;
|
|
background: rgba(0, 0, 0, 0.8);
|
|
color: #fff;
|
|
font-size: 20rpx;
|
|
padding: 4rpx 8rpx;
|
|
border-radius: 8rpx;
|
|
z-index: 2;
|
|
}
|
|
|
|
.goods-info-wrap {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
min-width: 0;
|
|
}
|
|
|
|
.goods-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 10rpx;
|
|
}
|
|
|
|
.goods-name {
|
|
font-family: PingFang SC;
|
|
font-weight: 500;
|
|
font-size: 14px;
|
|
line-height: 140%;
|
|
letter-spacing: 0%;
|
|
vertical-align: middle;
|
|
color: #333;
|
|
font-weight: bold;
|
|
flex-shrink: 1;
|
|
flex-grow: 1;
|
|
}
|
|
|
|
.brand-check-placeholder {
|
|
flex-shrink: 0;
|
|
margin-left: 10rpx;
|
|
}
|
|
|
|
.brand-check {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border: 1px solid #f8a01d;
|
|
border-radius: 8rpx;
|
|
color: #ff7a0e;
|
|
font-family: PingFang SC;
|
|
font-weight: 400;
|
|
font-size: 12px;
|
|
padding: 4rpx 10rpx;
|
|
line-height: 1;
|
|
white-space: nowrap;
|
|
|
|
text {
|
|
margin-right: 4rpx;
|
|
}
|
|
}
|
|
|
|
.goods-desc {
|
|
font-size: 20rpx;
|
|
color: #999;
|
|
display: block;
|
|
// margin-bottom: 20rpx;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.goods-info {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
flex-wrap: nowrap;
|
|
gap: 5rpx;
|
|
margin-top: 10rpx;
|
|
}
|
|
|
|
.price-info {
|
|
display: flex;
|
|
align-items: baseline;
|
|
white-space: nowrap;
|
|
flex-shrink: 0;
|
|
|
|
.price-symbol {
|
|
font-size: 24rpx;
|
|
color: #ff7a0e;
|
|
}
|
|
|
|
.price-value {
|
|
font-size: 36rpx;
|
|
color: #ff7a0e;
|
|
font-weight: bold;
|
|
margin: 0 0rpx;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.price-unit {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
white-space: nowrap;
|
|
}
|
|
}
|
|
|
|
.quantity-control {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-shrink: 0;
|
|
white-space: nowrap;
|
|
|
|
button {
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
padding: 0;
|
|
margin: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 28rpx;
|
|
color: #666;
|
|
background: #ffffff;
|
|
border: none;
|
|
border-radius: 50%;
|
|
|
|
&::after {
|
|
border: none;
|
|
}
|
|
|
|
&:active {
|
|
opacity: 0.8;
|
|
}
|
|
}
|
|
|
|
.quantity {
|
|
width: 50rpx;
|
|
text-align: center;
|
|
font-size: 32rpx;
|
|
color: #333;
|
|
}
|
|
}
|
|
|
|
.rules-brand-row {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-top: 20rpx;
|
|
gap: 16rpx;
|
|
|
|
.rules-link {
|
|
margin-top: 0;
|
|
|
|
.rules {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
font-family: PingFang SC;
|
|
font-weight: 400;
|
|
font-size: 12px;
|
|
color: #666;
|
|
white-space: nowrap;
|
|
}
|
|
}
|
|
|
|
.brand-check-placeholder {
|
|
margin-left: 12rpx;
|
|
}
|
|
}
|
|
}
|
|
|
|
.other-unrecycle-card {
|
|
display: flex;
|
|
align-items: center;
|
|
background: #fff;
|
|
border-radius: 24rpx;
|
|
box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06);
|
|
padding: 30rpx 30rpx 30rpx 30rpx;
|
|
margin: 30rpx 0 0 0;
|
|
}
|
|
|
|
.other-unrecycle-img {
|
|
width: 120rpx;
|
|
height: 120rpx;
|
|
border-radius: 24rpx;
|
|
background: #f8f8f8;
|
|
margin-right: 28rpx;
|
|
object-fit: contain;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.other-unrecycle-info {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
min-width: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.other-unrecycle-title {
|
|
font-size: 30rpx;
|
|
color: #222;
|
|
font-weight: bold;
|
|
margin-bottom: 8rpx;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.other-unrecycle-desc {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
margin-bottom: 12rpx;
|
|
text-overflow: ellipsis;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.other-unrecycle-price-row {
|
|
display: flex;
|
|
align-items: center;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.other-unrecycle-price {
|
|
font-size: 28rpx;
|
|
color: #ff9c00;
|
|
font-weight: bold;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.other-unrecycle-btn {
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
margin-left: 24rpx;
|
|
border-radius: 50%;
|
|
background: #fff;
|
|
color: #666;
|
|
font-size: 36rpx;
|
|
border: none;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.fixed-bottom-wrap {
|
|
position: fixed;
|
|
padding-bottom: 120rpx;
|
|
left: 0;
|
|
bottom: calc(env(safe-area-inset-bottom));
|
|
// bottom: calc(v-bind('tabbarHeight + "rpx"') + env(safe-area-inset-bottom));
|
|
width: 100vw;
|
|
z-index: 100;
|
|
background: transparent;
|
|
box-sizing: border-box;
|
|
pointer-events: auto;
|
|
}
|
|
|
|
.bottom-bar-divider {
|
|
width: 100%;
|
|
height: 1px;
|
|
background: #f0f0f0;
|
|
position: absolute;
|
|
left: 0;
|
|
bottom: 0;
|
|
z-index: 1;
|
|
}
|
|
|
|
.green-tip-bar {
|
|
width: 100%;
|
|
background: #eaffea;
|
|
color: #13ac47;
|
|
font-size: 20rpx;
|
|
padding: 8rpx 30rpx;
|
|
box-sizing: border-box;
|
|
text-align: center;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
line-height: 1.4;
|
|
min-height: 40rpx;
|
|
|
|
.tip-highlight {
|
|
color: #ff9c00;
|
|
font-weight: bold;
|
|
font-size: 20rpx;
|
|
}
|
|
}
|
|
|
|
.bottom-bar {
|
|
width: 100%;
|
|
background-color: #fff;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0 30rpx;
|
|
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
|
|
height: 120rpx;
|
|
border-top-left-radius: 0;
|
|
border-top-right-radius: 0;
|
|
border-bottom-left-radius: env(safe-area-inset-bottom);
|
|
border-bottom-right-radius: env(safe-area-inset-bottom);
|
|
|
|
.bottom-left {
|
|
// flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
|
|
.summary-row {
|
|
display: flex;
|
|
align-items: center;
|
|
font-size: 26rpx;
|
|
color: #333;
|
|
|
|
.summary-label {
|
|
color: #333;
|
|
}
|
|
|
|
.summary-count {
|
|
color: #ff9c00;
|
|
font-weight: bold;
|
|
font-size: 28rpx;
|
|
}
|
|
}
|
|
|
|
.amount-row {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-top: 4rpx;
|
|
|
|
.amount {
|
|
color: #ff9c00;
|
|
font-size: 44rpx;
|
|
font-weight: bold;
|
|
vertical-align: middle;
|
|
}
|
|
}
|
|
}
|
|
|
|
.submit-btn {
|
|
width: 300rpx;
|
|
height: 88rpx;
|
|
background: linear-gradient(to right, #ffd01e, #ff8917);
|
|
border-radius: 44rpx;
|
|
color: #fff;
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border: none;
|
|
// margin-left: 0rpx;
|
|
box-shadow: 0 4rpx 16rpx rgba(255, 156, 0, 0.08);
|
|
|
|
&::after {
|
|
border: none;
|
|
}
|
|
|
|
&:active {
|
|
opacity: 0.9;
|
|
}
|
|
}
|
|
}
|
|
|
|
.detail-popup-mask {
|
|
position: fixed;
|
|
left: 0;
|
|
right: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
// padding-bottom: calc(env(safe-area-inset-bottom));
|
|
// bottom: calc(120rpx + env(safe-area-inset-bottom));
|
|
// bottom: calc(90rpx + env(safe-area-inset-bottom));
|
|
/* tabbar高度+安全区 */
|
|
background: rgba(0, 0, 0, 0.35);
|
|
z-index: 9999;
|
|
display: flex;
|
|
align-items: flex-end;
|
|
justify-content: center;
|
|
}
|
|
|
|
.detail-popup {
|
|
width: 100vw;
|
|
max-width: none;
|
|
background: #fff;
|
|
border-radius: 48rpx 48rpx 0 0;
|
|
box-shadow: 0 8rpx 48rpx rgba(0, 0, 0, 0.18);
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
position: relative;
|
|
padding: 0;
|
|
padding-bottom: calc(env(safe-area-inset-bottom));
|
|
overflow: hidden;
|
|
min-height: 80vh;
|
|
bottom: 0;
|
|
}
|
|
|
|
.detail-popup-close {
|
|
position: absolute;
|
|
right: 36rpx;
|
|
top: 36rpx;
|
|
font-size: 36rpx;
|
|
color: #bbb;
|
|
z-index: 2;
|
|
}
|
|
|
|
.popup-green-tip {
|
|
border-radius: 48rpx 48rpx 0 0;
|
|
font-size: 20rpx;
|
|
padding: 24rpx 30rpx 0 30rpx;
|
|
background: #eaffea;
|
|
color: #13ac47;
|
|
text-align: left;
|
|
}
|
|
|
|
.panel-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
padding: 40rpx 36rpx 0 36rpx;
|
|
background: #fff;
|
|
position: relative;
|
|
}
|
|
|
|
.panel-title {
|
|
font-size: 32rpx;
|
|
color: #222;
|
|
font-weight: bold;
|
|
text-align: center;
|
|
flex: 1;
|
|
}
|
|
|
|
.popup-panel-list {
|
|
// flex: 1;
|
|
width: 710rpx;
|
|
overflow-y: auto;
|
|
height: 70vh !important;
|
|
padding: 0 24rpx;
|
|
scrollbar-width: none;
|
|
/* Firefox */
|
|
-ms-overflow-style: none;
|
|
|
|
/* IE and Edge */
|
|
&::-webkit-scrollbar {
|
|
width: 0 !important;
|
|
display: none;
|
|
/* Chrome, Safari, Opera */
|
|
}
|
|
}
|
|
|
|
.panel-item {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: flex-start;
|
|
padding: 24rpx 0;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
cursor: pointer;
|
|
|
|
&:active {
|
|
// background: #f8f8f8;
|
|
}
|
|
}
|
|
|
|
.panel-img-container {
|
|
position: relative;
|
|
width: 100rpx;
|
|
height: 100rpx;
|
|
margin-right: 20rpx;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.panel-item-img {
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 16rpx;
|
|
background: #f8f8f8;
|
|
}
|
|
|
|
.panel-brand-tag {
|
|
position: absolute;
|
|
top: 0rpx;
|
|
left: 0rpx;
|
|
background: rgba(0, 0, 0, 0.8);
|
|
color: #fff;
|
|
font-size: 18rpx;
|
|
padding: 2rpx 6rpx;
|
|
border-radius: 6rpx;
|
|
z-index: 2;
|
|
}
|
|
|
|
.panel-item-info {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
min-width: 0;
|
|
|
|
}
|
|
|
|
.panel-item-name {
|
|
font-size: 28rpx;
|
|
color: #222;
|
|
font-weight: bold;
|
|
margin-bottom: 4rpx;
|
|
text-overflow: ellipsis;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.panel-item-desc {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
margin-bottom: 4rpx;
|
|
text-overflow: ellipsis;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.panel-item-price {
|
|
font-size: 26rpx;
|
|
color: #ff9c00;
|
|
margin-top: 2rpx;
|
|
}
|
|
|
|
.panel-quantity-control {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-left: 20rpx;
|
|
// margin-right: 30rpx;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.panel-quantity-control button {
|
|
width: 48rpx;
|
|
height: 48rpx;
|
|
padding: 0;
|
|
margin: 0 8rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 32rpx;
|
|
color: #666;
|
|
background: #ffffff;
|
|
border: none;
|
|
border-radius: 50%;
|
|
|
|
&::after {
|
|
border: none;
|
|
}
|
|
|
|
&:active {
|
|
opacity: 0.8;
|
|
}
|
|
}
|
|
|
|
.panel-quantity-control .quantity {
|
|
width: 30rpx;
|
|
text-align: center;
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
}
|
|
|
|
.popup-bottom-bar {
|
|
width: 100%;
|
|
background-color: #fff;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0 30rpx;
|
|
box-sizing: border-box;
|
|
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
|
|
height: 120rpx;
|
|
border-top: 1px solid #f0f0f0;
|
|
border-bottom-left-radius: 48rpx;
|
|
border-bottom-right-radius: 48rpx;
|
|
|
|
// padding-bottom: env(safe-area-inset-bottom);
|
|
.bottom-left {
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
|
|
.summary-row {
|
|
display: flex;
|
|
align-items: center;
|
|
font-size: 26rpx;
|
|
color: #333;
|
|
|
|
.summary-label {
|
|
color: #333;
|
|
}
|
|
|
|
.summary-count {
|
|
color: #ff9c00;
|
|
font-weight: bold;
|
|
font-size: 28rpx;
|
|
}
|
|
}
|
|
|
|
.amount-row {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-top: 4rpx;
|
|
|
|
.amount {
|
|
color: #ff9c00;
|
|
font-size: 44rpx;
|
|
font-weight: bold;
|
|
vertical-align: middle;
|
|
}
|
|
}
|
|
}
|
|
|
|
.submit-btn {
|
|
width: 300rpx;
|
|
height: 88rpx;
|
|
background: linear-gradient(to right, #ffd01e, #ff8917);
|
|
border-radius: 44rpx;
|
|
color: #fff;
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border: none;
|
|
box-shadow: 0 4rpx 16rpx rgba(255, 156, 0, 0.08);
|
|
|
|
&::after {
|
|
border: none;
|
|
}
|
|
|
|
&:active {
|
|
opacity: 0.9;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 添加衣物浮窗按钮 */
|
|
.floating-add-btn {
|
|
position: absolute;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
bottom: 210rpx;
|
|
width: 160rpx;
|
|
height: 80rpx;
|
|
background: linear-gradient(to right, #ffd01e, #ff8917);
|
|
border-radius: 40rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
box-shadow: 0 8rpx 24rpx rgba(255, 156, 0, 0.3);
|
|
z-index: 10;
|
|
|
|
&:active {
|
|
opacity: 0.9;
|
|
transform: translateX(-50%) scale(0.95);
|
|
}
|
|
|
|
.floating-btn-text {
|
|
color: #fff;
|
|
font-size: 28rpx;
|
|
font-weight: bold;
|
|
line-height: 1;
|
|
text-align: center;
|
|
}
|
|
}
|
|
|
|
.uv-tabbar {
|
|
z-index: 1000;
|
|
}
|
|
|
|
.loading-more {
|
|
text-align: center;
|
|
color: #999;
|
|
padding: 20rpx 0;
|
|
font-size: 26rpx;
|
|
}
|
|
|
|
|
|
.price-info-popup-mask {
|
|
position: fixed;
|
|
left: 0;
|
|
right: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
background: rgba(0, 0, 0, 0.4);
|
|
z-index: 996000;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.price-info-popup {
|
|
width: 85vw;
|
|
max-width: 600rpx;
|
|
background: #fff;
|
|
border-radius: 24rpx;
|
|
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.12);
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
position: relative;
|
|
padding: 40rpx 40rpx;
|
|
|
|
.price-info-popup-title {
|
|
font-size: 34rpx;
|
|
color: #333;
|
|
font-weight: bold;
|
|
text-align: center;
|
|
margin-bottom: 30rpx;
|
|
}
|
|
|
|
.price-info-popup-content {
|
|
width: 100%;
|
|
max-height: 50vh;
|
|
|
|
.price-info-section {
|
|
margin-bottom: 30rpx;
|
|
|
|
&:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.price-info-heading {
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
font-weight: 500;
|
|
margin-bottom: 15rpx;
|
|
}
|
|
|
|
.price-info-text {
|
|
font-size: 26rpx;
|
|
color: #666;
|
|
line-height: 1.6;
|
|
}
|
|
}
|
|
}
|
|
|
|
.price-info-popup-btn {
|
|
width: 100%;
|
|
height: 88rpx;
|
|
background: linear-gradient(to right, #ffd01e, #ff8917);
|
|
border-radius: 44rpx;
|
|
color: #fff;
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border: none;
|
|
margin-top: 40rpx;
|
|
box-shadow: 0 4rpx 16rpx rgba(255, 156, 0, 0.08);
|
|
|
|
&::after {
|
|
border: none;
|
|
}
|
|
|
|
&:active {
|
|
opacity: 0.9;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.rules-link {
|
|
min-width: 90rpx;
|
|
padding: 0 12rpx;
|
|
|
|
.rules {
|
|
font-size: 15px;
|
|
white-space: normal;
|
|
overflow: visible;
|
|
}
|
|
}
|
|
|
|
// ... existing code ...
|
|
.rules-brand-row {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-top: 20rpx;
|
|
gap: 24rpx; // 增大间距
|
|
|
|
.rules-link {
|
|
margin-top: 0;
|
|
}
|
|
|
|
.brand-check-placeholder {
|
|
margin-left: 16rpx;
|
|
}
|
|
}
|
|
|
|
// ... existing code ...
|
|
.price-info {
|
|
display: flex;
|
|
align-items: baseline;
|
|
white-space: nowrap;
|
|
flex-shrink: 0;
|
|
gap: 12rpx; // 增大间距
|
|
|
|
.price-symbol {
|
|
font-size: 32rpx; // 增大符号
|
|
color: #ff7a0e;
|
|
}
|
|
|
|
.price-value {
|
|
font-size: 44rpx; // 增大数字
|
|
color: #ff7a0e;
|
|
font-weight: bold;
|
|
margin: 0 6rpx;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.price-unit {
|
|
font-size: 28rpx;
|
|
color: #999;
|
|
white-space: nowrap;
|
|
}
|
|
}
|
|
|
|
.quantity-control {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-shrink: 0;
|
|
white-space: nowrap;
|
|
gap: 0rpx; // 增大间距
|
|
|
|
button {
|
|
width: 30rpx; // 增大按钮
|
|
height: 72rpx;
|
|
padding: 0;
|
|
margin: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 36rpx; // 增大符号
|
|
color: #666;
|
|
background: #ffffff;
|
|
border: none;
|
|
border-radius: 50%;
|
|
|
|
&::after {
|
|
border: none;
|
|
}
|
|
|
|
&:active {
|
|
opacity: 0.8;
|
|
}
|
|
}
|
|
|
|
.quantity {
|
|
width: 60rpx;
|
|
text-align: center;
|
|
font-size: 36rpx; // 增大数字
|
|
color: #333;
|
|
}
|
|
}
|
|
</style>
|