|
|
- <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>
|