feat(支付): 重构支付方式逻辑以支持店铺模式配置

新增支付方式映射文件,支持根据店铺模式显示不同支付选项
重构结算组件,动态显示支持的支付方式并处理支付逻辑
在商品列表选择店铺时保存选中店铺信息
This commit is contained in:
dzq 2025-06-21 16:33:17 +08:00
parent 39820a036d
commit 6e49347de2
4 changed files with 99 additions and 68 deletions

View File

@ -0,0 +1,14 @@
export const paymentMethodOptions = [
{ label: '微信支付', value: 0, type: 'primary' },
{ label: '借呗支付', value: 1, type: 'success' },
{ label: '要呗支付', value: 2, type: 'info' },
{ label: '余额支付', value: 3, type: 'warning' },
];
export const modeToPaymentMethodMap: Record<number, number[]> = {
0: [0],
1: [0, 1],
2: [0, 1],
3: [0],
4: [2],
};

View File

@ -61,6 +61,7 @@ const showAb98BindPopup = ref(false);
function handleShopSelect(selectedShopId: number) { function handleShopSelect(selectedShopId: number) {
shopId.value = selectedShopId; shopId.value = selectedShopId;
showShopList.value = false; showShopList.value = false;
productStore.setSelectedShop(shopList.value.find(shop => shop.shopId === selectedShopId)!);
productStore.getGoods(selectedShopId); productStore.getGoods(selectedShopId);
cartStore.clearCart(); cartStore.clearCart();
activeCategory.value = 0; activeCategory.value = 0;

View File

@ -1,25 +1,42 @@
<script setup lang="ts"> <script setup lang="ts">
import { useCartStore } from "@/pinia/stores/cart" import { useCartStore } from "@/pinia/stores/cart";
import { useWxStore } from "@/pinia/stores/wx" import { useWxStore } from "@/pinia/stores/wx";
import { useAb98UserStore } from '@/pinia/stores/ab98-user' import { useAb98UserStore } from '@/pinia/stores/ab98-user';
import { storeToRefs } from "pinia" import { storeToRefs } from "pinia";
import { showConfirmDialog } from "vant" import { showConfirmDialog } from "vant";
import { submitOrderApi } from "@/common/apis/shop" import { submitOrderApi } from "@/common/apis/shop";
import type { SubmitOrderRequestData, WxJsApiPreCreateResponse } from "@/common/apis/shop/type" import type { SubmitOrderRequestData, WxJsApiPreCreateResponse } from "@/common/apis/shop/type";
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router';
import { useProductStore } from "@/pinia/stores/product";
//
import { paymentMethodOptions, modeToPaymentMethodMap } from "@/common/utils/maps/payment";
const router = useRouter() const router = useRouter();
const cartStore = useCartStore() const cartStore = useCartStore();
const { cartItems, totalPrice } = storeToRefs(cartStore) const { cartItems, totalPrice } = storeToRefs(cartStore);
const wxStore = useWxStore() const wxStore = useWxStore();
const { openid, balance, corpidLogin, userid: qyUserid, name: qyName } = storeToRefs(wxStore) const { openid, balance, corpidLogin, userid: qyUserid, name: qyName } = storeToRefs(wxStore);
const ab98UserStore = useAb98UserStore() const ab98UserStore = useAb98UserStore();
const { tel, userid: ab98Userid, name } = storeToRefs(ab98UserStore) const { tel, userid: ab98Userid, name } = storeToRefs(ab98UserStore);
const selectedPayment = ref<'wechat' | 'balance' | 'approval'>('wechat'); const productStore = useProductStore();
//
const supportedPayments = computed(() => {
const shopMode = productStore.selectedShop?.mode || 0;
const allowedValues = modeToPaymentMethodMap[shopMode] || [];
//
// 1.
// 2. (0)
return paymentMethodOptions.filter(option => allowedValues.includes(option.value)
&& (option.value !== 0 || !corpidLogin.value));
});
//
const selectedPayment = ref<string>(supportedPayments.value[0]?.value.toString() || '0');
const contact = ref(""); const contact = ref("");
const applyRemark = ref(""); const applyRemark = ref("");
const submitting = ref(false); const submitting = ref(false);
@ -28,28 +45,13 @@ const isApproval = computed(() => {
return cartItems.value.some(item => item.product.belongType == 1); return cartItems.value.some(item => item.product.belongType == 1);
}); });
watch(corpidLogin, (newValue) => { // value
if (isApproval.value) { const paymentValueToType: Record<string, 'wechat' | 'balance' | 'approval'> = {
selectedPayment.value = 'approval'; '0': 'wechat',
} else { '1': 'balance',
if (newValue) { '2': 'approval',
selectedPayment.value = 'balance'; '3': 'balance'
} else { };
selectedPayment.value = 'wechat';
}
}
}, { immediate: true });
watch(isApproval, (newValue) => {
if (newValue) {
selectedPayment.value = 'approval';
} else {
if (corpidLogin.value) {
selectedPayment.value = 'balance';
} else {
selectedPayment.value = 'wechat';
}
}
})
function callWxJsApi(paymentInfo: WxJsApiPreCreateResponse) { function callWxJsApi(paymentInfo: WxJsApiPreCreateResponse) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -127,7 +129,8 @@ async function handleSubmit() {
quantity: item.quantity, quantity: item.quantity,
cellId: item.product.cellId, cellId: item.product.cellId,
})), })),
paymentType: selectedPayment.value, // value
paymentType: paymentValueToType[selectedPayment.value] || 'wechat',
mobile: tel.value, mobile: tel.value,
name: isInternal === 2 ? qyName.value : name.value, name: isInternal === 2 ? qyName.value : name.value,
applyRemark: applyRemark.value, applyRemark: applyRemark.value,
@ -141,28 +144,35 @@ async function handleSubmit() {
throw new Error("订单提交失败") throw new Error("订单提交失败")
} }
if (selectedPayment.value === 'wechat') { if (selectedPayment.value == '0') { //
if (data.paymentInfo) { if (data.paymentInfo) {
await callWxJsApi(data.paymentInfo); await callWxJsApi(data.paymentInfo);
} }
} else if (selectedPayment.value === 'balance') { } else if (selectedPayment.value == '1') { //
// wxStore.setBalance(data.newBalance || 0);
try {
await showConfirmDialog({
title: "支付成功",
message: `借呗支付成功,剩余余额:¥${data.newBalance?.toFixed(2)}`
})
} catch (error) {}
} else if (selectedPayment.value == '2') { //
try {
await showConfirmDialog({
title: "提交领用申请成功",
message: `请等待管理员审批`
})
} catch (error) {}
} else if (selectedPayment.value == '3') { //
wxStore.setBalance(data.newBalance || 0); wxStore.setBalance(data.newBalance || 0);
try { try {
await showConfirmDialog({ await showConfirmDialog({
title: "支付成功", title: "支付成功",
message: `余额支付成功,剩余余额:¥${data.newBalance?.toFixed(2)}` message: `余额支付成功,剩余余额:¥${data.newBalance?.toFixed(2)}`
}) })
} catch (error) { } catch (error) {}
} } else { //
} else if (selectedPayment.value === 'approval') { //
//
try {
await showConfirmDialog({
title: "提交领用申请成功",
message: `请等待管理员审批`
})
} catch (error) { }
} }
router.push({ router.push({
@ -225,25 +235,24 @@ async function handleSubmit() {
<van-field v-model="applyRemark" label="领用说明" type="textarea" rows="2" autosize /> <van-field v-model="applyRemark" label="领用说明" type="textarea" rows="2" autosize />
</van-cell-group> --> </van-cell-group> -->
<!-- 支付方式 -->
<van-cell-group v-if="!isApproval" class="contact-form"> <van-cell-group v-if="!isApproval" class="contact-form">
<van-cell v-if="!corpidLogin" :class="['payment-option', { selected: selectedPayment === 'wechat' }]" <van-cell
@click="selectedPayment = 'wechat'"> v-for="method in supportedPayments"
<van-icon name="wechat" class="method-icon" /> :key="method.value"
<span class="method-label">微信支付</span> :class="['payment-option', { selected: selectedPayment === method.value.toString(), disabled: method.value === 1 && (balance < totalPrice) }]"
<div class="empty"></div> @click="selectedPayment = method.value.toString()"
<van-icon v-if="selectedPayment === 'wechat'" name="success" class="check-icon" /> >
</van-cell> <van-icon
:name="method.value === 0 ? 'wechat' : method.value === 1 ? 'balance-o' : method.value === 2 ? 'credit-card' : 'wallet'"
<van-cell v-if="balance && balance > 0" class="method-icon"
:class="['payment-option', { selected: selectedPayment === 'balance', disabled: balance < totalPrice }]" />
@click="selectedPayment = 'balance'">
<van-icon name="balance-o" class="method-icon" />
<span class="method-label"> <span class="method-label">
借呗支付 {{ method.label }}
<span class="balance-amount">当前¥{{ balance.toFixed(2) }}</span> <span v-if="method.value === 1" class="balance-amount">当前¥{{ balance.toFixed(2) }}</span>
</span> </span>
<div class="empty"></div> <div class="empty"></div>
<van-icon v-if="selectedPayment === 'balance'" name="success" class="check-icon" /> <van-icon v-if="selectedPayment === method.value.toString()" name="success" class="check-icon" />
</van-cell> </van-cell>
</van-cell-group> </van-cell-group>

View File

@ -1,3 +1,4 @@
import { ShopEntity } from "@/common/apis/shop/type"
import { pinia } from "@/pinia" import { pinia } from "@/pinia"
import { getShopGoodsApi } from "@@/apis/shop" import { getShopGoodsApi } from "@@/apis/shop"
@ -19,6 +20,11 @@ export const useProductStore = defineStore("product", () => {
const labels = ref<{ id: number, name: string }[]>([]); const labels = ref<{ id: number, name: string }[]>([]);
const categories = ref<Product[]>([]); const categories = ref<Product[]>([]);
const shopId = ref<number|null>(null); const shopId = ref<number|null>(null);
const selectedShop = ref<ShopEntity|null>(null);
const setSelectedShop = (shop: ShopEntity) => {
selectedShop.value = shop;
}
const getGoods = async (shopId_?: number) => { const getGoods = async (shopId_?: number) => {
if (shopId_ && shopId_ > 0) { if (shopId_ && shopId_ > 0) {
@ -58,7 +64,8 @@ export const useProductStore = defineStore("product", () => {
console.error("获取商品数据失败:", error) console.error("获取商品数据失败:", error)
} }
} }
return { labels, categories, shopId, getGoods } return { labels, categories, shopId, selectedShop,
getGoods, setSelectedShop }
}) })
/** /**