Browse Source

相同 id 的花材合并在一起

1. hdApp/src/mixins/cgProduct.js(仅 pageType 为 cg / bookCg 时生效)
增加按 id 合并购物车行的逻辑:_shouldMergeSelectByProductId、_mergeDuplicateSelectRows、_syncMergedSelectListIfNeeded、_selectRowMatches。
恢复本地记忆时用 _mergeDuplicateSelectRows 合并重复 id。
getSelectItemById:同一 id 的多行会汇总扎数/支数(防御旧数据)。
addEvent / delEvent / addCustomNumEvent / addItemEvent / updateItemEvent / delAllEvent / getSelectClassById:加减改与分类角标统计都改为按上述规则匹配。

2. ghsProduct.vue / bookProduct.vue
选颜色从 xj 回来时,判断是否已在购物车中改为:在 cg / bookCg 下只比 id,避免再插一条重复行。

其它仍用 cgProduct 且 pageType 不是这两种的页面,仍按 id + classId 区分,避免影响原有开单逻辑。
shizhongqi 2 months ago
parent
commit
d7314b275d

+ 106 - 23
hdApp/src/mixins/cgProduct.js

@@ -84,7 +84,13 @@ export default {
 		allPriceFun() {
 			let price = 0;
 			if (this.selectList) {
-				for (const item of this.selectList) {
+				// 唯一性处理,通过 id 去除重复商品 ---- 防止统计金额时因同一商品多次出现而重复计算
+				const newSelectList = this.selectList
+					.filter((item, index, self) =>
+						index === self.findIndex((t) => t.id === item.id)
+					);
+
+				for (const item of newSelectList) {
 					price += this.getLimitBuyPriceInfo(item).total;
 				}
 			}
@@ -197,6 +203,52 @@ export default {
 			const num = Number(value);
 			return isNaN(num) ? 0 : num;
 		},
+		
+		/** 供货商--采购 / 预订:列表里同一花材可能在不同分类下 classId 不同,购物车应按 id 合并为一行 */
+		// -----------start----------
+		_shouldMergeSelectByProductId() {
+			return this.pageType === "cg" || this.pageType === "bookCg";
+		},
+		_mergeDuplicateSelectRows(list) {
+			if (!Array.isArray(list) || list.length === 0) {
+				return Array.isArray(list) ? [...list] : [];
+			}
+			const map = new Map();
+			const order = [];
+			list.forEach(ele => {
+				const key = String(ele.id);
+				if (!map.has(key)) {
+					const copy = { ...ele };
+					copy.bigCount = Number(copy.bigCount) || 0;
+					copy.smallCount = Number(copy.smallCount) || 0;
+					map.set(key, copy);
+					order.push(key);
+				} else {
+					const prev = map.get(key);
+					prev.bigCount = Number(prev.bigCount) + (Number(ele.bigCount) || 0);
+					prev.smallCount = Number(prev.smallCount) + (Number(ele.smallCount) || 0);
+				}
+			});
+			return order.map(k => map.get(k));
+		},
+		_syncMergedSelectListIfNeeded() {
+			if (!this._shouldMergeSelectByProductId()) return;
+			const list = this.selectList;
+			if (!list || !list.length) return;
+			const merged = this._mergeDuplicateSelectRows(list);
+			if (merged.length !== list.length) {
+				this.setSelectInfoByType({ type: this.pageType, info: merged });
+			}
+		},
+		_selectRowMatches(element, item) {
+			if (!element || !item) return false;
+			if (this._shouldMergeSelectByProductId()) {
+				return String(element.id) === String(item.id);
+			}
+			return element.id == item.id && element.classId == item.classId;
+		},
+		// ------------end---------
+		
 		getLimitBuyItemById(id) {
 			if (!Array.isArray(this.limitBuyList)) {
 				return null;
@@ -357,7 +409,8 @@ export default {
 					let targetId = this.option.id ? this.option.id : 0
 					let currentInfo = uni.getStorageSync('selectList'+this.pageType+'_ghs_'+targetId)
 					if(!this.$util.isEmpty(currentInfo)){
-						this.setSelectInfoByType({ type: this.pageType, info: currentInfo })
+						const mergedInfo = this._mergeDuplicateSelectRows(currentInfo);
+						this.setSelectInfoByType({ type: this.pageType, info: mergedInfo })
 					}else{
 						//临时解决方案
 						this.resetSelectInfoByType(this.pageType);
@@ -382,7 +435,8 @@ export default {
 					let targetId = this.option.id ? this.option.id : 0
 					let currentInfo = uni.getStorageSync('selectList'+this.pageType+'_ghs_'+targetId)
 					if(!this.$util.isEmpty(currentInfo)){
-						this.setSelectInfoByType({ type: this.pageType, info: currentInfo })
+						const mergedInfo = this._mergeDuplicateSelectRows(currentInfo);
+						this.setSelectInfoByType({ type: this.pageType, info: mergedInfo })
 					}else{
 						//临时解决方案
 						this.resetSelectInfoByType(this.pageType);
@@ -561,21 +615,29 @@ export default {
 				autoPrice: 0, //调价价格
 				itemPrice: 0 //调价价格
 			};
-			const item =
-				this.selectList &&
-				this.selectList.find(ele => {
-					return ele.id == id && ele.classId == classId;
-				});
-			if (item) {
-				info = {
-					...item,
-					bigCount: Number(item.bigCount),
-					smallCount: Number(item.smallCount),
-					autoPrice: Number(item.autoPrice),
-					itemPrice: Number(item.itemPrice),
-				};
+			if (!this.selectList || !this.selectList.length) {
+				return info;
 			}
-			return info;
+			const matches = this.selectList.filter(ele =>
+				this._selectRowMatches(ele, { id, classId })
+			);
+			if (!matches.length) {
+				return info;
+			}
+			const base = { ...matches[0] };
+			let bigCount = 0;
+			let smallCount = 0;
+			matches.forEach(m => {
+				bigCount += Number(m.bigCount) || 0;
+				smallCount += Number(m.smallCount) || 0;
+			});
+			return {
+				...base,
+				bigCount,
+				smallCount,
+				autoPrice: Number(base.autoPrice),
+				itemPrice: Number(base.itemPrice)
+			};
 		},
 		//通过id获取当前选中的商品类别信息  左边菜单角标  当前选中该类别商品多少件
 		getSelectClassById(classId) {
@@ -592,7 +654,10 @@ export default {
 			if (productItem && productItem.child) {
 				for (const item of productItem.child) {
 					for (const selectItem of this.selectList) {
-						if (item.id == selectItem.id && item.classId == selectItem.classId) {
+						const matched = this._shouldMergeSelectByProductId()
+							? item.id == selectItem.id
+							: item.id == selectItem.id && item.classId == selectItem.classId;
+						if (matched) {
 							info.bigCount += Number(selectItem.bigCount);
 							info.smallCount += Number(selectItem.smallCount);
 							info.itemPrice += selectItem.itemPrice?Number(selectItem.itemPrice):'';
@@ -604,6 +669,7 @@ export default {
 		},
 		//添加商品
 		addEvent(item) {
+			this._syncMergedSelectListIfNeeded();
 			const list = this.selectList;
 			let has = false;
 			for (let index = 0; index < list.length; index++) {
@@ -613,7 +679,7 @@ export default {
 				}else{
 					this.isSmallCount = false
 				}
-				if (element.id == item.id && element.classId == item.classId) {
+				if (this._selectRowMatches(element, item)) {
 					has = true;
 					if(this.offVerifyRepertory){//去除库存验证
 						if(this.isSmallCount){
@@ -684,14 +750,27 @@ export default {
 
 		},
 
-		addCustomNumEvent(item,params1,type) {
+		addCustomNumEvent(item, params1, type) {
+			this._syncMergedSelectListIfNeeded();
 			const list = this.selectList;
+			const existed = list.find(ele => this._selectRowMatches(ele, item));
+			if (existed) {
+				if (type != "noAdd") {
+					this.setSelectInfoByType({ type: this.pageType, info: list });
+				}
+				this.$nextTick(() => {
+					this.customNum(params1);
+				});
+				this.rememberProduct();
+				return;
+			}
 			let info = { classId: item.classId, id: item.id };
 			const classInfo =
 				this.productInfo &&
 				this.productInfo.find(element => {
 					return element.classId == item.classId && element.child;
 				});
+			
 			if (classInfo) {
 				info = classInfo.child.find(ele => {
 					return ele.id == item.id;
@@ -717,6 +796,7 @@ export default {
 		},
 		//减去商品
 		delEvent(item) {
+			this._syncMergedSelectListIfNeeded();
 			const list = copyObject(this.selectList);
 			let has = false;
 			for (let index = 0; index < list.length; index++) {
@@ -726,7 +806,7 @@ export default {
 				}else{
 					this.isSmallCount = false
 				}
-				if (element.id == item.id && element.classId == item.classId) {
+				if (this._selectRowMatches(element, item)) {
 					has = true;
 					if (element.bigCount > 0) {
 						if (!this.isSmallCount) {
@@ -749,6 +829,7 @@ export default {
 			this.rememberProduct()
 		},
 		delAllEvent(item) {
+			this._syncMergedSelectListIfNeeded();
 			const list = this.selectList;
 			for (let index = 0; index < list.length; index++) {
 				const element = list[index];
@@ -881,12 +962,13 @@ export default {
 			this.setSelectInfoByType({ type: this.pageType, info: list });
 		},
 		addItemEvent(item) {
+			this._syncMergedSelectListIfNeeded();
 			const list = this.selectList;
 			if(!this.$util.isEmpty(list)){
 				let hasItem = false
 				for (let index = 0; index < list.length; index++) {
 					const element = list[index];
-					if (element.id == item.id && element.classId == item.classId) {
+					if (this._selectRowMatches(element, item)) {
 						hasItem = true
 						const { bigCount, smallCount } = list[index];
 						const ratio = Number(item.ratio);
@@ -918,10 +1000,11 @@ export default {
 		},
 		//更新商品
 		updateItemEvent(item) {
+			this._syncMergedSelectListIfNeeded();
 			const list = this.selectList;
 			for (let index = 0; index < list.length; index++) {
 				const element = list[index];
-				if (element.id == item.id && element.classId == item.classId) {
+				if (this._selectRowMatches(element, item)) {
 					const { bigCount, smallCount } = list[index];
 					const ratio = Number(item.ratio);
 					if (this.isLimit) {

+ 3 - 7
hdApp/src/pagesPurchase/bookProduct.vue

@@ -247,11 +247,7 @@ export default {
 		}
 	},
 	onShow(){
-
 		if(this.xjData.hasUpdate == 1){
-
-			const list = this.selectList;
-
 			this.customData = this.hasColorInfo
 
 			if(this.xjData.cancel == 1){
@@ -261,12 +257,12 @@ export default {
 				this.affirm({index:0})
 			}else{
 
-				//判断list有没有数据,没有需要初始化
+				//判断list有没有数据,没有需要初始化(预订页同一 id 可能多条分类展示,按 id 判断是否与购物车中是同一种花材)
 				const list = this.selectList;
-				let has = false
+				let has = false // 是否已存在该花材
 				for (let index = 0; index < list.length; index++) {
 					const element = list[index];
-					if (element.id == this.hasColorInfo.id && element.classId == this.hasColorInfo.classId) {
+					if (element.id == this.hasColorInfo.id && ((this.pageType !== 'cg' && this.pageType !== 'bookCg') ? element.classId == this.hasColorInfo.classId : true)) {
 						has = true
 					}
 				}

+ 36 - 39
hdApp/src/pagesPurchase/ghsProduct.vue

@@ -42,10 +42,7 @@
 				<view style="height:150upx"></view>
 			</scroll-view>
 			<scroll-view scroll-y class="right-box" :scroll-into-view="scroll_into_view" scroll-with-animation="true"
-																@scroll="scroll_detail"
-																lower-threshold="100"
-																@scrolltolower="scroll_bottom">
-
+				@scroll="scroll_detail" lower-threshold="100" @scrolltolower="scroll_bottom">
 				<block v-if="!$util.isEmpty(filterProductInfo)">
 					<view class="item_list_bx selectAll" v-for="(classItem, classIndex) in filterProductInfo" :key="classIndex" :id="`class_${classIndex}`">
 						<view class="item_list_title">{{ classItem.className }}</view>
@@ -302,45 +299,45 @@ export default {
 			this.notOpenShop = false
 		}
 
-		if(this.xjData.hasUpdate == 1){
-			this.customData = this.hasColorInfo
+			if(this.xjData.hasUpdate == 1){
+				this.customData = this.hasColorInfo
 
-			if(this.xjData.cancel == 1){
-				this.customData.bigCount = 0
-				this.customData.smallCount = 0
-				this.affirm({index:0})
-			}else{
-				//判断list有没有数据,没有需要初始化
-				const list = this.selectList;
-				let has = false
-				for (let index = 0; index < list.length; index++) {
-					const element = list[index];
-					if (element.id == this.hasColorInfo.id && element.classId == this.hasColorInfo.classId) {
-						has = true
+				if(this.xjData.cancel == 1){
+					this.customData.bigCount = 0
+					this.customData.smallCount = 0
+					this.affirm({index:0})
+				}else{
+					//判断list有没有数据,没有需要初始化(进货页同一 id 可能多条分类展示,按 id 判断是否与购物车中是同一种花材)
+					const list = this.selectList;
+					let has = false
+					for (let index = 0; index < list.length; index++) {
+						const element = list[index];
+						if (element.id == this.hasColorInfo.id && ((this.pageType !== 'cg' && this.pageType !== 'bookCg') ? element.classId == this.hasColorInfo.classId : true)) {
+							has = true
+						}
 					}
-				}
 
-				if(has == false){
-					let params = {
-						...this.hasColorInfo,
-						bigCount: null,
-						smallCount: null,
-						autoPrice: null,
-						realityWeight: null,
-						userPrice: null,
-					};
-					list.push(params);
-					this.setSelectInfoByType({ type: this.pageType, info: list });
-				}
+					if(has == false){
+						let params = {
+							...this.hasColorInfo,
+							bigCount: null,
+							smallCount: null,
+							autoPrice: null,
+							realityWeight: null,
+							userPrice: null,
+						};
+						list.push(params);
+						this.setSelectInfoByType({ type: this.pageType, info: list });
+					}
 
-				this.customData.bigCount = this.xjData.stock
-				this.customData.smallCount = 0
-				this.customData.price = this.xjData.price
-				this.customData.itemPrice = this.xjData.price
-				this.customData.userPrice = (Number(this.xjData.stock) * Number(this.xjData.price)).toFixed(2)
+					this.customData.bigCount = this.xjData.stock
+					this.customData.smallCount = 0
+					this.customData.price = this.xjData.price
+					this.customData.itemPrice = this.xjData.price
+					this.customData.userPrice = (Number(this.xjData.stock) * Number(this.xjData.price)).toFixed(2)
 
-				this.affirm({index:1})
-			}
+					this.affirm({index:1})
+				}
 		}
 		this.xjData = {}
 	},
@@ -854,7 +851,7 @@ export default {
 		height: calc(100vh - 140upx);
 		flex: 1;
 		box-sizing: border-box;
-		padding-bottom:190upx;
+		padding-bottom:110upx;
 	}
 	.item_list_bx {
 		padding: 20upx 16upx 20upx 16upx;