wuyi пре 1 година
родитељ
комит
caa657ad04

+ 1 - 0
package.json

@@ -10,6 +10,7 @@
     "format": "prettier --write src/"
   },
   "dependencies": {
+    "@element-plus/icons-vue": "^2.3.1",
     "@vicons/tabler": "^0.12.0",
     "@vitejs/plugin-vue-jsx": "^4.0.1",
     "@vueuse/core": "^10.11.0",

BIN
src/assets/images/QRCode.png


BIN
src/assets/images/TRC.png


BIN
src/assets/images/USD.png


+ 9 - 1
src/router/index.js

@@ -142,7 +142,15 @@ const router = createRouter({
                     meta: {
                         title: '操作日志'
                     }
-                }
+                },
+                {
+                    path: '/paymentView',
+                    name: 'paymentView',
+                    component: () => import('../views/PaymentView.vue'),
+                    meta: {
+                        title: '充值'
+                    }
+                },
             ]
         }
     ]

+ 4 - 0
src/views/MainView.vue

@@ -162,6 +162,10 @@ if (roles.includes('admin')) {
                 {
                     name: '/statistics',
                     title: '统计'
+                },
+                {
+                    name: '/paymentView',
+                    title: '充值'
                 }
             ]
         }

+ 390 - 0
src/views/PaymentView.vue

@@ -0,0 +1,390 @@
+<template>
+    <div>
+        <el-steps style="max-width: 45%"
+                  :active="active"
+                  finish-status="success"
+        >
+            <el-step title="选择支付方式和充值金额" />
+            <el-step title="支付" />
+            <el-step title="完成" />
+        </el-steps>
+    </div>
+
+    <div>
+        <div style="margin-top: 50px" v-if="isPaymentMethod">
+            <el-form :model="form" :rules="rules" label-width="auto" style="max-width: 600px">
+                <el-form-item prop="chain" label="支付方式:">
+                    <div class="gap-y-4 flex flex-col px-4 py-5 sm:p-6">
+                        <div class="ml-7">
+                            <img src="../assets/images/TRC.png" alt="Tronscan" class="ml-2">
+                            <span>Tronscan</span>
+                        </div>
+                        <div class="ml-7">
+                            <el-radio-group v-model="form.chain">
+                                <el-radio value="TRC20-USDT">TRC20-USDT</el-radio>
+                            </el-radio-group>
+                        </div>
+                    </div>
+                </el-form-item>
+                <el-form-item prop="amount" label="充值金额:">
+                    <el-input v-model="form.amount" placeholder="请输入金额" />
+                </el-form-item>
+            </el-form>
+        </div>
+
+        <div style="margin-top: 50px" v-if="isRechargeAmount">
+            <div class="image-container">
+                <img src="../assets/images/QRCode.png" alt="Receive" class="centered-image">
+            </div>
+
+            <div class="pt-2">
+                <dl>
+                    <div class="space-y-2 py-2 sm:py-4">
+                        <dt>充值金额</dt>
+                        <dd>
+                            <span class="font-mono">
+                                <span class="">$</span><span>{{ orderData.amount }}</span>
+                            </span>
+                        </dd>
+                    </div>
+                    <div class="flex items-center align-center text-center w-full flex-row">
+                        <div class="flex border-gray-200 dark:border-gray-800 w-full border-t border-dotted" />
+                    </div>
+                    <div class="space-y-2 py-2 sm:py-4">
+                        <dt>支付金额</dt>
+                        <dd>
+                            <span class="font-mono">
+                                <span class="">$</span><span class="">{{ orderData.rechargeAmount }}</span>
+                            </span>
+                        </dd>
+                    </div>
+                    <div class="flex items-center align-center text-center w-full flex-row">
+                        <div class="flex border-gray-200 dark:border-gray-800 w-full border-t border-dotted" />
+                    </div>
+                    <div class="space-y-2 py-2 sm:py-4">
+                        <dt>充值地址</dt>
+                        <dd>{{ orderData.address }}</dd>
+                    </div>
+                    <div class="flex items-center align-center text-center w-full flex-row">
+                        <div class="flex border-gray-200 dark:border-gray-800 w-full border-t border-dotted" />
+                    </div>
+                    <div class="space-y-2 py-2 sm:py-4">
+                        <dt>货币</dt>
+                        <dd class="select-all"><span>{{ orderData.chain }}</span></dd>
+                    </div>
+                    <div class="flex items-center align-center text-center w-full flex-row">
+                        <div class="flex border-gray-200 dark:border-gray-800 w-full border-t border-dotted" />
+                    </div>
+                    <div class="space-y-2 py-2 sm:py-4">
+                        <dt>状态</dt>
+                        <dd>
+                            <ElTag v-if="orderData.status === 'pending'" type="warning" size="large">待支付</ElTag>
+                            <ElTag v-else-if="orderData.status === 'completed'" type="success" size="large">已完成</ElTag>
+                            <ElTag v-else-if="orderData.status === 'cancel'" type="danger" size="large">已取消</ElTag>
+                            <ElTag v-else-if="orderData.status === 'error'" type="danger" size="large">待发送</ElTag>
+                        </dd>
+                    </div>
+                    <div class="flex items-center align-center text-center w-full flex-row">
+                        <div class="flex border-gray-200 dark:border-gray-800 w-full border-t border-dotted" />
+                    </div>
+                    <div class="space-y-2 py-2 sm:py-4">
+                        <dt>创建时间</dt>
+                        <dd>{{ timeFormatter(null, null, orderData.createdAt, null) }}</dd>
+                    </div>
+                    <div class="flex items-center align-center text-center w-full flex-row">
+                        <div class="flex border-gray-200 dark:border-gray-800 w-full border-t border-dotted" />
+                    </div>
+                </dl>
+            </div>
+        </div>
+
+        <div style="margin-top: 50px" v-if="isCompleted">
+            <div class="pt-2">
+                <dl>
+                    <div class="space-y-2 py-2 sm:py-4">
+                        <dt>充值金额</dt>
+                        <dd>
+                            <span class="font-mono">
+                                <span class="">$</span><span>{{ orderData.amount }}</span>
+                            </span>
+                        </dd>
+                    </div>
+                    <div class="flex items-center align-center text-center w-full flex-row">
+                        <div class="flex border-gray-200 dark:border-gray-800 w-full border-t border-dotted" />
+                    </div>
+                    <div class="space-y-2 py-2 sm:py-4">
+                        <dt>支付金额</dt>
+                        <dd>
+                            <span class="font-mono">
+                                <span class="">$</span><span class="">{{ orderData.rechargeAmount }}</span>
+                            </span>
+                        </dd>
+                    </div>
+                    <div class="flex items-center align-center text-center w-full flex-row">
+                        <div class="flex border-gray-200 dark:border-gray-800 w-full border-t border-dotted" />
+                    </div>
+                    <div class="space-y-2 py-2 sm:py-4">
+                        <dt>充值地址</dt>
+                        <dd>{{ orderData.address }}</dd>
+                    </div>
+                    <div class="flex items-center align-center text-center w-full flex-row">
+                        <div class="flex border-gray-200 dark:border-gray-800 w-full border-t border-dotted" />
+                    </div>
+                    <div class="space-y-2 py-2 sm:py-4">
+                        <dt>货币</dt>
+                        <dd class="select-all"><span>{{ orderData.chain }}</span></dd>
+                    </div>
+                    <div class="flex items-center align-center text-center w-full flex-row">
+                        <div class="flex border-gray-200 dark:border-gray-800 w-full border-t border-dotted" />
+                    </div>
+                    <div class="space-y-2 py-2 sm:py-4">
+                        <dt>状态</dt>
+                        <dd>
+                            <el-button v-if="orderData.status === 'pending'" type="warning" loading>处理中</el-button>
+                            <ElTag v-else-if="orderData.status === 'completed'" type="success" size="large">已完成</ElTag>
+                            <ElTag v-else-if="orderData.status === 'cancel'" type="danger" size="large">已取消</ElTag>
+                            <ElTag v-else-if="orderData.status === 'error'" type="danger" size="large">待发送</ElTag>
+                        </dd>
+                    </div>
+                    <div class="flex items-center align-center text-center w-full flex-row">
+                        <div class="flex border-gray-200 dark:border-gray-800 w-full border-t border-dotted" />
+                    </div>
+                    <div class="space-y-2 py-2 sm:py-4">
+                        <dt>创建时间</dt>
+                        <dd>{{ timeFormatter(null, null, orderData.createdAt, null) }}</dd>
+                    </div>
+                    <div class="flex items-center align-center text-center w-full flex-row">
+                        <div class="flex border-gray-200 dark:border-gray-800 w-full border-t border-dotted" />
+                    </div>
+                </dl>
+            </div>
+        </div>
+
+        <div style="margin-top: 50px" v-if="completed">
+            <div class="pt-2">
+                <dl>
+                    <div class="space-y-2 py-2 sm:py-4">
+                        <dt>充值金额</dt>
+                        <dd>
+                            <span class="font-mono">
+                                <span class="">$</span><span>{{ orderData.amount }}</span>
+                            </span>
+                        </dd>
+                    </div>
+                    <div class="flex items-center align-center text-center w-full flex-row">
+                        <div class="flex border-gray-200 dark:border-gray-800 w-full border-t border-dotted" />
+                    </div>
+                    <div class="space-y-2 py-2 sm:py-4">
+                        <dt>支付金额</dt>
+                        <dd>
+                            <span class="font-mono">
+                                <span class="">$</span><span class="">{{ orderData.rechargeAmount }}</span>
+                            </span>
+                        </dd>
+                    </div>
+                    <div class="flex items-center align-center text-center w-full flex-row">
+                        <div class="flex border-gray-200 dark:border-gray-800 w-full border-t border-dotted" />
+                    </div>
+                    <div class="space-y-2 py-2 sm:py-4">
+                        <dt>充值地址</dt>
+                        <dd>{{ orderData.address }}</dd>
+                    </div>
+                    <div class="flex items-center align-center text-center w-full flex-row">
+                        <div class="flex border-gray-200 dark:border-gray-800 w-full border-t border-dotted" />
+                    </div>
+                    <div class="space-y-2 py-2 sm:py-4">
+                        <dt>货币</dt>
+                        <dd class="select-all"><span>{{ orderData.chain }}</span></dd>
+                    </div>
+                    <div class="flex items-center align-center text-center w-full flex-row">
+                        <div class="flex border-gray-200 dark:border-gray-800 w-full border-t border-dotted" />
+                    </div>
+                    <div class="space-y-2 py-2 sm:py-4">
+                        <dt>状态</dt>
+                        <dd>
+                            <ElTag v-if="orderData.status === 'pending'" type="warning" size="large">处理中</ElTag>
+                            <ElTag v-else-if="orderData.status === 'completed'" type="success" size="large">已完成
+                            </ElTag>
+                            <ElTag v-else-if="orderData.status === 'cancel'" type="danger" size="large">已取消</ElTag>
+                            <ElTag v-else-if="orderData.status === 'error'" type="danger" size="large">待发送</ElTag>
+                        </dd>
+                    </div>
+                    <div class="flex items-center align-center text-center w-full flex-row">
+                        <div class="flex border-gray-200 dark:border-gray-800 w-full border-t border-dotted" />
+                    </div>
+                    <div class="space-y-2 py-2 sm:py-4">
+                        <dt>创建时间</dt>
+                        <dd>{{ timeFormatter(null, null, orderData.createdAt, null) }}</dd>
+                    </div>
+                    <div class="flex items-center align-center text-center w-full flex-row">
+                        <div class="flex border-gray-200 dark:border-gray-800 w-full border-t border-dotted" />
+                    </div>
+                </dl>
+            </div>
+        </div>
+
+    </div>
+
+    <div style="margin-top: 50px">
+        <el-button @click="previous" v-if="active.valueOf() !== 0">上一步</el-button>
+        <el-button @click="next" v-if="active.valueOf() === 2">下一步</el-button>
+        <el-button @click="createOrder" v-if="active.valueOf() === 0">创建订单</el-button>
+        <el-button @click="next" v-if="active.valueOf() === 1">确认充值</el-button>
+    </div>
+</template>
+
+<script setup>
+import { ref, watch } from 'vue'
+import { http } from '@/plugins/http'
+import { ElMessage } from 'element-plus'
+import { useTimeFormatter } from '@/utils/formatter'
+
+const timeFormatter = useTimeFormatter()
+const rules = {
+    chain: [{ required: true, message: '请选择充值方式', trigger: 'change' }],
+    amount: [
+        { required: true, message: '请输入充值金额', trigger: 'blur' },
+        {
+            validator: (rule, value, callback) => {
+                const regex = /^-?\d+$/
+                if (!regex.test(value)) {
+                    callback(new Error('充值金额请填写整数'))
+                } else {
+                    const amountValue = parseInt(value, 10)
+                    if (amountValue <= 10) {
+                        callback(new Error('充值金额必须大于10'))
+                    } else {
+                        callback()
+                    }
+                }
+            }
+        }
+    ]
+}
+
+const form = ref({
+    chain: 'TRC20-USDT',
+    rechargeAmount: null,
+    amount: null
+})
+
+const orderData = ref({})
+
+const isPaymentMethod = ref(true)
+const isRechargeAmount = ref(false)
+const isCompleted = ref(false)
+const completed = ref(false)
+
+const loading = ref(false)
+
+const active = ref(0)
+
+function next() {
+    ++active.value
+    switch (active.value) {
+        case 1:
+            isPaymentMethod.value = false
+            isRechargeAmount.value = true
+            isCompleted.value = false
+            completed.value = false
+            break
+        case 2:
+            isPaymentMethod.value = false
+            isRechargeAmount.value = false
+            isCompleted.value = true
+            completed.value = false
+            break
+        case 3:
+            isPaymentMethod.value = false
+            isRechargeAmount.value = false
+            isCompleted.value = false
+            completed.value = true
+            break
+        default:
+            isPaymentMethod.value = true
+            isRechargeAmount.value = false
+    }
+
+    if (active.value > 3) active.value = 0
+}
+
+function previous() {
+    if (active.value === 1) {
+        --active.value
+    }
+    switch (active.value) {
+        case 1:
+            isPaymentMethod.value = false
+            isRechargeAmount.value = true
+            break
+        case 2:
+            isPaymentMethod.value = false
+            isRechargeAmount.value = false
+            break
+        default:
+            isPaymentMethod.value = true
+            isRechargeAmount.value = false
+    }
+}
+
+async function createOrder() {
+    try {
+        console.log(form.value)
+        if (form.value.chain === null || form.value.chain === '') {
+            ElMessage.error('请选择充值方式')
+            return
+        } else if (form.value.amount === null || form.value.amount === '') {
+            ElMessage.error('请输入充值金额')
+            return
+        } else if (form.value.amount < 10) {
+            ElMessage.error('充值金额必须大于10')
+            return
+        }
+        orderData.value = await http.put('/payOrder', form.value)
+        next()
+    } catch (e) {
+        ElMessage.error(e.message)
+    }
+}
+
+async function rechargeConfirm() {
+    try {
+        orderData.value = await http.get(`/payOrder/${orderData.value.id}/rechargeConfirm`)
+        if (orderData.value.status === 'completed') {
+            ElMessage.success('充值成功')
+            next()
+        }
+    } catch (e) {
+        console.log(e.message)
+    }
+}
+
+watch(active, (newValue) => {
+    if (newValue === 2) {
+        let count = 0
+        const intervalId = setInterval(() => {
+            count++
+            if (count >= 10 || orderData.value.status !== 'pending') {
+                clearInterval(intervalId)
+            } else {
+                rechargeConfirm()
+            }
+        }, 10000)
+    }
+})
+
+
+</script>
+
+<style scoped>
+.image-container {
+    display: flex;
+    justify-content: center;
+}
+
+.centered-image {
+    width: 300px;
+    height: 300px;
+    object-fit: cover;
+}
+</style>