Просмотр исходного кода

零售端-订单提交运费、包装费计算优化

ouyang 5 дней назад
Родитель
Сommit
9b0ccc3c7a
2 измененных файлов с 118 добавлено и 127 удалено
  1. 20 10
      mallApp/src/api/ps-method/index.js
  2. 98 117
      mallApp/src/pages/billing/affirmMix.vue

+ 20 - 10
mallApp/src/api/ps-method/index.js

@@ -1,10 +1,20 @@
-/**
- * 花店配送方式 API(xhPsMethod / xhPsExplain)
- * 用途:商城混合结算页展示购买方式说明
- */
-import https from '@/plugins/luch-request_0.0.7/request'
-
-/** 获取门店全部配送方式及说明项 */
-export const getAllPsMethod = data => {
-  return https.get('/ps-method/get-all-method', data)
-}
+/**

+ * 花店配送方式 API(xhPsMethod / xhPsExplain)

+ * 用途:商城混合结算页展示购买方式说明、批量预览附加费

+ */

+import https from '@/plugins/luch-request_0.0.7/request'

+

+/** 获取门店全部配送方式及说明项;可传 itemTotalAmount、bigNum 一并返回各 style 附加费预览 */

+export const getAllPsMethod = data => {

+  return https.get('/ps-method/get-all-method', data)

+}

+

+/** 商品金额/扎数变化时批量刷新附加费(切换购买方式不再重复请求) */

+export const calcMixFeeBatch = data => {

+  return https.post('/ps-method/calc-mix-fee-batch', data)

+}

+

+/** 单购买方式预览(兼容保留) */

+export const calcMixFee = data => {

+  return https.post('/ps-method/calc-mix-fee', data)

+}


+ 98 - 117
mallApp/src/pages/billing/affirmMix.vue

@@ -386,7 +386,7 @@
 			class="affirm-hb-select-host"
 			hide-trigger
 			:hbData="hbData"
-			:totalPrice="allPriceFun"
+			:totalPrice="mixGoodsPrice"
 			v-model="selectedHbId"
 			@change="onHbChange"
 		></hb-select>
@@ -496,7 +496,7 @@ import { currentInfo } from "@/api/user";
 import { getInfo } from "@/api/shop";
 import { getAddressList } from "@/api/user-address";
 import { getAvailableHb } from "@/api/hb";
-import { getAllPsMethod } from "@/api/ps-method";
+import { getAllPsMethod, calcMixFeeBatch } from "@/api/ps-method";
 import MxDatePicker from "@/components/mx-datepicker/mx-datepicker.vue";
 import HbSelect from "@/components/hb/hb-select";
 
@@ -577,7 +577,15 @@ export default {
 			psMethodList: [],
 			/** 是否已拉取过默认地址,避免切换购买方式重复请求 */
 			defaultAddressLoaded: false,
-			defaultAddressLoading: false
+			defaultAddressLoading: false,
+			/** 各购买方式附加费预览缓存(进页/金额变化时批量拉取,切换方式只读缓存) */
+			unMeetFeeBySendType: {},
+			unMeetFeePreview: {
+				tip: "",
+				canOrder: true,
+				belowMinimum: false
+			},
+			unMeetFeeBatchTimer: null
 		};
 	},
 	onLoad() {
@@ -605,24 +613,26 @@ export default {
 
 		this.loadShopInfo();
 		this.loadSelectedAddress();
+		// 附加费在 loadPsMethods 中与配送方式一并批量返回
 		// 商品金额变化后刷新红包可用性(对齐 affirmGhs onShow)
 		if (this.shopInfo && this.shopInfo.id) {
 			this.getHbData();
 		}
 	},
 	watch: {
-		/** 商品总价变化时,剔除已不满足门槛的红包,并同步未达门槛附加费 */
-		allPriceFun() {
+		/** 商品总价变化时,剔除红包并批量刷新附加费缓存(不随购买方式切换重复请求) */
+		mixGoodsPrice() {
 			this.syncSelectedHbAfterPriceChange();
-			this.syncUnMeetFee();
+			this.loadUnMeetFeeBatch();
 			this.recheckRunnerFreeDelivery();
 		},
-		/** 购买方式切换后同步附加费;跑腿时重算是否免配送费 */
+		/** 切换购买方式:读缓存;style=2 跑腿仍按地址重算距离运费 */
 		"form.sendType"() {
-			this.syncUnMeetFee();
+			this.applyCurrentUnMeetFee();
 			this.recheckRunnerFreeDelivery();
 		},
 		mixItemBigNum() {
+			this.loadUnMeetFeeBatch();
 			this.recheckRunnerFreeDelivery();
 		}
 	},
@@ -675,14 +685,14 @@ export default {
 			if (!this.hbData || this.hbData.length === 0) {
 				return false;
 			}
-			const price = this.allPriceFun;
+			const price = this.mixGoodsPrice;
 			return this.hbData.some((item) => {
 				const min = Number(item.minConsume) || 0;
 				return price >= min;
 			});
 		},
 		modifyPrice() {
-			let price = Number(this.allPriceFun) || 0;
+			let price = Number(this.mixGoodsPrice) || 0;
 
 			if (this.hasAvailableHb && this.selectedHbId) {
 				price = price - Number(this.selectedHb.amount);
@@ -700,36 +710,25 @@ export default {
 			price = price.toFixed(2);
 			return parseFloat(price);
 		},
-		/** 混合单花材扎数(花束不计入最低消费数量) */
+		/** 混合单花材扎数(与提交 product.num 一致:仅支数时按 smallCount/ratio 折算) */
 		mixItemBigNum() {
 			let bigLength = 0;
 			(this.list || []).forEach((item) => {
-				if (!this.isBouquetItem(item)) {
+				if (this.isBouquetItem(item)) {
+					return;
+				}
+				if (Number(item.smallCount) > 0) {
+					const ratio = Number(item.ratio) || 1;
+					bigLength += Number(item.smallCount) / ratio;
+				} else {
 					bigLength += Number(item.bigCount) || 0;
 				}
 			});
 			return bigLength;
 		},
-		/** 未达最低消费时在配送说明中展示的提示(单行) */
+		/** 未达最低消费提示(来自批量预览缓存,与下单 calcFee 同源) */
 		unMeetWarningText() {
-			const method = this.currentPsMethod;
-			if (!method || !this.checkPsMethodBelowMinimum(method)) {
-				return "";
-			}
-			const unMeet = Number(method.unMeet) || 0;
-			const fee = Number(method.unMeetFee) || 0;
-			const conditionText = this.buildUnMeetConditionText(method);
-			if (!conditionText) {
-				return "";
-			}
-			if (unMeet === 1) {
-				return `订单不满${conditionText},不能下单`;
-			}
-			if ((unMeet === 0 || unMeet === 2) && fee > 0) {
-				const feeLabel = unMeet === 2 ? "包装费" : "运费";
-				return `订单不满${conditionText},加${feeLabel}${fee}元`;
-			}
-			return "";
+			return (this.unMeetFeePreview && this.unMeetFeePreview.tip) || "";
 		},
 		displaySendCost() {
 			if (this.form.sendType == 2) {
@@ -740,23 +739,6 @@ export default {
 			}
 			return false;
 		},
-		totalPrice() {
-			let allPrice = Number(this.mixGoodsPrice).toFixed(2);
-			allPrice = Number(allPrice);
-			let price = allPrice;
-
-			if (this.displaySendCost == true) {
-				if (!this.isFreeDelivery) {
-					price = price + this.form.sendCost;
-				}
-			}
-
-			this.needAddPackCost = false;
-			if (this.form.sendType == 4) {
-				// 快递暂不额外加价
-			}
-			return price.toFixed(2);
-		},
 		showDeliveryPolicy() {
 			if (!this.shopInfo) return false;
 
@@ -1005,16 +987,76 @@ export default {
 			if (!matched) {
 				this.changeSendType(options[0].value);
 			} else {
-				this.syncUnMeetFee();
+				this.applyCurrentUnMeetFee();
 				this.ensureDefaultAddressIfNeeded();
 			}
 		},
-		/** 拉取门店配送方式及说明(xhPsMethod / xhPsExplain) */
+		/** 批量预览接口入参(商品金额 + 花材扎数) */
+		getUnMeetFeeBatchParams() {
+			return {
+				itemTotalAmount: Number(this.mixGoodsPrice) || 0,
+				bigNum: Number(this.mixItemBigNum) || 0
+			};
+		},
+		/** 写入各 style 附加费缓存并应用到当前购买方式 */
+		setUnMeetFeeBatch(fees) {
+			if (!fees || typeof fees !== "object") {
+				return;
+			}
+			this.unMeetFeeBySendType = fees;
+			this.applyCurrentUnMeetFee();
+		},
+		/** 从缓存读取当前购买方式的附加费/提示(切换方式不调接口) */
+		applyCurrentUnMeetFee() {
+			const sendType = Number(this.form.sendType);
+			if (sendType < 0 || sendType > 4) {
+				this.form.unMeetSendCost = 0;
+				this.form.packCost = 0;
+				this.unMeetFeePreview = { tip: "", canOrder: true, belowMinimum: false };
+				return;
+			}
+			const data = this.unMeetFeeBySendType[String(sendType)] || {};
+			this.form.unMeetSendCost = Number(data.unMeetSendCost != null ? data.unMeetSendCost : data.sendCost) || 0;
+			this.form.packCost = Number(data.packingFee != null ? data.packingFee : data.packCost) || 0;
+			this.unMeetFeePreview = {
+				tip: data.tip || "",
+				canOrder: data.canOrder !== false,
+				belowMinimum: !!data.belowMinimum
+			};
+		},
+		/**
+		 * 商品金额/扎数变化时防抖批量刷新附加费(style=2 跑腿距离运费仍走 getDeliveryQuotes)
+		 */
+		loadUnMeetFeeBatch() {
+			if (this.unMeetFeeBatchTimer) {
+				clearTimeout(this.unMeetFeeBatchTimer);
+			}
+			this.unMeetFeeBatchTimer = setTimeout(() => {
+				this.unMeetFeeBatchTimer = null;
+				this.doLoadUnMeetFeeBatch();
+			}, 200);
+		},
+		/** 调用 calc-mix-fee-batch 刷新全量 style 缓存 */
+		doLoadUnMeetFeeBatch() {
+			const params = this.getUnMeetFeeBatchParams();
+			calcMixFeeBatch(params).then((res) => {
+				if (res.code == 1 && res.data && res.data.fees) {
+					this.setUnMeetFeeBatch(res.data.fees);
+				}
+			}).catch(() => {});
+		},
+		/** 拉取门店配送方式及说明(可选一并返回各 style 附加费预览) */
 		loadPsMethods() {
 			this.syncShopContext();
-			return getAllPsMethod().then((res) => {
-				if (res.code == 1 && res.data && Array.isArray(res.data.method)) {
-					this.psMethodList = res.data.method;
+			const params = this.getUnMeetFeeBatchParams();
+			return getAllPsMethod(params).then((res) => {
+				if (res.code == 1 && res.data) {
+					if (Array.isArray(res.data.method)) {
+						this.psMethodList = res.data.method;
+					}
+					if (res.data.fees) {
+						this.setUnMeetFeeBatch(res.data.fees);
+					}
 					this.syncSendTypeAfterMethodsLoaded();
 				}
 			}).catch(() => {});
@@ -1154,7 +1196,7 @@ export default {
 			if (!this.selectedHbId) {
 				return;
 			}
-			const price = Number(this.allPriceFun) || 0;
+			const price = Number(this.mixGoodsPrice) || 0;
 			const min = Number(this.selectedHb && this.selectedHb.minConsume) || 0;
 			if (price < min) {
 				this.selectedHbId = null;
@@ -1167,66 +1209,6 @@ export default {
 				this.form.cardInfo = "";
 			}
 		},
-		/** 拼接最低消费门槛文案,如 200元或30扎 */
-		buildUnMeetConditionText(method) {
-			if (!method) {
-				return "";
-			}
-			const parts = [];
-			const minAmount = Number(method.minAmount) || 0;
-			const minNum = Number(method.minNum) || 0;
-			if (minAmount > 0) {
-				parts.push(`${minAmount}元`);
-			}
-			if (minNum > 0) {
-				parts.push(`${minNum}扎`);
-			}
-			return parts.join("或");
-		},
-		/**
-		 * 判断当前结算单是否未达最低消费
-		 * 满 minAmount 或 minNum 任一达标即视为达标;两者均未达标才返回 true
-		 */
-		checkPsMethodBelowMinimum(method) {
-			if (!method) {
-				return false;
-			}
-			const minAmount = Number(method.minAmount) || 0;
-			const minNum = Number(method.minNum) || 0;
-			if (minAmount <= 0 && minNum <= 0) {
-				return false;
-			}
-			const allPrice = Number(this.allPriceFun) || 0;
-			const bigNum = Number(this.mixItemBigNum) || 0;
-			const amountOk = minAmount <= 0 || allPrice >= minAmount;
-			const numOk = minNum <= 0 || bigNum >= minNum;
-			return !(amountOk || numOk);
-		},
-		/** 同步未达最低消费时的附加运费/包装费(与后端 PsMethodClass.calcFee 一致,按购买方式每日一次) */
-		syncUnMeetFee() {
-			const method = this.currentPsMethod;
-			this.form.unMeetSendCost = 0;
-			this.form.packCost = 0;
-			if (!method || !this.checkPsMethodBelowMinimum(method)) {
-				return;
-			}
-			const unMeet = Number(method.unMeet) || 0;
-			const fee = parseFloat(Number(method.unMeetFee) || 0);
-			if (fee <= 0) {
-				return;
-			}
-			if (unMeet === 0) {
-				if (Number(method.todaySendFeeLocked) === 1) {
-					return;
-				}
-				this.form.unMeetSendCost = fee;
-			} else if (unMeet === 2) {
-				if (Number(method.todayPackFeeLocked) === 1) {
-					return;
-				}
-				this.form.packCost = fee;
-			}
-		},
 		onAnonymityChange(e) {
 			this.form.anonymity = e.detail.value ? 1 : 0;
 		},
@@ -1496,7 +1478,7 @@ export default {
 				this.deliveryQuotesLoading = false;
 				this.showDistance = 0;
 			}
-			this.syncUnMeetFee();
+			this.applyCurrentUnMeetFee();
 		},
 		/** 构建跑腿报价请求中的收货地址(使用结算页所选地址坐标) */
 		buildDeliveryQuoteAddressPayload() {
@@ -1633,8 +1615,7 @@ export default {
 				}
 			}
 
-			const method = this.currentPsMethod;
-			if (method && Number(method.unMeet) === 1 && this.checkPsMethodBelowMinimum(method)) {
+			if (this.unMeetFeePreview && this.unMeetFeePreview.canOrder === false) {
 				this.$msg(this.unMeetWarningText || "未达到最低消费,不能下单");
 				return false;
 			}