mirror of
https://github.com/yangjian102621/geekai.git
synced 2026-05-05 09:24:29 +08:00
移动端支付已完成
This commit is contained in:
@@ -112,6 +112,7 @@ func (h *PaymentHandler) SyncOrders() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, order := range orders {
|
for _, order := range orders {
|
||||||
|
time.Sleep(time.Second * 1)
|
||||||
//超时15分钟的订单,直接标记为已关闭
|
//超时15分钟的订单,直接标记为已关闭
|
||||||
if time.Now().After(order.CreatedAt.Add(time.Minute * 15)) {
|
if time.Now().After(order.CreatedAt.Add(time.Minute * 15)) {
|
||||||
h.DB.Model(&model.Order{}).Where("id", order.Id).Update("checked", true)
|
h.DB.Model(&model.Order{}).Where("id", order.Id).Update("checked", true)
|
||||||
|
|||||||
@@ -131,7 +131,7 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
border: 1px solid var(--theme-border-primary);
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.product-header {
|
.product-header {
|
||||||
@@ -270,7 +270,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 12px 16px;
|
padding: 10px 16px;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="form">
|
<div class="form px-3">
|
||||||
<div class="text-center" v-if="email !== ''">当前已绑定邮箱:{{ email }}</div>
|
<div class="text-center" v-if="email !== ''">当前已绑定邮箱:{{ email }}</div>
|
||||||
<el-form label-position="top">
|
<el-form label-position="top">
|
||||||
<el-form-item label="邮箱地址">
|
<el-form-item label="邮箱地址">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="form">
|
<div class="form px-3">
|
||||||
<div class="text-center" v-if="mobile !== ''">当前已绑手机号:{{ mobile }}</div>
|
<div class="text-center" v-if="mobile !== ''">当前已绑手机号:{{ mobile }}</div>
|
||||||
<el-form label-position="top">
|
<el-form label-position="top">
|
||||||
<el-form-item label="手机号">
|
<el-form-item label="手机号">
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
v-model="showDialog"
|
v-model="showDialog"
|
||||||
:close-on-click-modal="true"
|
:close-on-click-modal="true"
|
||||||
:show-close="true"
|
:show-close="true"
|
||||||
style="max-width: 600px"
|
style="max-width: 400px"
|
||||||
:before-close="close"
|
:before-close="close"
|
||||||
title="修改密码"
|
title="修改密码"
|
||||||
>
|
>
|
||||||
<div class="form" id="password-form">
|
<div class="form px-3" id="password-form">
|
||||||
<el-form :model="form" label-width="120px">
|
<el-form :model="form" label-position="top">
|
||||||
<el-form-item label="原始密码">
|
<el-form-item label="原始密码">
|
||||||
<el-input v-model="form['old_pass']" type="password" />
|
<el-input v-model="form['old_pass']" type="password" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
:append-to-body="true"
|
:append-to-body="true"
|
||||||
>
|
>
|
||||||
<div class="form">
|
<div class="form">
|
||||||
<el-form :model="form" label-width="80px" label-position="left">
|
<el-form :model="form" label-width="80px" label-position="top">
|
||||||
<el-tabs v-model="form.type" class="demo-tabs">
|
<el-tabs v-model="form.type" class="demo-tabs">
|
||||||
<el-tab-pane label="手机号验证" name="mobile">
|
<el-tab-pane label="手机号验证" name="mobile">
|
||||||
<el-form-item label="手机号">
|
<el-form-item label="手机号">
|
||||||
|
|||||||
@@ -55,7 +55,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="product-title">
|
<div class="product-title">
|
||||||
<h3 class="name">{{ item.name }}</h3>
|
<h3 class="name">{{ item.name }}</h3>
|
||||||
<p class="description">{{ item.description || '全模型通用算力' }}</p>
|
<p class="description">算力值:{{ item.power }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -169,12 +169,12 @@ import RedeemVerify from '@/components/RedeemVerify.vue'
|
|||||||
import UserOrder from '@/components/UserOrder.vue'
|
import UserOrder from '@/components/UserOrder.vue'
|
||||||
import { checkSession, getSystemInfo } from '@/store/cache'
|
import { checkSession, getSystemInfo } from '@/store/cache'
|
||||||
import { useSharedStore } from '@/store/sharedata'
|
import { useSharedStore } from '@/store/sharedata'
|
||||||
|
import { closeLoading, showLoading } from '@/utils/dialog'
|
||||||
import { httpGet, httpPost } from '@/utils/http'
|
import { httpGet, httpPost } from '@/utils/http'
|
||||||
|
import { isMobile } from '@/utils/libs'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import QRCode from 'qrcode'
|
import QRCode from 'qrcode'
|
||||||
import { onMounted, ref, onUnmounted } from 'vue'
|
import { onMounted, onUnmounted, ref } from 'vue'
|
||||||
import { showLoading, closeLoading } from '@/utils/dialog'
|
|
||||||
import { isMobile } from '@/utils/libs'
|
|
||||||
|
|
||||||
const list = ref([])
|
const list = ref([])
|
||||||
const vipImg = ref('/images/menu/member.png')
|
const vipImg = ref('/images/menu/member.png')
|
||||||
|
|||||||
@@ -4,14 +4,6 @@
|
|||||||
<!-- 产品套餐 -->
|
<!-- 产品套餐 -->
|
||||||
<div class="products-section">
|
<div class="products-section">
|
||||||
<div class="text-center bg-[#7c3aed] text-white rounded-lg p-3 mb-4">充值套餐</div>
|
<div class="text-center bg-[#7c3aed] text-white rounded-lg p-3 mb-4">充值套餐</div>
|
||||||
<!-- <div class="info-alert" v-if="vipInfoText">
|
|
||||||
<van-notice-bar
|
|
||||||
:text="vipInfoText"
|
|
||||||
color="#1989fa"
|
|
||||||
background="#ecf9ff"
|
|
||||||
:scrollable="false"
|
|
||||||
/>
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
<div class="products-grid" v-if="list.length > 0">
|
<div class="products-grid" v-if="list.length > 0">
|
||||||
<div v-for="item in list" :key="item.id" class="product-card">
|
<div v-for="item in list" :key="item.id" class="product-card">
|
||||||
@@ -24,40 +16,29 @@
|
|||||||
|
|
||||||
<div class="product-info">
|
<div class="product-info">
|
||||||
<div class="price-info">
|
<div class="price-info">
|
||||||
<div class="original-price">
|
<div class="discount-price">
|
||||||
<span class="label">原价:</span>
|
<span class="label">商品价格:</span>
|
||||||
<span class="price">¥{{ item.price }}</span>
|
<span class="price">¥{{ item.price }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="discount-price">
|
|
||||||
<span class="label">优惠价:</span>
|
|
||||||
<span class="price">¥{{ item.discount }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="product-details">
|
<div class="product-details">
|
||||||
<div class="detail-item">
|
<div class="detail-item">
|
||||||
<span class="label">有效期:</span>
|
<span class="label">算力值:</span>
|
||||||
<span class="value">{{ item.days > 0 ? item.days + '天' : '长期有效' }}</span>
|
<span class="value">{{ item.power }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-item">
|
|
||||||
<span class="label">算力值:</span>
|
|
||||||
<span class="value">{{ item.power }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="payment-methods">
|
<div class="payment-methods">
|
||||||
<div class="methods-grid">
|
<div class="methods-grid">
|
||||||
<van-button
|
<button class="payment-btn wechat-btn" @click="wxPay(item)">
|
||||||
v-for="payWay in payWays"
|
<i class="iconfont icon-wechat-pay"></i>
|
||||||
:key="payWay.pay_type"
|
<span>微信支付</span>
|
||||||
size="small"
|
</button>
|
||||||
:color="getPayButtonColor(payWay.pay_type)"
|
<button class="payment-btn alipay-btn" @click="alipay(item)">
|
||||||
@click="pay(item, payWay)"
|
<i class="iconfont icon-alipay"></i>
|
||||||
class="pay-button"
|
<span>支付宝</span>
|
||||||
>
|
</button>
|
||||||
<i class="iconfont" :class="getPayIcon(payWay.pay_type)"></i>
|
|
||||||
{{ getPayButtonText(payWay.pay_type) }}
|
|
||||||
</van-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -90,29 +71,27 @@
|
|||||||
|
|
||||||
<!-- 支付弹窗 -->
|
<!-- 支付弹窗 -->
|
||||||
<van-dialog
|
<van-dialog
|
||||||
v-model="showPayDialog"
|
:show="showPayDialog"
|
||||||
title="支付确认"
|
:title="title"
|
||||||
:show-cancel-button="false"
|
:show-cancel-button="false"
|
||||||
|
confirm-button-text="确认支付成功"
|
||||||
:close-on-click-overlay="false"
|
:close-on-click-overlay="false"
|
||||||
|
@confirm="paySuccess"
|
||||||
>
|
>
|
||||||
<div class="pay-dialog-content">
|
<div class="pay-dialog-content">
|
||||||
<div v-if="qrImg" class="qr-section">
|
<div v-if="qrImg" class="qr-section">
|
||||||
<p class="pay-tip">请使用微信扫码支付:</p>
|
|
||||||
<div class="qr-container">
|
<div class="qr-container">
|
||||||
<van-image :src="qrImg" width="200" height="200" />
|
<van-image :src="qrImg" width="200" height="200" />
|
||||||
</div>
|
</div>
|
||||||
<p class="pay-amount">¥{{ currentPrice }}</p>
|
<p class="pay-amount">¥{{ currentPrice }}</p>
|
||||||
</div>
|
<p class="pay-tip">支付成功之后点击确定按钮</p>
|
||||||
<div class="pay-actions">
|
|
||||||
<van-button type="success" @click="payCallback(true)">支付成功</van-button>
|
|
||||||
<van-button type="danger" @click="payCallback(false)">支付失败</van-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</van-dialog>
|
</van-dialog>
|
||||||
|
|
||||||
<!-- 卡密兑换弹窗 -->
|
<!-- 卡密兑换弹窗 -->
|
||||||
<van-dialog
|
<van-dialog
|
||||||
v-model:show="showRedeemVerifyDialog"
|
:show="showRedeemVerifyDialog"
|
||||||
title="卡密兑换"
|
title="卡密兑换"
|
||||||
:show-cancel-button="false"
|
:show-cancel-button="false"
|
||||||
:show-confirm-button="false"
|
:show-confirm-button="false"
|
||||||
@@ -134,7 +113,7 @@ import { useSharedStore } from '@/store/sharedata'
|
|||||||
import { httpGet, httpPost } from '@/utils/http'
|
import { httpGet, httpPost } from '@/utils/http'
|
||||||
import QRCode from 'qrcode'
|
import QRCode from 'qrcode'
|
||||||
import { showFailToast, showLoadingToast, showSuccessToast } from 'vant'
|
import { showFailToast, showLoadingToast, showSuccessToast } from 'vant'
|
||||||
import { computed, onMounted, ref } from 'vue'
|
import { onMounted, onUnmounted, ref } from 'vue'
|
||||||
|
|
||||||
// 响应式数据
|
// 响应式数据
|
||||||
const list = ref([])
|
const list = ref([])
|
||||||
@@ -143,7 +122,6 @@ const isLogin = ref(false)
|
|||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
const loadingText = ref('加载中...')
|
const loadingText = ref('加载中...')
|
||||||
const vipInfoText = ref('')
|
const vipInfoText = ref('')
|
||||||
const payWays = ref([])
|
|
||||||
const userOrderKey = ref(0)
|
const userOrderKey = ref(0)
|
||||||
|
|
||||||
// 弹窗控制
|
// 弹窗控制
|
||||||
@@ -154,53 +132,17 @@ const showPayDialog = ref(false)
|
|||||||
const qrImg = ref('')
|
const qrImg = ref('')
|
||||||
const currentPrice = ref(0)
|
const currentPrice = ref(0)
|
||||||
const currentProduct = ref(null)
|
const currentProduct = ref(null)
|
||||||
const currentPayWay = ref(null)
|
const selectedPid = ref(0)
|
||||||
|
const orderTimeout = ref(1800)
|
||||||
|
const handler = ref(null)
|
||||||
|
const title = ref('')
|
||||||
|
|
||||||
const store = useSharedStore()
|
const store = useSharedStore()
|
||||||
|
|
||||||
// 支付按钮颜色
|
|
||||||
const getPayButtonColor = (payType) => {
|
|
||||||
const colors = {
|
|
||||||
alipay: '#15A6E8',
|
|
||||||
wxpay: '#07C160',
|
|
||||||
qqpay: '#12B7F5',
|
|
||||||
paypal: '#0070BA',
|
|
||||||
jdpay: '#E1251B',
|
|
||||||
douyin: '#000000',
|
|
||||||
}
|
|
||||||
return colors[payType] || '#1989fa'
|
|
||||||
}
|
|
||||||
|
|
||||||
// 支付按钮图标
|
|
||||||
const getPayIcon = (payType) => {
|
|
||||||
const icons = {
|
|
||||||
alipay: 'icon-alipay',
|
|
||||||
wxpay: 'icon-wechat-pay',
|
|
||||||
qqpay: 'icon-qq',
|
|
||||||
paypal: 'icon-paypal',
|
|
||||||
jdpay: 'icon-jd-pay',
|
|
||||||
douyin: 'icon-douyin',
|
|
||||||
}
|
|
||||||
return icons[payType] || 'icon-money'
|
|
||||||
}
|
|
||||||
|
|
||||||
// 支付按钮文本
|
|
||||||
const getPayButtonText = (payType) => {
|
|
||||||
const texts = {
|
|
||||||
alipay: '支付宝',
|
|
||||||
wxpay: '微信支付',
|
|
||||||
qqpay: 'QQ钱包',
|
|
||||||
paypal: 'PayPal',
|
|
||||||
jdpay: '京东支付',
|
|
||||||
douyin: '抖音支付',
|
|
||||||
}
|
|
||||||
return texts[payType] || '支付'
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化
|
// 初始化
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
checkSession()
|
checkSession()
|
||||||
.then((user) => {
|
.then(() => {
|
||||||
isLogin.value = true
|
isLogin.value = true
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
@@ -222,64 +164,82 @@ onMounted(() => {
|
|||||||
getSystemInfo()
|
getSystemInfo()
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
vipInfoText.value = res.data['vip_info_text']
|
vipInfoText.value = res.data['vip_info_text']
|
||||||
|
if (res.data['order_pay_timeout'] > 0) {
|
||||||
|
orderTimeout.value = res.data['order_pay_timeout']
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error('获取系统配置失败:', e.message)
|
console.error('获取系统配置失败:', e.message)
|
||||||
})
|
})
|
||||||
|
|
||||||
// 获取支付方式
|
|
||||||
httpGet('/api/payment/payWays')
|
|
||||||
.then((res) => {
|
|
||||||
payWays.value = res.data
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
showFailToast('获取支付方式失败:' + e.message)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// 支付处理
|
// 支付处理
|
||||||
const pay = (product, payWay) => {
|
const wxPay = (product) => {
|
||||||
if (!isLogin.value) {
|
if (!isLogin.value) {
|
||||||
store.setShowLoginDialog(true)
|
store.setShowLoginDialog(true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selectedPid.value = product.id
|
||||||
currentProduct.value = product
|
currentProduct.value = product
|
||||||
currentPayWay.value = payWay
|
currentPrice.value = Number(product.price)
|
||||||
currentPrice.value = Number(product.discount)
|
title.value = '请打开微信扫码支付'
|
||||||
|
|
||||||
showLoadingToast({
|
showLoadingToast({
|
||||||
message: '正在生成支付订单...',
|
message: '正在生成支付订单...',
|
||||||
forbidClick: true,
|
forbidClick: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
let host = import.meta.env.VITE_API_HOST
|
// 生成支付订单
|
||||||
if (host === '') {
|
GenerateOrder('wxpay')
|
||||||
host = `${location.protocol}//${location.host}`
|
}
|
||||||
|
|
||||||
|
const alipay = (product) => {
|
||||||
|
if (!isLogin.value) {
|
||||||
|
store.setShowLoginDialog(true)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
httpPost(`${import.meta.env.VITE_API_HOST}/api/payment/doPay`, {
|
selectedPid.value = product.id
|
||||||
product_id: product.id,
|
currentProduct.value = product
|
||||||
pay_way: payWay.pay_way,
|
currentPrice.value = Number(product.price)
|
||||||
pay_type: payWay.pay_type,
|
title.value = '请打开支付宝扫码支付'
|
||||||
user_id: 0, // 移除用户ID依赖
|
|
||||||
host: host,
|
showLoadingToast({
|
||||||
device: 'mobile',
|
message: '正在生成支付订单...',
|
||||||
|
forbidClick: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
// 生成支付订单
|
||||||
|
GenerateOrder('alipay')
|
||||||
|
}
|
||||||
|
|
||||||
|
function GenerateOrder(payWay) {
|
||||||
|
// 生成支付订单
|
||||||
|
httpPost('/api/payment/create', {
|
||||||
|
pid: selectedPid.value,
|
||||||
|
pay_way: payWay,
|
||||||
|
domain: `${window.location.protocol}//${window.location.host}`,
|
||||||
|
device: 'pc',
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (payWay.pay_way === 'wechat') {
|
if (res.data.pay_url) {
|
||||||
// 生成二维码
|
// 生成二维码
|
||||||
QRCode.toDataURL(res.data, { width: 200, height: 200, margin: 2 }, (error, url) => {
|
QRCode.toDataURL(res.data.pay_url, { width: 200, height: 200, margin: 2 }, (error, url) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
showFailToast('生成二维码失败')
|
showFailToast('生成二维码失败')
|
||||||
} else {
|
} else {
|
||||||
qrImg.value = url
|
qrImg.value = url
|
||||||
showPayDialog.value = true
|
showPayDialog.value = true
|
||||||
|
// 开始查询订单状态
|
||||||
|
if (handler.value) {
|
||||||
|
clearTimeout(handler.value)
|
||||||
|
}
|
||||||
|
handler.value = setTimeout(() => queryOrder(res.data.order_no), 3000)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// 跳转支付
|
showFailToast('支付链接生成失败')
|
||||||
window.open(res.data, '_blank')
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
@@ -287,25 +247,47 @@ const pay = (product, payWay) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 支付回调
|
// 查询订单状态
|
||||||
const payCallback = (success) => {
|
const queryOrder = async (orderNo) => {
|
||||||
|
try {
|
||||||
|
const res = await httpGet('/api/order/query?order_no=' + orderNo)
|
||||||
|
if (res?.data.status === 2) {
|
||||||
|
paySuccess(true)
|
||||||
|
} else {
|
||||||
|
// 继续查询,但设置最大查询次数
|
||||||
|
const maxQueries = Math.floor(orderTimeout.value / 3) // 每3秒查询一次
|
||||||
|
if (handler.value && maxQueries > 0) {
|
||||||
|
handler.value = setTimeout(() => queryOrder(orderNo), 3000)
|
||||||
|
} else {
|
||||||
|
// 查询超时
|
||||||
|
showFailToast('支付超时,请重新发起支付')
|
||||||
|
showPayDialog.value = false
|
||||||
|
qrImg.value = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('查询订单状态失败:', error)
|
||||||
|
// 继续查询,但设置最大重试次数
|
||||||
|
if (handler.value) {
|
||||||
|
handler.value = setTimeout(() => queryOrder(orderNo), 3000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const paySuccess = () => {
|
||||||
showPayDialog.value = false
|
showPayDialog.value = false
|
||||||
qrImg.value = ''
|
showSuccessToast('支付成功!')
|
||||||
|
clearTimeout(handler.value)
|
||||||
if (success) {
|
userOrderKey.value += 1
|
||||||
showSuccessToast('支付成功!')
|
|
||||||
userOrderKey.value += 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 卡密兑换回调
|
// 组件卸载时清理定时器
|
||||||
const redeemCallback = (success) => {
|
onUnmounted(() => {
|
||||||
showRedeemVerifyDialog.value = false
|
if (handler.value) {
|
||||||
|
clearTimeout(handler.value)
|
||||||
if (success) {
|
handler.value = null
|
||||||
showSuccessToast('卡密兑换成功!')
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@@ -456,14 +438,46 @@ const redeemCallback = (success) => {
|
|||||||
.methods-grid {
|
.methods-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
gap: 8px;
|
gap: 12px;
|
||||||
|
|
||||||
.pay-button {
|
.payment-btn {
|
||||||
height: 36px;
|
height: 44px;
|
||||||
font-size: 12px;
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
margin-right: 4px;
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.wechat-btn {
|
||||||
|
background: #07c160;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #06ad56;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.alipay-btn {
|
||||||
|
background: #15a6e8;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #1395d1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -493,16 +507,42 @@ const redeemCallback = (success) => {
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: var(--van-text-color);
|
color: var(--van-text-color);
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.qr-container {
|
.qr-container {
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
|
padding: 16px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 12px;
|
||||||
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pay-amount {
|
.pay-amount {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #ff6b35;
|
color: #ff6b35;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pay-status {
|
||||||
|
margin-top: 15px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 12px;
|
||||||
|
background: #f0f9ff;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #e0f2fe;
|
||||||
|
|
||||||
|
.success-status {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
color: #07c160;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,6 +550,8 @@ const redeemCallback = (success) => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
padding-top: 16px;
|
||||||
|
border-top: 1px solid #f0f0f0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user