爱简收旧衣按件回收前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

1679 lines
44 KiB

<template>
<view class="container">
<!-- 顶部banner -->
<view class="banner">
<swiper
:indicator-dots="false"
:autoplay="true"
:interval="3000"
:duration="500"
circular
style="width: 100%; height: 400rpx;"
>
<swiper-item v-for="(item, index) in bannerList" :key="item.id || index">
<image :src="item.image" mode="aspectFill" style="width: 100%; height: 100%;" />
</swiper-item>
</swiper>
</view>
<!-- 商品列表 -->
<view class="goods-list">
<!-- 左侧分类导航 -->
<scroll-view class="category-nav" scroll-y>
<view
v-for="(category, index) in categories"
:key="category.id || index"
class="category-item"
:class="{ active: currentCategory === index }"
@tap="switchCategory(index)"
>
<view class="category-dot" v-if="getCategoryItemCount(index) > 0"></view>
{{ category.title }}
</view>
</scroll-view>
<!-- 右侧商品列表 -->
<scroll-view class="goods-content" scroll-y @scrolltolower="loadMoreGoods" style="height: 70vh">
<view class="goods-section">
<view class="goods-item" v-for="(item, index) in recycleList" :key="index">
<image v-if="item.image" :src="item.image" class="goods-item-img" mode="aspectFit" />
<view class="goods-info-wrap">
<view class="goods-header">
<text class="goods-name">{{item.name}}</text>
<view class="rules-link" @tap="showRules(item)">
<view class="rules">
<text>回收规则</text>
<uni-icons type="right" size="14" color="#999"></uni-icons>
</view>
</view>
</view>
<text class="goods-desc">{{item.desc}}</text>
<view class="goods-info">
<view class="price-info">
<text class="price-symbol">¥</text>
<text class="price-value">{{item.price}}</text>
<text class="price-unit">/件</text>
</view>
<view class="quantity-control">
<button class="btn-minus" @tap="updateQuantity(index, -1)">-</button>
<text class="quantity">{{item.quantity || 0}}</text>
<button class="btn-plus" @tap="updateQuantity(index, 1)">+</button>
</view>
</view>
<view class="brand-check" v-if="item.shopCion" @tap="showBrandPopup = true">
<text>查看品牌</text>
<uni-icons type="right" size="14" color="#ff7a0e"></uni-icons>
</view>
</view>
</view>
</view>
<!-- 不可回收商品 -->
<view class="other-unrecycle-card">
<image class="other-unrecycle-img" src="/static/回收/衣物.png" mode="aspectFit" />
<view class="other-unrecycle-info">
<view class="other-unrecycle-title">其他上衣(需咨询顾问)(暂不回收)</view>
<view class="other-unrecycle-desc">需连线回收顾问筛选</view>
<view class="other-unrecycle-price-row">
<text class="other-unrecycle-price">¥ — /件</text>
</view>
</view>
<button class="other-unrecycle-btn" disabled>+</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"> 3.76元</text>
</view>
<view class="bottom-bar">
<view class="bottom-left">
<view class="summary-row">
<text class="summary-label">已选 <text class="summary-count">{{totalCount}}</text> 件 预计回收可得</text>
<uni-icons type="help" size="18" color="#b2b2b2" style="margin: 0 8rpx;" />
</view>
<view class="amount-row">
<uni-icons :type="showDetailPanel ? 'up' : 'down'" size="18" color="#5e5e5e" style="margin-right: 8rpx;vertical-align: middle;" @tap="toggleDetailPanel" />
<text class="amount">¥{{priceRange.min}}-{{priceRange.max}}</text>
</view>
</view>
<button class="submit-btn" @tap="submitOrder">预约上门取件</button>
</view>
<view class="bottom-bar-divider"></view>
</view>
<!-- 明细弹窗遮罩和弹窗 -->
<view v-if="showDetailPanel" class="detail-popup-mask" @tap.self="toggleDetailPanel">
<view class="detail-popup" @tap.stop>
<view class="detail-popup-close" @tap="toggleDetailPanel">×</view>
<view class="green-tip-bar popup-green-tip">
回收范围仅支持回收以上品类,按件回收预计比称重回收多
<text class="tip-highlight"> 3.76元</text>
</view>
<view class="panel-header">
<text class="panel-title">已选商品明细</text>
</view>
<scroll-view class="panel-list popup-panel-list" scroll-y>
<view v-for="(item, idx) in selectedProducts" :key="idx" class="panel-item">
<image v-if="item.image" :src="item.image" class="panel-item-img" mode="aspectFit" />
<view class="panel-item-info">
<text class="panel-item-name">{{item.name}}</text>
<text class="panel-item-desc">{{item.desc}}</text>
<text class="panel-item-price">¥{{item.price}}/件</text>
</view>
<view class="panel-quantity-control">
<button class="btn-minus" @tap="updateQuantityByProduct(item, -1)">-</button>
<text class="quantity">{{item.quantity}}</text>
<button class="btn-plus" @tap="updateQuantityByProduct(item, 1)">+</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> 件 预计回收可得</text>
<uni-icons type="help" size="18" color="#b2b2b2" style="margin: 0 8rpx;" />
</view>
<view class="amount-row">
<uni-icons :type="showDetailPanel ? 'up' : 'down'" size="18" color="#5e5e5e" style="margin-right: 8rpx;vertical-align: middle;" @tap="toggleDetailPanel" />
<text class="amount">¥{{priceRange.min}}-{{priceRange.max}}</text>
</view>
</view>
<button class="submit-btn" @tap="submitOrder">预约上门取件</button>
</view>
</view>
</view>
<!-- 根据角色显示不同的导航栏 -->
<uv-tabbar
v-if="ishow"
:value="value"
:fixed="true"
@change="changeTo"
class="uv-tabbar"
>
<uv-tabbar-item text="首页" >
<template v-slot:active-icon>
<image class="icon" src="/static/home/首页-点击.png"></image>
</template>
<template v-slot:inactive-icon>
<image class="icon" src="/static/home/首页-未点击.png"></image>
</template>
</uv-tabbar-item>
<uv-tabbar-item text="回收" >
<template v-slot:active-icon>
<image class="icon" src="/static/home/回收-点击.png"></image>
</template>
<template v-slot:inactive-icon>
<image class="icon" src="/static/home/回收-未点击.png"></image>
</template>
</uv-tabbar-item>
<uv-tabbar-item text="我的" >
<template v-slot:active-icon>
<image class="icon" src="/static/home/我的-点击.png"></image>
</template>
<template v-slot:inactive-icon>
<image class="icon" src="/static/home/我的-未点击.png"></image>
</template>
</uv-tabbar-item>
</uv-tabbar>
<!-- 品牌索引弹窗 -->
<view v-if="showBrandPopup" class="brand-popup-mask" @tap.self="closeBrandPopup">
<view class="brand-popup">
<view class="brand-popup-header">
<text class="brand-popup-close" @tap="closeBrandPopup">关闭</text>
<text class="brand-popup-title">可回收的品牌</text>
</view>
<view class="brand-popup-search">
<input class="brand-search-input" v-model="brandSearch" placeholder="请输入要查询的内容" />
</view>
<scroll-view class="brand-popup-list" scroll-y :scroll-into-view="scrollToView">
<view v-for="letter in brandIndexList" :key="letter" :id="'brand-letter-' + letter">
<view class="brand-letter">{{letter}}</view>
<view v-for="brand in filteredBrandList.filter(b => b.letter === letter)" :key="brand.name" class="brand-item" @tap="openBrandConfirm(brand)">
<image :src="brand.logo" class="brand-logo" mode="aspectFit" />
<text class="brand-name">{{brand.name}}</text>
</view>
</view>
</scroll-view>
<view class="brand-index-bar">
<text v-for="letter in brandIndexList" :key="letter" :class="{active: currentLetter === letter}" @tap="scrollToLetter(letter)">{{letter}}</text>
</view>
</view>
</view>
<!-- 回收规则弹窗 -->
<view v-if="showRulePopup" class="rule-popup-mask" @tap.self="closeRulePopup">
<view class="rule-popup">
<view class="rule-popup-title">回收规则</view>
<scroll-view class="rule-popup-content" scroll-y>
<rich-text :nodes="ruleHtml" />
</scroll-view>
<button class="rule-popup-btn" @tap="closeRulePopup">我知道了</button>
<!-- <view class="rule-popup-close" @tap="closeRulePopup">
<uni-icons type="close" size="36" color="#fff" />
</view> -->
</view>
</view>
<!-- 预约上门取件弹窗 -->
<view v-if="showPickupConfirm" class="pickup-confirm-mask">
<view class="pickup-confirm-popup">
<view class="pickup-confirm-title">温馨提示</view>
<view class="pickup-confirm-content">
1.当前回收快递免费上门,由于快递成本较高,为避免不必要的成本及资源二次浪费不属于可回收品类或不符合回收标准的物品请勿寄出。<br/><br/>
2.已通过的回收物品将正常结算。不符合回收要求的物品可选择快递取回,运费自付。请在订单结算后48小时内联系在线客服安排取回,逾期未联系将默认捐赠,无法再次取回。<br/><br/>
3.若用户寄出大量不可回收的物品,平台有权限制下次回收权限,或取消下次包邮服务。<br/><br/>
4.对于合格率高的回收订单,平台将根据实际情况,给予额外回收奖励。
</view>
<view class="pickup-confirm-btn-row">
<button class="pickup-confirm-btn" @tap="handlePickupCancel">取消回收</button>
<button class="pickup-confirm-btn agree" @tap="handlePickupAgree">我同意</button>
</view>
</view>
</view>
<!-- 品牌确认弹窗 -->
<view v-if="showBrandConfirm" class="brand-confirm-mask" @tap.self="closeBrandConfirm">
<view class="brand-confirm-popup">
<view class="brand-confirm-title">品牌确认提示</view>
<view class="brand-confirm-logo-wrap">
<image :src="brandConfirmInfo.logo" class="brand-confirm-logo" mode="aspectFit" />
</view>
<view class="brand-confirm-name">{{ brandConfirmInfo.name }}</view>
<view class="brand-confirm-desc">请确认所选品牌是否与实物品牌信息一致,否则将无法进行回收。</view>
<view class="brand-confirm-btn-row">
<button class="brand-confirm-btn retry" @tap="closeBrandConfirm">重新选择</button>
<button class="brand-confirm-btn confirm" @tap="confirmBrand">确认一致</button>
</view>
</view>
</view>
</view>
</template>
<script>
import tabBarMixin from '../mixins/tabBarMixin.js'
export default {
mixins: [tabBarMixin],
data() {
return {
value:1,
ishow:true,
// 动态数据
allProducts: {}, // { [categoryId]: [商品数组] }
allProductsPage: {}, // { [categoryId]: 当前已加载页码 }
allProductsTotal: {}, // { [categoryId]: 总数 }
pageSize: 10,
currentCategory: 0,
tabbarHeight: 0,
showDetailPanel: false,
showBrandPopup: false,
showRulePopup: false,
ruleImgUrl: '/static/回收/回收规则.png',
showPickupConfirm: false,
showBrandConfirm: false,
brandConfirmInfo: {
logo: '',
name: ''
},
brandList: [
{ logo: '/static/brand/alexander.png', name: 'Alexander McQueen/亚历山大麦昆', letter: 'A' },
{ logo: '/static/brand/alexander.png', name: 'Alexander McQueen/亚历山大麦昆', letter: 'A' },
// ... 可补充更多品牌 ...
],
brandIndexList: ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'],
currentLetter: 'A',
scrollToView: '',
brandSearch: '',
ruleHtml: '', // 回收规则富文本内容
loadingMore: false,
finished: false,
pendingBrandIndex: null, // 记录待加一的品牌商品index
}
},
computed: {
// 当前分类的商品列表
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) => sum + (item.quantity || 0), 0)
}, 0)
},
// 计算总价格
totalPrice() {
const total = Object.values(this.allProducts).reduce((categoryTotal, categoryItems) => {
return categoryTotal + categoryItems.reduce((sum, item) => sum + (item.quantity || 0) * Number(item.price), 0)
}, 0)
return total.toFixed(1)
},
// 计算价格范围
priceRange() {
if (this.totalCount === 0) {
return {
min: '0.0',
max: '0.0'
}
}
const total = Number(this.totalPrice)
const min = Math.max(0, (total - 2.2)).toFixed(1)
const max = (total + 2.2).toFixed(1)
return { min, max }
},
selectedProducts() {
// 返回所有已选商品
return this.recycleList.filter(item => item.quantity > 0)
},
filteredBrandList() {
if (!this.brandSearch) return this.brandList
const keyword = this.brandSearch.trim().toLowerCase()
return this.brandList.filter(b => b.name.toLowerCase().includes(keyword))
},
bannerList() {
return getApp().globalData.bannerList || []
},
categories() {
const list = getApp().globalData.pricePreviewList || []
return list.filter(item => item.pid === '0').sort((a, b) => a.sort - b.sort)
}
},
methods: {
changeTo(e){
this.value = e
if(e==2){
uni.reLaunch({
url: '/pages/component/my'
});
}else if(e==0){
console.log(e,'111')
uni.reLaunch({
url: '/pages/component/home'
});
}
},
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) => 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
// 品牌商品且数量为0且加一时弹出品牌索引弹窗
if (item.shopCion && (item.quantity || 0) === 0 && delta > 0) {
this.pendingBrandIndex = index
this.showBrandPopup = true // 打开品牌索引弹窗
return
}
let newQuantity = (item.quantity || 0) + delta
if (newQuantity < 0) newQuantity = 0
this.$set(item, 'quantity', newQuantity)
},
// 显示回收规则
showRules(item) {
// 获取回收规则富文本
this.$api('getGoodsRecycleRule', { goodsId: item.id }, res => {
if (res.code === 200 && res.result) {
this.ruleHtml = res.result
} else {
this.ruleHtml = '<p>暂无回收规则</p>'
}
this.showRulePopup = true
})
},
showMore() {
uni.showToast({
title: '更多规则请咨询客服',
icon: 'none'
})
},
submitOrder() {
if (this.totalCount === 0) {
uni.showToast({
title: '请选择要回收的物品',
icon: 'none'
})
return
}
this.showPickupConfirm = true;
},
handlePickupCancel() {
this.showPickupConfirm = false;
},
handlePickupAgree() {
this.showPickupConfirm = false;
uni.showLoading({
title: '提交中...'
})
setTimeout(() => {
uni.hideLoading()
uni.showToast({
title: '预约成功',
icon: 'success'
})
this.goToPickup()
}, 1500)
},
goToPickup() {
// 获取所有选中的衣物
const selectedItems = this.recycleList.filter(item => item.quantity > 0).map(item => ({
name: item.name,
icon: item.image,
quantity: item.quantity,
unitPrice: item.price,
desc: '允许脏破烂,160码以上'
}))
// 将选中的衣物信息转换为字符串
const itemsStr = encodeURIComponent(JSON.stringify(selectedItems))
// 跳转到预约页面
uni.navigateTo({
url: `/pages/subcomponent/pickup?fromRecycle=true&items=${itemsStr}`
})
},
checkBrand(index) {
this.showBrandPopup = true
},
closeBrandPopup() {
this.showBrandPopup = false
},
scrollToLetter(letter) {
this.currentLetter = letter
this.scrollToView = 'brand-letter-' + letter
},
// 添加下拉刷新方法
async refreshData() {
try {
// 这里可以添加刷新数据的逻辑,比如重新获取商品列表等
// 示例:重新初始化数据
this.currentCategory = 0
Object.values(this.allProducts).forEach(categoryItems => {
categoryItems.forEach(item => {
item.quantity = 0
})
})
// 模拟网络请求延迟
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
},
updateQuantityByProduct(item, delta) {
if (!item.quantity) item.quantity = 0
item.quantity += delta
if (item.quantity < 0) item.quantity = 0
this.updateTotal()
},
openRulePopup() {
this.showRulePopup = true
},
closeRulePopup() {
this.showRulePopup = false
},
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
}
},
openBrandConfirm(brand) {
this.brandConfirmInfo = {
logo: brand.logo,
name: brand.name
}
this.showBrandConfirm = true
},
closeBrandConfirm() {
this.showBrandConfirm = false
},
confirmBrand() {
this.showBrandConfirm = false
this.showBrandPopup = false
// 确认后将待加一的商品数量+1
if (this.pendingBrandIndex !== null) {
const categoryId = this.categories[this.currentCategory]?.id
const item = this.allProducts[categoryId]?.[this.pendingBrandIndex]
if (item) {
this.$set(item, 'quantity', 1)
}
this.pendingBrandIndex = null
}
},
},
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) {
if (options && options.categoryId) {
const idx = this.categories.findIndex(c => c.id == options.categoryId)
if (idx !== -1) this.currentCategory = idx
}
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()
}
},
onUnload() {
uni.$off('bannerListUpdated')
},
onShow() {
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()
}
},
watch: {
categories(newVal) {
const id = getApp().globalData.targetRecycleCategoryId
console.log('targetRecycleCategoryId', id)
console.log('categories:', newVal.map(c => c.id))
const idx = newVal.findIndex(c => String(c.id) === String(id))
console.log('findIndex result:', idx)
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;
min-height: 100vh;
padding-bottom: calc(100rpx + env(safe-area-inset-bottom)); /* 底部导航栏高度 + 安全区域 */
background-color: #f5f5f5;
}
.banner {
background: linear-gradient(135deg, #ff9500,#ff5e00);
position: relative;
height: 240rpx;
z-index: 1;
height: 400rpx;
image {
width: 100%;
height: 100%;
}
}
.goods-list {
flex: 1;
display: flex;
position: relative;
height: calc(100vh - 200rpx - 100rpx - 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: calc(100vh - 240rpx - 120rpx);
border-right: 1rpx solid rgba(255, 126, 14, 0.1);
margin: 1rpx;
border-radius: 20rpx 0 0 0;
margin-right: 20rpx;
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: 30rpx 20rpx;
text-align: center;
font-family: PingFang SC;
font-weight: 600;
font-size: 14px;
line-height: 100%;
letter-spacing: 0px;
color: #666;
.category-dot {
position: absolute;
top: 15rpx;
right: 15rpx;
width: 12rpx;
height: 12rpx;
background: #ff7a0e;
border-radius: 50%;
}
&.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: calc(100vh - 140rpx - 120rpx);
padding: 0 30rpx;
background: #ffffff;
width: 70%;
margin: 1rpx;
margin-left: 0;
border-radius: 0 20rpx 0 0;
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-item-img {
width: 120rpx;
height: 120rpx;
border-radius: 24rpx;
background: #f8f8f8;
margin-right: 28rpx;
object-fit: contain;
flex-shrink: 0;
}
.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;
}
.goods-desc {
font-size: 24rpx;
color: #999;
display: block;
margin-bottom: 20rpx;
}
.goods-info {
display: flex;
justify-content: space-between;
align-items: center;
}
.price-info {
display: flex;
align-items: baseline;
.price-symbol {
font-size: 24rpx;
color: #ff7a0e;
}
.price-value {
font-size: 36rpx;
color: #ff7a0e;
font-weight: bold;
margin: 0 4rpx;
}
.price-unit {
font-size: 24rpx;
color: #999;
}
}
.quantity-control {
display: flex;
align-items: center;
button {
width: 60rpx;
height: 60rpx;
padding: 0;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
color: #666;
background: #f8f8f8;
border: none;
border-radius: 50%;
&::after {
border: none;
}
&:active {
opacity: 0.8;
}
}
.quantity {
width: 80rpx;
text-align: center;
font-size: 32rpx;
color: #333;
}
}
.brand-check {
// margin-top: 20rpx;
// margin:0 auto;
display: flex;
flex-direction: row;
align-items: center;
// justify-content: center;
border: 1px solid #f8a01d;
width: 40%;
// background: #fff7f0;
border-radius: 8rpx;
color: #ff7a0e;
font-family: PingFang SC;
font-weight: 400;
font-size: 12px;
line-height: 140%;
letter-spacing: 0%;
text {
// margin-right: 8rpx;
}
}
}
.rules-link{
.rules{
font-family: PingFang SC;
font-weight: 400;
font-size: 12px;
line-height: 140%;
letter-spacing: 0%;
}
}
.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;
}
.other-unrecycle-title {
font-size: 30rpx;
color: #222;
font-weight: bold;
margin-bottom: 8rpx;
word-break: break-all;
white-space: normal;
overflow: visible;
}
.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;
}
.other-unrecycle-price {
font-size: 28rpx;
color: #ff9c00;
font-weight: bold;
}
.other-unrecycle-btn {
width: 60rpx;
height: 60rpx;
margin-left: 24rpx;
border-radius: 50%;
background: #f5f5f5;
color: #ccc;
font-size: 36rpx;
border: none;
display: flex;
align-items: center;
justify-content: center;
pointer-events: none;
}
.fixed-bottom-wrap {
position: fixed;
left: 0;
right: 0;
bottom: calc(v-bind('tabbarHeight + "px"') + env(safe-area-inset-bottom));
width: 100vw;
z-index: 1001;
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: 16rpx 30rpx 0 30rpx;
box-sizing: border-box;
text-align: left;
display: flex;
align-items: center;
justify-content: center;
// flex-direction: r;
.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: calc(90rpx + env(safe-area-inset-bottom)); /* tabbar高度+安全区 */
background: rgba(0,0,0,0.35);
z-index: 8;
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;
overflow: hidden;
min-height: 520rpx;
max-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;
overflow-y: auto;
max-height: 36vh;
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;
}
.panel-item-img {
width: 100rpx;
height: 100rpx;
margin-right: 20rpx;
border-radius: 16rpx;
background: #f8f8f8;
}
.panel-item-info {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
min-width: 0;
}
.panel-item-name {
font-size: 30rpx;
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;
}
.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: #f5f5f5;
border: none;
border-radius: 50%;
&::after {
border: none;
}
&:active {
opacity: 0.8;
}
}
.panel-quantity-control .quantity {
width: 40rpx;
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-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;
}
}
}
.brand-popup-mask {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: rgba(0,0,0,0.35);
z-index: 3000;
display: flex;
align-items: flex-end;
justify-content: center;
}
.brand-popup {
position: relative;
width: 100%;
max-width: 750px;
background: #fff;
border-radius: 32rpx 32rpx 0 0;
box-shadow: 0 -4rpx 24rpx rgba(0,0,0,0.08);
padding-bottom: 40rpx;
max-height: 90vh;
display: flex;
flex-direction: column;
overflow: hidden;
}
.brand-popup-header {
display: flex;
align-items: center;
justify-content: center;
padding: 32rpx 24rpx 0 24rpx;
font-size: 32rpx;
font-weight: bold;
position: relative;
}
.brand-popup-close {
position: absolute;
left: 24rpx;
font-size: 28rpx;
color: #888;
}
.brand-popup-title {
font-size: 32rpx;
color: #222;
font-weight: bold;
}
.brand-popup-search {
padding: 20rpx 24rpx 0 24rpx;
}
.brand-search-input {
width: 100%;
height: 60rpx;
border-radius: 30rpx;
background: #f5f5f5;
border: none;
padding-left: 40rpx;
font-size: 28rpx;
color: #888;
}
.brand-popup-list {
flex: 1;
overflow-y: auto;
max-height: 60vh;
padding: 0 24rpx;
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE and Edge */
&::-webkit-scrollbar {
width: 0 !important;
display: none; /* Chrome, Safari, Opera */
}
}
.brand-letter {
font-size: 28rpx;
color: #888;
margin: 24rpx 0 8rpx 0;
font-weight: bold;
}
.brand-item {
display: flex;
align-items: center;
padding: 16rpx 0;
border-bottom: 1px solid #f0f0f0;
}
.brand-logo {
width: 60rpx;
height: 60rpx;
margin-right: 20rpx;
border-radius: 8rpx;
background: #f8f8f8;
}
.brand-name {
font-size: 28rpx;
color: #222;
}
.brand-index-bar {
position: absolute;
right: 12rpx;
top: 120rpx;
width: 32rpx;
display: flex;
flex-direction: column;
align-items: center;
z-index: 10;
}
.brand-index-bar text {
font-size: 22rpx;
color: #bbb;
margin: 4rpx 0;
font-weight: bold;
&.active {
color: #ff9c00;
}
}
.rule-popup-mask {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: rgba(0,0,0,0.35);
z-index: 4000;
display: flex;
align-items: center;
justify-content: center;
}
.rule-popup {
width: 90vw;
max-width: 600rpx;
background: #fff;
border-radius: 48rpx;
box-shadow: 0 8rpx 32rpx rgba(0,0,0,0.12);
display: flex;
flex-direction: column;
align-items: center;
position: relative;
padding-bottom: 40rpx;
}
.rule-popup-title {
font-size: 36rpx;
color: #222;
font-weight: bold;
text-align: center;
margin-top: 48rpx;
margin-bottom: 16rpx;
}
.rule-popup-content {
width: 100%;
max-height: 420rpx;
padding: 0 40rpx;
box-sizing: border-box;
overflow-y: auto;
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE and Edge */
&::-webkit-scrollbar {
width: 0 !important;
display: none; /* Chrome, Safari, Opera */
}
}
.rule-popup-desc {
font-size: 26rpx;
color: #888;
text-align: center;
margin-bottom: 24rpx;
margin-top: 0;
}
.rule-popup-warning {
width: 100%;
border: 2rpx solid #ffb800;
color: #ffb800;
background: #fffbe6;
border-radius: 32rpx;
font-size: 28rpx;
text-align: center;
padding: 16rpx 0;
margin-bottom: 24rpx;
font-weight: bold;
}
.rule-popup-img {
display: block;
margin: 0 auto 24rpx auto;
max-width: 80%;
max-height: 300rpx;
border-radius: 16rpx;
object-fit: contain;
}
.rule-popup-btn {
width: 80%;
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: 0 auto;
margin-top: 16rpx;
box-shadow: 0 4rpx 16rpx rgba(255, 156, 0, 0.08);
&::after {
border: none;
}
&:active {
opacity: 0.9;
}
}
.rule-popup-close {
position: absolute;
right: 32rpx;
bottom: 32rpx;
width: 72rpx;
height: 72rpx;
background: #ff5a5f;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
z-index: 10;
box-shadow: 0 2rpx 8rpx rgba(255,90,95,0.12);
}
/* 预约上门取件弹窗样式 */
.pickup-confirm-mask {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: rgba(0,0,0,0.35);
z-index: 5000;
display: flex;
align-items: center;
justify-content: center;
}
.pickup-confirm-popup {
width: 90vw;
max-width: 600rpx;
background: #fff;
border-radius: 48rpx;
box-shadow: 0 8rpx 32rpx rgba(0,0,0,0.12);
display: flex;
flex-direction: column;
align-items: center;
position: relative;
padding: 48rpx 36rpx 40rpx 36rpx;
}
.pickup-confirm-title {
font-size: 36rpx;
color: #222;
font-weight: bold;
text-align: center;
margin-bottom: 24rpx;
}
.pickup-confirm-content {
font-size: 26rpx;
color: #333;
text-align: left;
line-height: 1.7;
margin-bottom: 36rpx;
}
.pickup-confirm-btn-row {
width: 100%;
display: flex;
justify-content: space-between;
gap: 32rpx;
}
.pickup-confirm-btn {
flex: 1;
height: 88rpx;
border-radius: 44rpx;
font-size: 32rpx;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
border: 2rpx solid #ffd01e;
background: #fff;
color: #ff9c00;
box-shadow: 0 4rpx 16rpx rgba(255, 156, 0, 0.08);
}
.pickup-confirm-btn:not(.agree) {
background: #fff0d2;
}
.pickup-confirm-btn.agree {
background: linear-gradient(to right, #ffd01e, #ff8917);
color: #fff;
border: none;
}
.uv-tabbar {
z-index: 1000;
}
.loading-more {
text-align: center;
color: #999;
padding: 20rpx 0;
font-size: 26rpx;
}
.brand-confirm-mask {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: rgba(0,0,0,0.25);
z-index: 5001;
display: flex;
align-items: center;
justify-content: center;
}
.brand-confirm-popup {
width: 70vw;
max-width: 270px;
background: #fff;
border-radius: 32rpx;
box-shadow: 0 8rpx 32rpx rgba(0,0,0,0.12);
display: flex;
flex-direction: column;
align-items: center;
padding: 48rpx 20rpx 36rpx 20rpx;
position: relative;
}
.brand-confirm-title {
font-size: 36rpx;
color: #222;
font-weight: bold;
text-align: center;
margin-bottom: 24rpx;
}
.brand-confirm-logo-wrap {
width: 120rpx;
height: 120rpx;
background: #f8f8f8;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 18rpx;
}
.brand-confirm-logo {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
}
.brand-confirm-name {
font-size: 28rpx;
color: #222;
font-weight: bold;
text-align: center;
margin-bottom: 16rpx;
}
.brand-confirm-desc {
font-size: 24rpx;
color: #999;
text-align: center;
margin-bottom: 32rpx;
line-height: 1.6;
}
.brand-confirm-btn-row {
width: 100%;
display: flex;
justify-content: space-between;
gap: 24rpx;
}
.brand-confirm-btn {
flex: 1;
height: 72rpx;
border-radius: 36rpx;
font-size: 28rpx;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
border: none;
margin: 0 0;
}
.brand-confirm-btn.retry {
background: #fff;
color: #ff9c00;
border: 2rpx solid #ff9c00;
}
.brand-confirm-btn.confirm {
background: linear-gradient(to right, #ffd01e, #ff8917);
color: #fff;
border: none;
}
</style>