|
@@ -39,12 +39,6 @@
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
- <!-- 自动会员折扣/门店满减提示:放在客户卡片上方;手动选折后不展示 -->
|
|
|
|
|
- <view v-if="wholeDiscountTipText" class="whole-discount-tip">
|
|
|
|
|
- <text class="whole-discount-tip-label">{{ wholeDiscountTipLabel }}</text>
|
|
|
|
|
- <text class="whole-discount-tip-amount">{{ wholeDiscountTipAmount }}</text>
|
|
|
|
|
- </view>
|
|
|
|
|
-
|
|
|
|
|
<view class="customer-strip" @tap.stop="pickCustomer">
|
|
<view class="customer-strip" @tap.stop="pickCustomer">
|
|
|
<text class="customer-strip-label">客户</text>
|
|
<text class="customer-strip-label">客户</text>
|
|
|
<view class="customer-strip-name-wrap">
|
|
<view class="customer-strip-name-wrap">
|
|
@@ -258,6 +252,10 @@
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
|
|
+/**
|
|
|
|
|
+ * hdApp 工具-计算器直接收款:用户输入(及手选折)即应收。
|
|
|
|
|
+ * 不套会员折扣、门店满减;createOrder 传 skipMemberDiscount / skipShopMeetCut,避免服务端二次扣减。
|
|
|
|
|
+ */
|
|
|
import { createOrder } from '@/api/order/index'
|
|
import { createOrder } from '@/api/order/index'
|
|
|
import { getCustomInfo } from '@/api/custom'
|
|
import { getCustomInfo } from '@/api/custom'
|
|
|
import { mapActions, mapGetters } from 'vuex'
|
|
import { mapActions, mapGetters } from 'vuex'
|
|
@@ -307,7 +305,7 @@ export default {
|
|
|
customInfo: { discount: 1, balance: 0 },
|
|
customInfo: { discount: 1, balance: 0 },
|
|
|
/**
|
|
/**
|
|
|
* 是否已在打折弹层选手动折扣(含「无折扣」)。
|
|
* 是否已在打折弹层选手动折扣(含「无折扣」)。
|
|
|
- * false:应收按会员折扣/门店满减互斥自动扣;true:只按 discountZhe,不再套会员/门店。
|
|
|
|
|
|
|
+ * 仅影响手选折展示;会员折扣/门店满减不再参与应收。
|
|
|
*/
|
|
*/
|
|
|
manualDiscountLocked: false,
|
|
manualDiscountLocked: false,
|
|
|
}
|
|
}
|
|
@@ -316,10 +314,6 @@ export default {
|
|
|
...mapGetters({
|
|
...mapGetters({
|
|
|
myShopInfo: 'getMyShopInfo',
|
|
myShopInfo: 'getMyShopInfo',
|
|
|
}),
|
|
}),
|
|
|
- /** 门店满减字段来自登录门店 myShopInfo */
|
|
|
|
|
- shopMeetCutInfo() {
|
|
|
|
|
- return this.myShopInfo || {}
|
|
|
|
|
- },
|
|
|
|
|
/** 与 mall.vue 快捷开单一致:myShopInfo.defaultCustomId(goItemKjKd / goHsKjKd) */
|
|
/** 与 mall.vue 快捷开单一致:myShopInfo.defaultCustomId(goItemKjKd / goHsKjKd) */
|
|
|
shortcutCustomerId() {
|
|
shortcutCustomerId() {
|
|
|
const shop = this.myShopInfo || {}
|
|
const shop = this.myShopInfo || {}
|
|
@@ -352,46 +346,17 @@ export default {
|
|
|
return Math.min(10, Math.max(0.01, z)) / 10
|
|
return Math.min(10, Math.max(0.01, z)) / 10
|
|
|
},
|
|
},
|
|
|
/**
|
|
/**
|
|
|
- * 应收金额:
|
|
|
|
|
- * - 已选手动打折/无折扣:stackTotal * 手选倍率
|
|
|
|
|
- * - 否则:stackTotal 扣会员折扣与门店满减中较大者(互斥)
|
|
|
|
|
|
|
+ * 应收金额:算式合计 × 手选折扣(默认 10 折即原价)。
|
|
|
|
|
+ * 不套会员折扣、门店满减;提交时 skip* 避免服务端再扣。
|
|
|
*/
|
|
*/
|
|
|
stackDiscountedAmount() {
|
|
stackDiscountedAmount() {
|
|
|
const raw = Number(this.stackTotal)
|
|
const raw = Number(this.stackTotal)
|
|
|
if (isNaN(raw) || raw <= 0) return 0
|
|
if (isNaN(raw) || raw <= 0) return 0
|
|
|
- if (this.manualDiscountLocked) {
|
|
|
|
|
- return parseFloat((raw * this.discountRate).toFixed(2))
|
|
|
|
|
- }
|
|
|
|
|
- const pick = this.pickWholeOrderDiscount(raw, 1)
|
|
|
|
|
- let price = raw - (Number(pick.amount) || 0)
|
|
|
|
|
- if (price < 0) price = 0
|
|
|
|
|
- return parseFloat(price.toFixed(2))
|
|
|
|
|
|
|
+ return parseFloat((raw * this.discountRate).toFixed(2))
|
|
|
},
|
|
},
|
|
|
isDiscountActive() {
|
|
isDiscountActive() {
|
|
|
return this.manualDiscountLocked && Number(this.discountZhe) < 10 - 1e-6
|
|
return this.manualDiscountLocked && Number(this.discountZhe) < 10 - 1e-6
|
|
|
},
|
|
},
|
|
|
- /** 自动互斥优惠结果(手动选折时不算展示) */
|
|
|
|
|
- wholeDiscountPick() {
|
|
|
|
|
- if (this.manualDiscountLocked) return { type: 'none', amount: 0 }
|
|
|
|
|
- const raw = Number(this.stackTotal)
|
|
|
|
|
- if (isNaN(raw) || raw <= 0) return { type: 'none', amount: 0 }
|
|
|
|
|
- return this.pickWholeOrderDiscount(raw, 1)
|
|
|
|
|
- },
|
|
|
|
|
- wholeDiscountTipLabel() {
|
|
|
|
|
- const type = this.wholeDiscountPick.type
|
|
|
|
|
- if (!(Number(this.wholeDiscountPick.amount) > 0)) return ''
|
|
|
|
|
- if (type === 'member') return '会员折扣'
|
|
|
|
|
- if (type === 'shop') return '门店满减优惠'
|
|
|
|
|
- return ''
|
|
|
|
|
- },
|
|
|
|
|
- wholeDiscountTipAmount() {
|
|
|
|
|
- const amount = Number(this.wholeDiscountPick.amount) || 0
|
|
|
|
|
- if (amount <= 0) return ''
|
|
|
|
|
- return `-¥${parseFloat(amount.toFixed(2))}`
|
|
|
|
|
- },
|
|
|
|
|
- wholeDiscountTipText() {
|
|
|
|
|
- return !!(this.wholeDiscountTipLabel && this.wholeDiscountTipAmount)
|
|
|
|
|
- },
|
|
|
|
|
zl() {
|
|
zl() {
|
|
|
if (!(this.selHasPay === 1 && this.selPayWay === 4)) return 0
|
|
if (!(this.selHasPay === 1 && this.selPayWay === 4)) return 0
|
|
|
let amount = 0
|
|
let amount = 0
|
|
@@ -575,7 +540,7 @@ export default {
|
|
|
const z = Number(sel)
|
|
const z = Number(sel)
|
|
|
if (!isNaN(z) && z > 0 && z <= 10) {
|
|
if (!isNaN(z) && z > 0 && z <= 10) {
|
|
|
this.discountZhe = parseFloat(z.toFixed(2))
|
|
this.discountZhe = parseFloat(z.toFixed(2))
|
|
|
- // 本地存过小于 10 折视为曾选手动折扣;10=无折扣不锁,仍可走会员/门店自动优惠
|
|
|
|
|
|
|
+ // 本地存过小于 10 折视为曾选手动折扣;10 折不锁,应收即用户输入
|
|
|
this.manualDiscountLocked = z < 10 - 1e-6
|
|
this.manualDiscountLocked = z < 10 - 1e-6
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -594,7 +559,7 @@ export default {
|
|
|
}
|
|
}
|
|
|
if (z >= 10 - 1e-6) {
|
|
if (z >= 10 - 1e-6) {
|
|
|
this.discountZhe = 10
|
|
this.discountZhe = 10
|
|
|
- // 未选手动折或仅为默认 10:保持不锁,可走会员/门店;若曾在弹层点过「无折扣」则 locked 仍为 true
|
|
|
|
|
|
|
+ // 未选手动折或仅为默认 10:应收即用户输入;若曾在弹层点过「无折扣」则 locked 仍为 true
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
const ok = this.customDiscountZheList.some((x) => Math.abs(Number(x) - z) < 1e-4)
|
|
const ok = this.customDiscountZheList.some((x) => Math.abs(Number(x) - z) < 1e-4)
|
|
@@ -619,7 +584,7 @@ export default {
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
resetActiveDiscountToNone() {
|
|
resetActiveDiscountToNone() {
|
|
|
- // 重置为「未选手动折」,应收重新走会员/门店互斥
|
|
|
|
|
|
|
+ // 清空手选折扣,应收回到用户输入原价(不套会员折扣/门店满减)
|
|
|
this.discountZhe = 10
|
|
this.discountZhe = 10
|
|
|
this.manualDiscountLocked = false
|
|
this.manualDiscountLocked = false
|
|
|
this.persistDiscountSelected()
|
|
this.persistDiscountSelected()
|
|
@@ -687,65 +652,11 @@ export default {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
this.discountZhe = parseFloat(n.toFixed(2))
|
|
this.discountZhe = parseFloat(n.toFixed(2))
|
|
|
- // 含「无折扣」:锁定手动模式,不再套会员折扣/门店满减
|
|
|
|
|
|
|
+ // 含「无折扣」:锁定手选折;会员折扣/门店满减不参与应收
|
|
|
this.manualDiscountLocked = true
|
|
this.manualDiscountLocked = true
|
|
|
this.persistDiscountSelected()
|
|
this.persistDiscountSelected()
|
|
|
this.closeDiscountPopup()
|
|
this.closeDiscountPopup()
|
|
|
},
|
|
},
|
|
|
- /**
|
|
|
|
|
- * 会员折扣与门店满减互斥取大,对齐 WholeOrderDiscountClass / affirm 开单页。
|
|
|
|
|
- * 计算器直接收款 bigNum 按 1(与后端 zjGathering 一行 num=1 一致)。
|
|
|
|
|
- */
|
|
|
|
|
- pickWholeOrderDiscount(basePrice, bigNum) {
|
|
|
|
|
- const memberSave = this.calcMemberDiscountSave(basePrice)
|
|
|
|
|
- const shopSave = this.calcShopMeetCutSave(basePrice, bigNum)
|
|
|
|
|
- if (memberSave >= shopSave && memberSave > 0) {
|
|
|
|
|
- return { type: 'member', amount: memberSave }
|
|
|
|
|
- }
|
|
|
|
|
- if (shopSave > 0) {
|
|
|
|
|
- return { type: 'shop', amount: shopSave }
|
|
|
|
|
- }
|
|
|
|
|
- return { type: 'none', amount: 0 }
|
|
|
|
|
- },
|
|
|
|
|
- /** 会员折扣额:custom.discount ∈ (0,1) */
|
|
|
|
|
- calcMemberDiscountSave(basePrice) {
|
|
|
|
|
- const base = Number(Number(basePrice || 0).toFixed(2))
|
|
|
|
|
- const discount = Number(this.customInfo && this.customInfo.discount)
|
|
|
|
|
- if (!(discount > 0 && discount < 1) || base <= 0) {
|
|
|
|
|
- return 0
|
|
|
|
|
- }
|
|
|
|
|
- let after = Number((base * discount).toFixed(2))
|
|
|
|
|
- if (after <= 0) {
|
|
|
|
|
- after = 0.01
|
|
|
|
|
- }
|
|
|
|
|
- const save = Number((base - after).toFixed(2))
|
|
|
|
|
- return save > 0 ? save : 0
|
|
|
|
|
- },
|
|
|
|
|
- /** 门店满减额:与 OrderClass 门槛一致 */
|
|
|
|
|
- calcShopMeetCutSave(basePrice, bigNum) {
|
|
|
|
|
- const base = Number(Number(basePrice || 0).toFixed(2))
|
|
|
|
|
- const shop = this.shopMeetCutInfo || {}
|
|
|
|
|
- const meetNum = Number(shop.meetNum) || 0
|
|
|
|
|
- const meetAmount = Number(shop.meetAmount) || 0
|
|
|
|
|
- const cutOption = Number(shop.cutAmount) || 0
|
|
|
|
|
- const cutStyle = Number(shop.cutStyle) || 0
|
|
|
|
|
- let cutAmount = 0
|
|
|
|
|
- if (cutStyle === 0) {
|
|
|
|
|
- cutAmount = Number(cutOption.toFixed(2))
|
|
|
|
|
- } else {
|
|
|
|
|
- cutAmount = Number((base * (1 - cutOption)).toFixed(2))
|
|
|
|
|
- }
|
|
|
|
|
- if (!(cutAmount > 0 && meetNum >= 0 && meetAmount > 0)) {
|
|
|
|
|
- return 0
|
|
|
|
|
- }
|
|
|
|
|
- if (Number(bigNum || 0) < meetNum || base < meetAmount) {
|
|
|
|
|
- return 0
|
|
|
|
|
- }
|
|
|
|
|
- if (cutAmount >= base) {
|
|
|
|
|
- return 0
|
|
|
|
|
- }
|
|
|
|
|
- return cutAmount
|
|
|
|
|
- },
|
|
|
|
|
addCustomDiscountZhe() {
|
|
addCustomDiscountZhe() {
|
|
|
this.tapVoice()
|
|
this.tapVoice()
|
|
|
const raw = String(this.customZheInput || '').trim()
|
|
const raw = String(this.customZheInput || '').trim()
|
|
@@ -1100,10 +1011,13 @@ export default {
|
|
|
}
|
|
}
|
|
|
if (z >= 10 - 1e-6) {
|
|
if (z >= 10 - 1e-6) {
|
|
|
this.discountZhe = 10
|
|
this.discountZhe = 10
|
|
|
|
|
+ this.manualDiscountLocked = false
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
const ok = this.customDiscountZheList.some((x) => Math.abs(Number(x) - z) < 1e-4)
|
|
const ok = this.customDiscountZheList.some((x) => Math.abs(Number(x) - z) < 1e-4)
|
|
|
this.discountZhe = ok ? z : 10
|
|
this.discountZhe = ok ? z : 10
|
|
|
|
|
+ // 暂存里带了有效手选折则锁上手选,避免只改数字却不显示「X折后」
|
|
|
|
|
+ this.manualDiscountLocked = ok
|
|
|
},
|
|
},
|
|
|
applyHistoryRow(row) {
|
|
applyHistoryRow(row) {
|
|
|
if (!row) return
|
|
if (!row) return
|
|
@@ -1297,7 +1211,7 @@ export default {
|
|
|
emitHasPay !== 4
|
|
emitHasPay !== 4
|
|
|
) {
|
|
) {
|
|
|
const that = this
|
|
const that = this
|
|
|
- that.$util.confirmModal({content:'余额充值,可以使用余额支付'},() => {
|
|
|
|
|
|
|
+ that.$util.confirmModal({content:'余额充足,可以使用余额支付'},() => {
|
|
|
that._submitCashierPayCore(true)
|
|
that._submitCashierPayCore(true)
|
|
|
})
|
|
})
|
|
|
return
|
|
return
|
|
@@ -1321,7 +1235,7 @@ export default {
|
|
|
getGoods: 1,
|
|
getGoods: 1,
|
|
|
hasPay: emitHasPay != null ? emitHasPay : 0,
|
|
hasPay: emitHasPay != null ? emitHasPay : 0,
|
|
|
payWay: Number(emitHasPay) === 1 ? (emitPayWay != null ? emitPayWay : 0) : 0,
|
|
payWay: Number(emitHasPay) === 1 ? (emitPayWay != null ? emitPayWay : 0) : 0,
|
|
|
- // 应收已含自动会员/门店或手选折扣,禁止服务端再折/再满减
|
|
|
|
|
|
|
+ // 计算器按用户输入(及手选折)收款,禁止服务端再套会员折扣/门店满减
|
|
|
skipMemberDiscount: 1,
|
|
skipMemberDiscount: 1,
|
|
|
skipShopMeetCut: 1,
|
|
skipShopMeetCut: 1,
|
|
|
}
|
|
}
|
|
@@ -1556,30 +1470,6 @@ export default {
|
|
|
color: #d97706;
|
|
color: #d97706;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 客户卡片上方:自动会员折扣/门店满减提示 */
|
|
|
|
|
-.whole-discount-tip {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- flex-direction: row;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- justify-content: space-between;
|
|
|
|
|
- padding: 16upx 24upx;
|
|
|
|
|
- margin: 0 0 12upx;
|
|
|
|
|
- background-color: #ffffff;
|
|
|
|
|
- border-radius: 16upx;
|
|
|
|
|
- box-sizing: border-box;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.whole-discount-tip-label {
|
|
|
|
|
- font-size: 26upx;
|
|
|
|
|
- color: #333333;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.whole-discount-tip-amount {
|
|
|
|
|
- font-size: 28upx;
|
|
|
|
|
- font-weight: bold;
|
|
|
|
|
- color: #ff2842;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
.customer-strip {
|
|
.customer-strip {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
flex-direction: row;
|
|
flex-direction: row;
|
|
@@ -2207,4 +2097,4 @@ export default {
|
|
|
color: #c5ccd6;
|
|
color: #c5ccd6;
|
|
|
padding: 60upx 0;
|
|
padding: 60upx 0;
|
|
|
}
|
|
}
|
|
|
-</style>
|
|
|
|
|
|
|
+</style>
|