From 30a87772d7e86b17ba741234a7a3dba4d3b4968c Mon Sep 17 00:00:00 2001
From: huliyong <2783385703@qq.com>
Date: Thu, 26 Jun 2025 19:11:47 +0800
Subject: [PATCH] =?UTF-8?q?feat(=E5=9B=9E=E6=94=B6):=20=E6=B7=BB=E5=8A=A0?=
=?UTF-8?q?=E5=93=81=E7=89=8C=E5=95=86=E5=93=81=E6=94=AF=E6=8C=81=E5=8F=8A?=
=?UTF-8?q?=E6=95=B0=E9=87=8F=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 在manifest.json中添加appid配置
- 实现品牌商品的展示、选择和数量管理
- 添加减少数量时的品牌选择弹窗
- 重构商品数量计算逻辑以支持品牌商品
- 更新订单详情页以显示品牌信息
---
manifest.json | 2 +-
pages/component/recycle copy.vue | 1927 ++++++++++++++++++++++++++++++++++++++
pages/component/recycle.vue | 380 +++++++-
pages/subcomponent/pickup.vue | 58 +-
4 files changed, 2319 insertions(+), 48 deletions(-)
create mode 100644 pages/component/recycle copy.vue
diff --git a/manifest.json b/manifest.json
index dc76de1..2f63bb3 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,6 +1,6 @@
{
"name" : "瀚海回收",
- "appid" : "",
+ "appid" : "__UNI__197A38F",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
diff --git a/pages/component/recycle copy.vue b/pages/component/recycle copy.vue
new file mode 100644
index 0000000..134e98e
--- /dev/null
+++ b/pages/component/recycle copy.vue
@@ -0,0 +1,1927 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ getCategoryItemCount(index) }}
+ {{ category.title }}
+
+
+
+
+
+
+
+
+
+
+ {{item.service}}
+
+
+ 回收规则
+
+
+
+
+
+ ¥
+ {{item.price}}
+ /件
+
+
+
+ {{item.quantity || 0}}
+
+
+
+
+
+
+
+
+
+
+
+ 其他上衣(需咨询顾问)(暂不回收)
+ 需连线回收顾问筛选
+
+ ¥ — /件
+
+
+
+
+ 加载中...
+ 没有更多了
+
+
+
+
+
+
+ 回收范围仅支持回收以上品类,按件回收预计比称重回收多
+ 3.76元
+
+
+
+
+ 已选 {{totalCount}} 件 预计回收可得
+
+
+
+
+ ¥{{priceRange.min}}-{{priceRange.max}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 关闭
+ 可回收的品牌
+
+
+
+
+
+
+ {{letter}}
+
+
+ {{brand.name}}
+
+
+
+
+ {{letter}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 品牌确认提示
+
+
+
+ {{ brandConfirmInfo.name }}
+ 请确认所选品牌是否与实物品牌信息一致,否则将无法进行回收。
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/component/recycle.vue b/pages/component/recycle.vue
index 60504b6..a3dd7bc 100644
--- a/pages/component/recycle.vue
+++ b/pages/component/recycle.vue
@@ -52,8 +52,8 @@
@@ -330,6 +347,10 @@ export default {
pendingBrandIndex: null, // 记录待加一的品牌商品index
showPriceInfoPopup: false,
isWaitingForBrandSelection: false, // 等待品牌选择的标志
+ showBrandReducePopup: false, // 显示减少数量时的品牌选择弹窗
+ reduceItem: null, // 待减少数量的商品
+ reduceBrandList: [], // 可减少的品牌列表
+ viewedRuleItems: new Set(), // 已查看过规则的商品ID集合
}
},
computed: {
@@ -341,13 +362,29 @@ export default {
// 计算总数量
totalCount() {
return Object.values(this.allProducts).reduce((total, categoryItems) => {
- return total + categoryItems.reduce((sum, item) => sum + (item.quantity || 0), 0)
+ return total + categoryItems.reduce((sum, item) => {
+ // 如果商品有品牌数量,汇总所有品牌的数量
+ 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)
},
// 计算总价格
totalPrice() {
const total = Object.values(this.allProducts).reduce((categoryTotal, categoryItems) => {
- return categoryTotal + categoryItems.reduce((sum, item) => sum + (item.quantity || 0) * Number(item.price), 0)
+ return categoryTotal + categoryItems.reduce((sum, item) => {
+ 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
+ }
+ return sum + itemQuantity * Number(item.price)
+ }, 0)
}, 0)
return total.toFixed(1)
},
@@ -365,8 +402,33 @@ export default {
return { min, max }
},
selectedProducts() {
- // 返回所有分类下所有已选商品
- return Object.values(this.allProducts).flat().filter(item => item.quantity > 0)
+ // 返回所有分类下所有已选商品,按品牌分组
+ const products = []
+ Object.values(this.allProducts).flat().forEach(item => {
+ 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.image : '',
+ uniqueKey: `${item.id}_${brandId}` // 用于区分同商品不同品牌
+ })
+ }
+ })
+ } else if (item.quantity > 0) {
+ // 没有品牌的商品
+ products.push({
+ ...item,
+ uniqueKey: item.id
+ })
+ }
+ })
+ return products
},
filteredBrandList() {
if (!this.brandSearch) return this.brandList
@@ -428,7 +490,12 @@ export default {
getCategoryItemCount(index) {
const categoryId = this.categories[index]?.id
const categoryItems = this.allProducts[categoryId] || []
- return categoryItems.reduce((sum, item) => sum + (item.quantity || 0), 0)
+ return categoryItems.reduce((sum, item) => {
+ 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) {
@@ -446,19 +513,100 @@ export default {
const categoryId = this.categories[this.currentCategory]?.id
const item = this.allProducts[categoryId]?.[index]
if (!item) return
+
+ // 如果是减少数量且delta为负数
+ if (delta < 0) {
+ // 检查是否有多个品牌
+ if (item.brandQuantities && Object.keys(item.brandQuantities).length > 1) {
+ // 有多个品牌,显示选择弹窗
+ this.reduceItem = { item, index, delta }
+ this.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 : '未知品牌',
+ image: brandInfo ? brandInfo.image : ''
+ }
+ })
+ this.showBrandReducePopup = true
+ 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) {
+ this.$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) {
+ if ((item.quantity || 0) === 0 && delta > 0) {
this.pendingBrandIndex = index
this.isWaitingForBrandSelection = true;
this.showRules(item); // 先显示回收规则
return
}
- let newQuantity = (item.quantity || 0) + delta
- if (newQuantity < 0) newQuantity = 0
- this.$set(item, 'quantity', newQuantity)
+
+ },
+ // 选择要减少的品牌
+ selectReduceBrand(brandInfo) {
+ const { item, index, delta } = this.reduceItem
+ const currentQty = item.brandQuantities[brandInfo.brandId] || 0
+ const newQty = Math.max(0, currentQty + delta)
+
+ this.$set(item.brandQuantities, brandInfo.brandId, newQty)
+
+ // 如果数量为0,删除该品牌
+ if (newQty === 0) {
+ this.$delete(item.brandQuantities, brandInfo.brandId)
+ }
+
+ this.closeBrandReducePopup()
+ },
+
+ // 关闭减少品牌选择弹窗
+ closeBrandReducePopup() {
+ this.showBrandReducePopup = false
+ this.reduceItem = null
+ this.reduceBrandList = []
+ },
+ // 获取品牌信息
+ getBrandInfo(brandId) {
+ return this.brandList.find(brand => brand.id === brandId)
+ },
+ // 获取商品的总数量(所有品牌)
+ getItemTotalQuantity(item) {
+ 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 (this.viewedRuleItems.has(item.id)) {
+ // 如果已经查看过,直接跳过规则弹窗,进入品牌选择
+ this.isWaitingForBrandSelection = false;
+ this.getGoodsBrandList(item.id);
+ this.showBrandPopup = true;
+ return;
+ }
+
// 获取回收规则富文本
this.$api('getGoodsRecycleRule', { goodsId: item.id }, res => {
if (res.code === 200 && res.result) {
@@ -466,7 +614,7 @@ export default {
} else {
this.ruleHtml = '暂无回收规则
'
}
- this.showRulePopup = true
+ this.showRulePopup = true
})
},
showMore() {
@@ -511,14 +659,25 @@ export default {
},
goToPickup() {
// 获取所有选中的衣物(所有分类)
- const selectedItems = this.selectedProducts.map(item => ({
- id: item.id,
- name: item.name,
- icon: item.image,
- quantity: item.quantity,
- unitPrice: item.price,
- desc: '允许脏破烂,160码以上'
- }))
+ const selectedItems = this.selectedProducts.map(item => {
+ const baseItem = {
+ id: item.id,
+ name: item.name,
+ icon: item.image,
+ quantity: item.quantity,
+ unitPrice: item.price,
+ desc: item.brandName ? `品牌:${item.brandName}` : '允许脏破烂,160码以上'
+ }
+
+ // 如果有品牌信息,添加品牌相关字段
+ if (item.brandId) {
+ baseItem.brandId = item.brandId
+ baseItem.brandName = item.brandName
+ baseItem.brandImage = item.brandImage
+ }
+
+ return baseItem
+ })
const itemsStr = encodeURIComponent(JSON.stringify(selectedItems))
uni.navigateTo({
url: `/pages/subcomponent/pickup?fromRecycle=true&items=${itemsStr}`
@@ -527,10 +686,10 @@ export default {
checkBrand(index) {
const categoryId = this.categories[this.currentCategory]?.id
const item = this.allProducts[categoryId]?.[index]
- if (item?.shopCion) {
+ if (item?.id) {
this.pendingBrandIndex = index
- this.getGoodsBrandList(item.shopCion)
- this.showBrandPopup = true
+ this.getGoodsBrandList(item.id)
+ this.showBrandPopup = true
}
},
closeBrandPopup() {
@@ -552,8 +711,13 @@ export default {
Object.values(this.allProducts).forEach(categoryItems => {
categoryItems.forEach(item => {
item.quantity = 0
+ if (item.brandQuantities) {
+ item.brandQuantities = {}
+ }
})
})
+ // 清空已查看规则的记录
+ this.viewedRuleItems.clear()
// 模拟网络请求延迟
await new Promise(resolve => setTimeout(resolve, 1000))
@@ -576,10 +740,44 @@ export default {
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()
+ // 在明细弹窗中更新数量
+ if (item.brandId) {
+ // 有品牌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)
+ this.$set(originalItem.brandQuantities, item.brandId, newQty)
+
+ // 如果数量为0,删除该品牌
+ if (newQty === 0) {
+ this.$delete(originalItem.brandQuantities, item.brandId)
+ }
+
+ // 同步更新显示的数量
+ item.quantity = newQty
+ }
+ } else {
+ // 没有品牌的商品
+ if (!item.quantity) item.quantity = 0
+ item.quantity += delta
+ if (item.quantity < 0) item.quantity = 0
+
+ // 同步到原商品
+ 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
},
openRulePopup() {
this.showRulePopup = true
@@ -591,13 +789,12 @@ export default {
this.isWaitingForBrandSelection = false; // 清除等待状态
const categoryId = this.categories[this.currentCategory]?.id;
const item = this.allProducts[categoryId]?.[this.pendingBrandIndex];
- if (item?.isPin === 'Y') {
- this.getGoodsBrandList(item.shopCion);
- this.showBrandPopup = true; // 打开品牌索引弹窗
- } else {
- // 如果商品不是品牌商品,或者出现意外情况,重置状态
- this.pendingBrandIndex = null;
- }
+
+ // 记录该商品的规则已被查看
+ this.viewedRuleItems.add(item.id);
+
+ this.getGoodsBrandList(item.id);
+ this.showBrandPopup = true; // 打开品牌索引弹窗
}
},
loadMoreGoods() {
@@ -639,14 +836,25 @@ export default {
const categoryId = this.categories[this.currentCategory]?.id
const item = this.allProducts[categoryId]?.[this.pendingBrandIndex]
if (item) {
- this.$set(item, 'quantity', 1)
- this.$set(item, 'pinId', this.brandConfirmInfo.id);
+ // 初始化品牌数量对象
+ if (!item.brandQuantities) {
+ this.$set(item, 'brandQuantities', {})
+ }
+
+ // 增加该品牌的数量
+ const currentQty = item.brandQuantities[this.brandConfirmInfo.id] || 0
+ this.$set(item.brandQuantities, this.brandConfirmInfo.id, currentQty + 1)
+
+ // 清除原来的quantity(如果存在)
+ if (item.quantity) {
+ this.$set(item, 'quantity', 0)
+ }
}
this.pendingBrandIndex = null
}
},
- getGoodsBrandList(iconId) {
- this.$api('getGoodsBrandList', { iconId }, res => {
+ getGoodsBrandList(productId) {
+ this.$api('getGoodsBrandList', { productId }, res => {
// console.log(res,'res')
if (res && res.success && res.result && res.result.records) {
this.brandList = res.result.records.map(item => {
@@ -725,8 +933,13 @@ export default {
Object.values(this.allProducts).forEach(categoryItems => {
categoryItems.forEach(item => {
this.$set(item, 'quantity', 0)
+ if (item.brandQuantities) {
+ this.$set(item, 'brandQuantities', {})
+ }
})
})
+ // 清空已查看规则的记录
+ this.viewedRuleItems.clear()
this.showDetailPanel = false
this.$forceUpdate()
getApp().globalData.shouldClearRecycle = false
@@ -764,8 +977,13 @@ export default {
Object.values(this.allProducts).forEach(categoryItems => {
categoryItems.forEach(item => {
this.$set(item, 'quantity', 0)
+ if (item.brandQuantities) {
+ this.$set(item, 'brandQuantities', {})
+ }
})
})
+ // 清空已查看规则的记录
+ this.viewedRuleItems.clear()
this.showDetailPanel = false
this.$forceUpdate()
getApp().globalData.shouldClearRecycle = false
@@ -776,8 +994,13 @@ export default {
Object.values(this.allProducts).forEach(categoryItems => {
categoryItems.forEach(item => {
this.$set(item, 'quantity', 0)
+ if (item.brandQuantities) {
+ this.$set(item, 'brandQuantities', {})
+ }
})
})
+ // 清空已查看规则的记录
+ this.viewedRuleItems.clear()
// 重置其他相关数据
this.showDetailPanel = false
this.$forceUpdate()
@@ -1923,4 +2146,79 @@ export default {
}
}
}
+
+/* 减少数量时的品牌选择弹窗 */
+.brand-reduce-popup-mask {
+ position: fixed;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ background: rgba(0,0,0,0.35);
+ z-index: 5001;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+.brand-reduce-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-reduce-popup-header {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 32rpx 24rpx 0 24rpx;
+ font-size: 32rpx;
+ font-weight: bold;
+ position: relative;
+}
+.brand-reduce-popup-close {
+ position: absolute;
+ left: 24rpx;
+ font-size: 28rpx;
+ color: #888;
+}
+.brand-reduce-popup-title {
+ font-size: 32rpx;
+ color: #222;
+ font-weight: bold;
+}
+.brand-reduce-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-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;
+}
\ No newline at end of file
diff --git a/pages/subcomponent/pickup.vue b/pages/subcomponent/pickup.vue
index a800e1d..f7e8b5d 100644
--- a/pages/subcomponent/pickup.vue
+++ b/pages/subcomponent/pickup.vue
@@ -55,9 +55,15 @@
订单详情
-
+
+
+
+
- {{ item.name }}
+
+ {{ item.name }}
+ {{ item.brandName }}
+
{{ item.desc }}
¥{{ item.unitPrice }}/件
@@ -324,7 +330,10 @@ export default {
shopId: item.id,
num: item.quantity
};
- if (item.pinId) {
+ // 如果有品牌ID,添加到订单项中
+ if (item.brandId) {
+ orderItem.pinId = item.brandId;
+ } else if (item.pinId) {
orderItem.pinId = item.pinId;
}
return orderItem;
@@ -604,14 +613,51 @@ export default {
padding: 0 30rpx;
.order-item {
display: flex;
- align-items: center;
+ align-items: flex-start;
padding: 30rpx 0;
border-bottom: 1rpx solid #f5f5f5;
&:last-child { border-bottom: none; }
- image { width: 80rpx; height: 80rpx; margin-right: 20rpx; }
+ .item-left {
+ position: relative;
+ margin-right: 20rpx;
+ image {
+ width: 80rpx;
+ height: 80rpx;
+ border-radius: 8rpx;
+ }
+ .brand-logo {
+ position: absolute;
+ bottom: -8rpx;
+ right: -8rpx;
+ width: 32rpx;
+ height: 32rpx;
+ border-radius: 50%;
+ border: 2rpx solid #fff;
+ background: #fff;
+ }
+ }
.item-info {
flex: 1;
- .name { font-size: 30rpx; color: #333; font-weight: 500; }
+ .name-brand-row {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+ margin-bottom: 4rpx;
+ .name {
+ font-size: 30rpx;
+ color: #333;
+ font-weight: 500;
+ margin-right: 12rpx;
+ }
+ .brand-tag {
+ background: #FFE8CC;
+ color: #FF9500;
+ font-size: 20rpx;
+ padding: 4rpx 8rpx;
+ border-radius: 8rpx;
+ border: 1rpx solid #FFD4A0;
+ }
+ }
.desc { font-size: 24rpx; color: #999; margin: 4rpx 0 8rpx 0; }
.price-row {
display: flex;