|
|
@@ -1,534 +1,23 @@
|
|
|
<template>
|
|
|
- <view class="pay-container">
|
|
|
- <!-- 顶部导航栏 -->
|
|
|
- <view class="nav-bar">
|
|
|
- <view class="nav-title">扫码付款</view>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 支付金额区域 -->
|
|
|
- <view class="amount-section">
|
|
|
- <view class="amount-label">支付金额</view>
|
|
|
- <view class="amount-display">
|
|
|
- <text class="currency">¥</text>
|
|
|
- <text class="amount">{{ displayAmount }}</text>
|
|
|
- </view>
|
|
|
- <view class="amount-tip">请输入支付金额</view>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 支付方式展示 -->
|
|
|
- <view class="payment-methods">
|
|
|
- <view class="method-list">
|
|
|
- <view class="method-item active">
|
|
|
- <view class="method-icon alipay">
|
|
|
- <text class="iconfont icon-zhifubao"></text>
|
|
|
- </view>
|
|
|
- <view class="method-info">
|
|
|
- <text class="method-name">支付宝</text>
|
|
|
- <text class="method-desc">安全便捷的支付方式</text>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 数字键盘 -->
|
|
|
- <view class="keyboard-section">
|
|
|
- <view class="keyboard">
|
|
|
- <view class="keyboard-row" v-for="(row, rowIndex) in keyboardKeys" :key="rowIndex">
|
|
|
- <view
|
|
|
- class="key-item"
|
|
|
- v-for="(key, keyIndex) in row"
|
|
|
- :key="keyIndex"
|
|
|
- :class="{
|
|
|
- 'key-number': key.type === 'number',
|
|
|
- 'key-delete': key.type === 'delete',
|
|
|
- 'key-dot': key.type === 'dot',
|
|
|
- 'key-confirm': key.type === 'confirm'
|
|
|
- }"
|
|
|
- @click="handleKeyPress(key)"
|
|
|
- >
|
|
|
- <text v-if="key.type === 'delete'" class="iconfont icon-delete"></text>
|
|
|
- <text v-else-if="key.type === 'confirm'">确认</text>
|
|
|
- <text v-else>{{ key.value }}</text>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 支付按钮 -->
|
|
|
- <view class="pay-button-section">
|
|
|
- <button
|
|
|
- class="pay-button"
|
|
|
- :class="{ disabled: !canPay }"
|
|
|
- :disabled="!canPay"
|
|
|
- @click="handlePay"
|
|
|
- >
|
|
|
- 立即支付
|
|
|
- </button>
|
|
|
- </view>
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+ <view>
|
|
|
+ 您好
|
|
|
</view>
|
|
|
</template>
|
|
|
-
|
|
|
<script>
|
|
|
-import { createPaymentOrder, requestPayment } from '@/api/payment';
|
|
|
-
|
|
|
export default {
|
|
|
- name: 'PayPage',
|
|
|
+ name: 'index',
|
|
|
data() {
|
|
|
return {
|
|
|
- currentAmount: '0.00',
|
|
|
- displayAmount: '0.00',
|
|
|
- keyboardKeys: [
|
|
|
- [
|
|
|
- { type: 'number', value: '1' },
|
|
|
- { type: 'number', value: '2' },
|
|
|
- { type: 'number', value: '3' }
|
|
|
- ],
|
|
|
- [
|
|
|
- { type: 'number', value: '4' },
|
|
|
- { type: 'number', value: '5' },
|
|
|
- { type: 'number', value: '6' }
|
|
|
- ],
|
|
|
- [
|
|
|
- { type: 'number', value: '7' },
|
|
|
- { type: 'number', value: '8' },
|
|
|
- { type: 'number', value: '9' }
|
|
|
- ],
|
|
|
- [
|
|
|
- { type: 'dot', value: '.' },
|
|
|
- { type: 'number', value: '0' },
|
|
|
- { type: 'delete', value: '' }
|
|
|
- ]
|
|
|
- ],
|
|
|
- hasDecimal: false,
|
|
|
- decimalPlaces: 0
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
- canPay() {
|
|
|
- const amount = parseFloat(this.currentAmount);
|
|
|
- return amount > 0 && amount <= 99999999.99;
|
|
|
- }
|
|
|
+
|
|
|
},
|
|
|
onLoad(options) {
|
|
|
- // 从扫码页面传递过来的金额
|
|
|
- if (options.amount) {
|
|
|
- this.setAmount(options.amount);
|
|
|
- }
|
|
|
- // 从扫码页面传递过来的订单信息
|
|
|
- if (options.orderId) {
|
|
|
- this.orderId = options.orderId;
|
|
|
- }
|
|
|
},
|
|
|
methods: {
|
|
|
- // 处理键盘按键
|
|
|
- handleKeyPress(key) {
|
|
|
- if (key.type === 'number') {
|
|
|
- this.addNumber(key.value);
|
|
|
- } else if (key.type === 'delete') {
|
|
|
- this.deleteNumber();
|
|
|
- } else if (key.type === 'dot') {
|
|
|
- this.addDecimal();
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- // 添加数字
|
|
|
- addNumber(num) {
|
|
|
- if (this.currentAmount === '0.00') {
|
|
|
- this.currentAmount = num;
|
|
|
- this.displayAmount = num;
|
|
|
- } else {
|
|
|
- if (this.hasDecimal) {
|
|
|
- if (this.decimalPlaces < 2) {
|
|
|
- this.currentAmount += num;
|
|
|
- this.decimalPlaces++;
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (this.currentAmount.length < 8) {
|
|
|
- this.currentAmount += num;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- this.updateDisplay();
|
|
|
- },
|
|
|
-
|
|
|
- // 添加小数点
|
|
|
- addDecimal() {
|
|
|
- if (!this.hasDecimal) {
|
|
|
- this.hasDecimal = true;
|
|
|
- this.currentAmount += '.';
|
|
|
- this.updateDisplay();
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- // 删除数字
|
|
|
- deleteNumber() {
|
|
|
- if (this.currentAmount.length > 1) {
|
|
|
- // 如果当前字符是小数点,删除小数点并重置状态
|
|
|
- if (this.currentAmount.endsWith('.')) {
|
|
|
- this.hasDecimal = false;
|
|
|
- this.currentAmount = this.currentAmount.slice(0, -1);
|
|
|
- } else {
|
|
|
- // 删除普通数字
|
|
|
- if (this.hasDecimal && this.currentAmount.split('.')[1]) {
|
|
|
- this.decimalPlaces--;
|
|
|
- }
|
|
|
- this.currentAmount = this.currentAmount.slice(0, -1);
|
|
|
- }
|
|
|
- } else {
|
|
|
- this.currentAmount = '0';
|
|
|
- this.hasDecimal = false;
|
|
|
- this.decimalPlaces = 0;
|
|
|
- }
|
|
|
- this.updateDisplay();
|
|
|
- },
|
|
|
-
|
|
|
- // 更新显示金额
|
|
|
- updateDisplay() {
|
|
|
- let amount = parseFloat(this.currentAmount) || 0;
|
|
|
- this.displayAmount = amount.toFixed(2);
|
|
|
- },
|
|
|
-
|
|
|
- // 设置金额
|
|
|
- setAmount(amount) {
|
|
|
- const numAmount = parseFloat(amount);
|
|
|
- if (!isNaN(numAmount) && numAmount > 0) {
|
|
|
- this.currentAmount = numAmount.toString();
|
|
|
- this.hasDecimal = this.currentAmount.includes('.');
|
|
|
- if (this.hasDecimal) {
|
|
|
- this.decimalPlaces = this.currentAmount.split('.')[1].length;
|
|
|
- }
|
|
|
- this.updateDisplay();
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- // 处理支付
|
|
|
- async handlePay() {
|
|
|
- if (!this.canPay) return;
|
|
|
-
|
|
|
- const amount = parseFloat(this.currentAmount);
|
|
|
-
|
|
|
- try {
|
|
|
- uni.showLoading({
|
|
|
- title: '支付中...'
|
|
|
- });
|
|
|
-
|
|
|
- // 模拟支付请求
|
|
|
- const result = await this.requestPayment(amount);
|
|
|
-
|
|
|
- uni.hideLoading();
|
|
|
-
|
|
|
- if (result.success) {
|
|
|
- // 支付成功,跳转到成功页面
|
|
|
- uni.navigateTo({
|
|
|
- url: `/admin/ghs/success?amount=${this.displayAmount}&orderId=${this.orderId || this.generateOrderId()}`
|
|
|
- });
|
|
|
- } else {
|
|
|
- // 支付失败,显示弹框
|
|
|
- this.paymentResult = {
|
|
|
- success: false,
|
|
|
- amount: this.displayAmount,
|
|
|
- message: result.message
|
|
|
- };
|
|
|
- this.showPaymentModal = true;
|
|
|
- }
|
|
|
-
|
|
|
- } catch (error) {
|
|
|
- uni.hideLoading();
|
|
|
- uni.showToast({
|
|
|
- title: '支付失败',
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- // 请求支付
|
|
|
- async requestPayment(amount) {
|
|
|
- try {
|
|
|
- // 创建支付订单
|
|
|
- const orderResult = await createPaymentOrder({
|
|
|
- amount: amount,
|
|
|
- paymentMethod: 'alipay',
|
|
|
- orderId: this.orderId || this.generateOrderId(),
|
|
|
- description: '扫码支付'
|
|
|
- });
|
|
|
-
|
|
|
- if (!orderResult.success) {
|
|
|
- throw new Error(orderResult.message);
|
|
|
- }
|
|
|
-
|
|
|
- // 发起支付
|
|
|
- const paymentResult = await requestPayment({
|
|
|
- orderId: orderResult.data.orderId,
|
|
|
- paymentMethod: 'alipay'
|
|
|
- });
|
|
|
-
|
|
|
- return paymentResult;
|
|
|
- } catch (error) {
|
|
|
- console.error('支付请求失败:', error);
|
|
|
- return {
|
|
|
- success: false,
|
|
|
- message: error.message || '支付失败,请重试'
|
|
|
- };
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- // 生成订单ID
|
|
|
- generateOrderId() {
|
|
|
- const timestamp = Date.now();
|
|
|
- const random = Math.floor(Math.random() * 10000);
|
|
|
- return `ORDER${timestamp}${random}`;
|
|
|
- },
|
|
|
-
|
|
|
-
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
-
|
|
|
<style lang="scss" scoped>
|
|
|
-.pay-container {
|
|
|
- min-height: 100vh;
|
|
|
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
- position: relative;
|
|
|
-}
|
|
|
-
|
|
|
-.nav-bar {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- padding: 20rpx 30rpx;
|
|
|
- background: rgba(255, 255, 255, 0.1);
|
|
|
- backdrop-filter: blur(10px);
|
|
|
-
|
|
|
- .nav-title {
|
|
|
- color: #fff;
|
|
|
- font-size: 36rpx;
|
|
|
- font-weight: 600;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-.amount-section {
|
|
|
- padding: 60rpx 40rpx;
|
|
|
- text-align: center;
|
|
|
-
|
|
|
- .amount-label {
|
|
|
- color: rgba(255, 255, 255, 0.8);
|
|
|
- font-size: 28rpx;
|
|
|
- margin-bottom: 20rpx;
|
|
|
- }
|
|
|
-
|
|
|
- .amount-display {
|
|
|
- display: flex;
|
|
|
- align-items: baseline;
|
|
|
- justify-content: center;
|
|
|
- margin-bottom: 20rpx;
|
|
|
-
|
|
|
- .currency {
|
|
|
- color: #fff;
|
|
|
- font-size: 48rpx;
|
|
|
- font-weight: 600;
|
|
|
- margin-right: 10rpx;
|
|
|
- }
|
|
|
-
|
|
|
- .amount {
|
|
|
- color: #fff;
|
|
|
- font-size: 80rpx;
|
|
|
- font-weight: 700;
|
|
|
- font-family: 'Arial', sans-serif;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .amount-tip {
|
|
|
- color: rgba(255, 255, 255, 0.6);
|
|
|
- font-size: 24rpx;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-.payment-methods {
|
|
|
- background: rgba(255, 255, 255, 0.95);
|
|
|
- margin: 0 30rpx 20rpx;
|
|
|
- border-radius: 15rpx;
|
|
|
- padding: 20rpx 30rpx;
|
|
|
-
|
|
|
- .method-list {
|
|
|
- .method-item {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- padding: 20rpx 0;
|
|
|
- transition: all 0.3s ease;
|
|
|
-
|
|
|
- &.active {
|
|
|
- background: rgba(102, 126, 234, 0.1);
|
|
|
- border-radius: 12rpx;
|
|
|
- padding: 20rpx 15rpx;
|
|
|
- margin: 0 -15rpx;
|
|
|
- }
|
|
|
-
|
|
|
- .method-icon {
|
|
|
- width: 60rpx;
|
|
|
- height: 60rpx;
|
|
|
- border-radius: 12rpx;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- margin-right: 20rpx;
|
|
|
-
|
|
|
- &.alipay {
|
|
|
- background: linear-gradient(135deg, #1677ff 0%, #4096ff 100%);
|
|
|
- }
|
|
|
-
|
|
|
- .iconfont {
|
|
|
- color: #fff;
|
|
|
- font-size: 32rpx;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .method-info {
|
|
|
- flex: 1;
|
|
|
-
|
|
|
- .method-name {
|
|
|
- display: block;
|
|
|
- font-size: 28rpx;
|
|
|
- font-weight: 600;
|
|
|
- color: #333;
|
|
|
- margin-bottom: 4rpx;
|
|
|
- }
|
|
|
-
|
|
|
- .method-desc {
|
|
|
- display: block;
|
|
|
- font-size: 22rpx;
|
|
|
- color: #999;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .method-check {
|
|
|
- width: 50rpx;
|
|
|
- height: 50rpx;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
-
|
|
|
- .iconfont {
|
|
|
- color: #1677ff;
|
|
|
- font-size: 32rpx;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-.keyboard-section {
|
|
|
- position: fixed;
|
|
|
- bottom: 160rpx;
|
|
|
- left: 0;
|
|
|
- right: 0;
|
|
|
- background: rgba(255, 255, 255, 0.95);
|
|
|
- backdrop-filter: blur(10px);
|
|
|
- padding: 30rpx;
|
|
|
-
|
|
|
- .keyboard {
|
|
|
- .keyboard-row {
|
|
|
- display: flex;
|
|
|
- margin-bottom: 20rpx;
|
|
|
-
|
|
|
- &:last-child {
|
|
|
- margin-bottom: 0;
|
|
|
- }
|
|
|
-
|
|
|
- .key-item {
|
|
|
- flex: 1;
|
|
|
- height: 120rpx;
|
|
|
- margin: 0 10rpx;
|
|
|
- border-radius: 20rpx;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- font-size: 40rpx;
|
|
|
- font-weight: 600;
|
|
|
- transition: all 0.2s ease;
|
|
|
-
|
|
|
- &.key-number {
|
|
|
- background: #fff;
|
|
|
- color: #333;
|
|
|
- box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
|
|
|
-
|
|
|
- &:active {
|
|
|
- background: #f0f0f0;
|
|
|
- transform: scale(0.95);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- &.key-delete {
|
|
|
- background: #ff6b6b;
|
|
|
- color: #fff;
|
|
|
-
|
|
|
- &:active {
|
|
|
- background: #ff5252;
|
|
|
- transform: scale(0.95);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- &.key-dot {
|
|
|
- background: #fff;
|
|
|
- color: #333;
|
|
|
- box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
|
|
|
-
|
|
|
- &:active {
|
|
|
- background: #f0f0f0;
|
|
|
- transform: scale(0.95);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- &.key-confirm {
|
|
|
- background: #667eea;
|
|
|
- color: #fff;
|
|
|
-
|
|
|
- &:active {
|
|
|
- background: #5a6fd8;
|
|
|
- transform: scale(0.95);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-.pay-button-section {
|
|
|
- position: fixed;
|
|
|
- bottom: 0;
|
|
|
- left: 0;
|
|
|
- right: 0;
|
|
|
- padding: 30rpx;
|
|
|
- background: rgba(255, 255, 255, 0.95);
|
|
|
- backdrop-filter: blur(10px);
|
|
|
-
|
|
|
- .pay-button {
|
|
|
- width: 100%;
|
|
|
- height: 100rpx;
|
|
|
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
- color: #fff;
|
|
|
- font-size: 36rpx;
|
|
|
- font-weight: 600;
|
|
|
- border-radius: 50rpx;
|
|
|
- border: none;
|
|
|
- transition: all 0.3s ease;
|
|
|
-
|
|
|
- &.disabled {
|
|
|
- background: #ccc;
|
|
|
- color: #999;
|
|
|
- }
|
|
|
-
|
|
|
- &:not(.disabled):active {
|
|
|
- transform: scale(0.98);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-</style>
|
|
|
+</style>
|