feat(payment): 实现支付功能并优化相关页面
- 新增 payment 存储对象,用于保存支付相关信息 - 实现全款和部分款项支付逻辑 - 优化直播室、艺术品详情、个人中心等页面的支付相关展示和功能 - 添加千分位格式化函数,提升用户体验
This commit is contained in:
parent
0308ace199
commit
f4427bc094
@ -1,6 +1,7 @@
|
||||
<script setup>
|
||||
import itemDetail from '@/components/itemDetail/index.vue'
|
||||
import {userArtwork} from "~/api/goods/index.js";
|
||||
import {useRouter} from "#vue-router";
|
||||
definePageMeta({
|
||||
i18n: 'detail.text8'
|
||||
})
|
||||
@ -12,8 +13,10 @@ const initData = async () => {
|
||||
const res = await userArtwork({uuid})
|
||||
if (res.status === 0) {
|
||||
detail.value = res.data
|
||||
console.log('detail',detail.value)
|
||||
}
|
||||
}
|
||||
const router = useRouter();
|
||||
const position = ref({x: window?.innerWidth - 120 || 0, y: 240})
|
||||
const startPosition = ref({x: 0, y: 0})
|
||||
const isDragging = ref(false)
|
||||
@ -44,7 +47,9 @@ const onDrag = (e) => {
|
||||
const stopDrag = () => {
|
||||
isDragging.value = false
|
||||
}
|
||||
|
||||
const goPay=()=>{
|
||||
router.push('/payment')
|
||||
}
|
||||
onMounted(() => {
|
||||
document.addEventListener('mousemove', onDrag)
|
||||
document.addEventListener('mouseup', stopDrag)
|
||||
@ -57,6 +62,10 @@ onUnmounted(() => {
|
||||
document.removeEventListener('touchmove', onDrag)
|
||||
document.removeEventListener('touchend', stopDrag)
|
||||
})
|
||||
function formatThousands(num) {
|
||||
|
||||
return Number(num).toLocaleString();
|
||||
}
|
||||
initData()
|
||||
</script>
|
||||
|
||||
@ -64,8 +73,8 @@ initData()
|
||||
<div class="relative h-screen-nav flex flex-col">
|
||||
<itemDetail class="grow-1" :detail-info="detail.auctionArtworkInfo"/>
|
||||
<div v-if="[1,3,4].includes(detail.status)" class="h-81px bg-#fff flex justify-center pt-7px">
|
||||
<van-button class="w-213px !h-38px" type="primary">
|
||||
<span class="text-#fff text-14px">{{ $t('art_detail_page.button') }} RMB10,000</span>
|
||||
<van-button class="w-213px !h-38px" type="primary" @click="goPay">
|
||||
<span class="text-#fff text-14px">{{ $t('art_detail_page.button') }} {{detail.leftCurrency}}{{formatThousands(detail.leftPrice)}}</span>
|
||||
</van-button>
|
||||
</div>
|
||||
<div
|
||||
|
@ -22,7 +22,6 @@ const confirm=async ()=>{
|
||||
}else {
|
||||
router.push('/collectCode/signature/panel')
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -4,6 +4,10 @@ import {authStore} from "~/stores/auth/index.js";
|
||||
import {useI18n} from 'vue-i18n'
|
||||
const {auctionData} = liveStore()
|
||||
const {userInfo}= authStore()
|
||||
function formatThousands(num) {
|
||||
|
||||
return Number(num).toLocaleString();
|
||||
}
|
||||
const headList=[
|
||||
{
|
||||
label:useI18n().t('live_room.head'),
|
||||
@ -40,7 +44,7 @@ const headItem=(statusCode)=>{
|
||||
<div class="text-start shrink-0 w-60px" :style="`color: ${headItem(item.statusCode).color}`" >{{ headItem(item.statusCode).label }}</div>
|
||||
<div class="text-start shrink-0 w-80px">{{ item.auctionType==='local'? $t('live_room.spot'):$t('live_room.network') }}</div>
|
||||
<div class="text-start shrink-0 w-80px">{{ item.createdAt }}</div>
|
||||
<div class="text-start shrink-0 w-80px">{{item.baseCurrency}}{{ item.baseMoney }}</div>
|
||||
<div class="text-start shrink-0 w-80px">{{item.baseCurrency}}{{ formatThousands(item.baseMoney) }}</div>
|
||||
<div class="text-start text-#2B53AC shrink-0 w-20px">{{ item.userId===userInfo.ID?$t('live_room.me'):'' }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -11,7 +11,7 @@ import {showMinWindow} from "~/components/liveMinWindow/createMinWindow.js";
|
||||
|
||||
const { quoteStatus, changeStatus, show, auctionData, getSocketData ,lastSnapshot,fullLive} = liveStore()
|
||||
const { pageRef } = goodStore()
|
||||
const { userInfo } = authStore()
|
||||
const { userInfo ,payment} = authStore()
|
||||
const showTang = ref(false)
|
||||
const router = useRouter()
|
||||
// 拖动相关状态
|
||||
@ -168,7 +168,7 @@ const openOne = () => {
|
||||
|
||||
const paySide = computed(() => {
|
||||
//当前是否已成交,以及成交人是当前登录用户
|
||||
if (auctionData.value.artwork?.isSoled && auctionData.value.artwork?.buyInfo.userID === userInfo.value.ID) {
|
||||
if (auctionData.value.artwork?.isSoled && auctionData.value.artwork?.buyInfo?.userID === userInfo.value.ID) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -176,6 +176,9 @@ const paySide = computed(() => {
|
||||
})
|
||||
|
||||
const goPay = () => {
|
||||
payment.value.leftCurrency=auctionData.value?.nowAuctionPrice?.currency
|
||||
payment.value.leftPrice=auctionData.value?.nowAuctionPrice?.successPrice
|
||||
payment.value.buyUid=auctionData.value?.nowAuctionPrice?.successBuyUuid
|
||||
handleCapture()
|
||||
router.push('/signature/protocol')
|
||||
}
|
||||
|
@ -63,6 +63,11 @@ const loadMore = async () => {
|
||||
const { finished } = await getArtworkList()
|
||||
localState.value.finished = finished
|
||||
}
|
||||
watch(()=>{
|
||||
return auctionData.value?.artwork?.index
|
||||
},(newValue)=>{
|
||||
console.log('newValue',newValue)
|
||||
})
|
||||
watch(()=>props.show,(newValue)=>{
|
||||
if (newValue){
|
||||
nextTick(()=>{
|
||||
@ -113,7 +118,7 @@ watch(()=>props.show,(newValue)=>{
|
||||
loading="lazy"
|
||||
/>
|
||||
<div class="w-45px h-17px bg-#2B53AC text-12px line-height-none flex justify-center items-center absolute top-2px left-2px text-#fff">LOT{{item.index}}</div>
|
||||
<div v-if="auctionData.artwork.index===item?.index" class="w-80px h-20px bg-#B58047 flex line-height-none justify-center items-center text-#fff text-12px bottom-0 absolute blink">{{ $t('live_room.cast') }}</div>
|
||||
<div v-show="auctionData.artwork.index===item?.index" class="w-80px h-20px bg-#B58047 flex line-height-none justify-center items-center text-#fff text-12px bottom-0 absolute blink">{{ $t('live_room.cast') }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="ellipsis line-height-20px text-16px font-600 min-h-40px">
|
||||
|
@ -181,15 +181,15 @@ const tipOpen = () => {
|
||||
<div class="mr-5px">{{ t('live_room.lower_price') }}:{{ auctionData?.nowAuctionPrice?.currency }}</div>
|
||||
<div ref="nextPriceRef" class="min-w-50px"></div>
|
||||
</div>
|
||||
<div v-if="quoteStatus" class="mt-10px mb-10px">
|
||||
<div v-if="quoteStatus&&auctionData?.nowAuctionPrice?.nowPrice!=='0'" class="mt-10px mb-10px">
|
||||
<van-button @click="goBuy" color="#FFB25F" class="w-344px !h-[40px]">
|
||||
<div>{{
|
||||
`${t('live_room.confirm')} ${auctionData?.nowAuctionPrice?.currency} ${auctionData?.nowAuctionPrice?.nextPrice ?? 0}`
|
||||
`${t('live_room.confirm')} ${auctionData?.nowAuctionPrice?.currency} ${auctionData?.nowAuctionPrice?.nowPrice ?? 0}`
|
||||
}}
|
||||
</div>
|
||||
</van-button>
|
||||
</div>
|
||||
<div v-if="!quoteStatus" class="mt-10px mb-10px">
|
||||
<div v-else class="mt-10px mb-10px">
|
||||
<van-button @click="tipOpen" color="#D6D6D8" class="w-344px !h-[40px]" >
|
||||
<div class="text-#7D7D7F text-14px">{{ t('live_room.button') }}</div>
|
||||
</van-button>
|
||||
|
@ -4,45 +4,60 @@ import {createBuyOrder} from "~/api/goods/index.js";
|
||||
import {goodStore} from "~/stores/goods/index.js";
|
||||
import { showLoadingToast ,closeToast} from 'vant';
|
||||
import {authStore} from "~/stores/auth/index.js";
|
||||
const {checkoutSessionUrl}= authStore()
|
||||
import {message} from "~/components/x-message/useMessage.js";
|
||||
const {checkoutSessionUrl,payment}= authStore()
|
||||
const payStatus=ref(0)
|
||||
definePageMeta({
|
||||
title: '支付'
|
||||
})
|
||||
const changePayStatus=()=>{
|
||||
payStatus.value=payStatus.value===0?1:0
|
||||
}
|
||||
const { auctionData} = liveStore()
|
||||
const validateInput = (e) => {
|
||||
const value = e.target.value
|
||||
const char = String.fromCharCode(e.charCode)
|
||||
|
||||
if (!/[\d.]/.test(char)) {
|
||||
e.preventDefault()
|
||||
return
|
||||
}
|
||||
|
||||
if (char === '.' && (value.includes('.') || !value)) {
|
||||
e.preventDefault()
|
||||
return
|
||||
}
|
||||
|
||||
if (value.includes('.') && value.split('.')[1]?.length >= 2) {
|
||||
e.preventDefault()
|
||||
return
|
||||
}
|
||||
}
|
||||
const amount=ref('')
|
||||
const confirmPay=async ()=>{
|
||||
if (payStatus.value===1&&!amount.value){
|
||||
message.warning('请输入金额')
|
||||
return
|
||||
}
|
||||
if (Number(payment.value.leftPrice)<Number(amount.value)){
|
||||
message.warning('不得高于全部金额')
|
||||
return
|
||||
}
|
||||
showLoadingToast({
|
||||
message: '加载中...',
|
||||
forbidClick: true,
|
||||
});
|
||||
const res=await createBuyOrder({
|
||||
buyUid:auctionData.value?.nowAuctionPrice?.successBuyUuid,
|
||||
price:String(auctionData.value?.nowAuctionPrice?.successPrice),
|
||||
currency:auctionData.value?.nowAuctionPrice?.currency
|
||||
buyUid:payment.value.buyUid,
|
||||
price:payStatus.value===0?payment.value.leftPrice:amount.value,
|
||||
currency:payment.value.leftCurrency,
|
||||
testReturnHost:'http://192.168.88.50:3000',
|
||||
testReturnEndPoint:'/payment/result'
|
||||
})
|
||||
if (res.status===0){
|
||||
window.location.href=res.data.checkoutSessionUrl
|
||||
}
|
||||
}
|
||||
|
||||
const handleInput = (e) => {
|
||||
// 只允许数字和小数点,且只保留两位小数
|
||||
const value = e.target.value
|
||||
// 清除非数字和小数点
|
||||
let newValue = value.replace(/[^\d.]/g, '')
|
||||
// 确保只有一个小数点
|
||||
newValue = newValue.replace(/\.{2,}/g, '.')
|
||||
// 只保留第一个小数点
|
||||
newValue = newValue.replace(/^(\d*\.\d*)\./, '$1')
|
||||
// 保留两位小数
|
||||
if (newValue.indexOf('.') > 0) {
|
||||
newValue = newValue.slice(0, newValue.indexOf('.') + 3)
|
||||
}
|
||||
// 禁止输入以0开头的多位整数
|
||||
newValue = newValue.replace(/^0+(\d)/, '$1')
|
||||
|
||||
amount.value = newValue
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -51,9 +66,9 @@ const confirmPay=async ()=>{
|
||||
<img class="w-126px h-126px" src="@/static/images/dddf34@2x.png" alt="">
|
||||
</div>
|
||||
<div class="text-#1A1A1A text-16px mb-25px font-bold">{{payStatus===0?'支付全部':'支付部分'}}</div>
|
||||
<div class="text-#999999 text-16px mb-24px font-bold" v-if="payStatus===0">{{auctionData?.nowAuctionPrice?.currency}} {{auctionData?.nowAuctionPrice?.successPrice}}</div>
|
||||
<div class="text-#999999 text-16px mb-24px font-bold" v-if="payStatus===0">{{payment.leftCurrency}} {{payment?.leftPrice}}</div>
|
||||
<div class="mb-12px" v-else>
|
||||
<input class="w-272px h-48px bg-#F3F3F3 px-11px text-16px" type="text" :placeholder="`最多${auctionData?.nowAuctionPrice?.currency}${auctionData?.nowAuctionPrice?.successPrice}`" @keydown="validateInput">
|
||||
<input v-model="amount" class="w-272px h-48px bg-#F3F3F3 px-11px text-16px" type="text" :placeholder="`最多${payment.leftCurrency}${payment?.leftPrice}`" @input="handleInput">
|
||||
</div>
|
||||
<div class="text-#2B53AC text-14px" @click="changePayStatus">{{payStatus===1?'支付全部':'支付部分'}}</div>
|
||||
<div class="w-full mt-auto mb-40px">
|
||||
|
@ -10,7 +10,7 @@ definePageMeta({
|
||||
})
|
||||
const {t}=useI18n();
|
||||
const router = useRouter()
|
||||
const { userInfo } = authStore()
|
||||
const { userInfo,payment } = authStore()
|
||||
const showMyList = ref([])
|
||||
const localState = ref({
|
||||
finished: true,
|
||||
@ -47,10 +47,13 @@ const onRefresh = async () => {
|
||||
localState.value.refreshing = false
|
||||
}
|
||||
|
||||
const goPay = (status) => {
|
||||
if (status===1){
|
||||
const goPay = (item) => {
|
||||
payment.value.leftPrice=item.leftPrice
|
||||
payment.value.leftCurrency=item.leftCurrency
|
||||
payment.value.buyUid=item.uuid
|
||||
if (item.status===1){
|
||||
router.push('/signature/protocol')
|
||||
}else if (status===4){
|
||||
}else if (item.status===4){
|
||||
router.push('/payment')
|
||||
}
|
||||
}
|
||||
@ -129,7 +132,7 @@ fetchData()
|
||||
v-if="[1,3,4].includes(item.status)"
|
||||
class="w-73px !h-30px"
|
||||
type="primary"
|
||||
@click.stop="goPay(item.status)"
|
||||
@click.stop="goPay(item)"
|
||||
>
|
||||
<span class="text-12px">{{ $t('art_detail_page.button') }}</span>
|
||||
</van-button>
|
||||
|
@ -5,7 +5,13 @@ export const authStore = createGlobalState(() => {
|
||||
const userInfo=useLocalStorage('userInfo',{})
|
||||
const fingerprint=useLocalStorage('fingerprint','')
|
||||
const checkoutSessionUrl=useLocalStorage('checkoutSessionUrl','')
|
||||
const payment=useLocalStorage('payment',{
|
||||
leftPrice:'',
|
||||
leftCurrency:'',
|
||||
buyUid:''
|
||||
})
|
||||
return{
|
||||
payment,
|
||||
checkoutSessionUrl,
|
||||
userInfo,
|
||||
RefreshToken,
|
||||
|
@ -112,7 +112,7 @@ export const liveStore = createGlobalState(() => {
|
||||
// 定义常量
|
||||
const WS_TYPES = {
|
||||
TIP: 'tip',
|
||||
STOP_ARTWORK: 'stopArtwor',
|
||||
STOP_ARTWORK: 'stopArtwork',
|
||||
OVER: 'over'
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user