Commit cb9ca950 by renyizhao

充值功能完成

parent 73636f4a
...@@ -42,4 +42,22 @@ export function getToken() { ...@@ -42,4 +42,22 @@ export function getToken() {
url: '/app/ai-token/get', url: '/app/ai-token/get',
method: 'post', method: 'post',
}) })
} }
\ No newline at end of file
// 创建充值记录
export function createRecharge(amount) {
return request({
url: '/app/recharge/create',
method: 'post',
data: { amount }
})
}
// 查询充值记录状态
export function getRecharge(id) {
return request({
url: '/app/recharge/get',
method: 'get',
params: { id }
})
}
...@@ -16,24 +16,37 @@ ...@@ -16,24 +16,37 @@
</el-form> </el-form>
<el-form :model="rechargeForm" label-width="100px" label-position="left"> <el-form :model="rechargeForm" label-width="100px" label-position="left">
<el-form-item label="充值金额:"> <el-form-item label="充值金额:">
<el-input-number v-model="rechargeForm.amount" :min="1" :precision="2" /> <el-input-number v-model="rechargeForm.amount" :min="0" :precision="2" />
<el-button type="primary" @click="handleRecharge" class="ml20">充值</el-button> <el-button type="primary" @click="handleRecharge" :loading="rechargeLoading" class="ml20">充值</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-dialog v-model="rechargeDialogVisible" title="扫码充值" width="300px">
<div class="text-center">
<p>充值金额:{{ rechargeForm.amount }}</p>
<div style="width: 200px; height: 200px; margin: 0 auto; background: #f5f5f5; display: flex; align-items: center; justify-content: center;">
二维码占位
</div>
</div>
</el-dialog>
</div> </div>
<!-- 支付二维码弹窗 -->
<el-dialog
:title="qrCode.title"
v-model="qrCode.visible"
width="385px"
append-to-body
:align-center="true"
:close-on-click-modal="false"
@closed="clearQueryInterval"
>
<div class="text-center">
<p>充值金额:¥{{ rechargeForm.amount }}</p>
<p style="color: #999; font-size: 12px;">请使用微信或支付宝扫码支付</p>
<div v-if="qrCode.url" style="width: 200px; height: 200px; margin: 10px auto;">
<img :src="qrCode.url" style="width: 100%; height: 100%;" />
</div>
</div>
</el-dialog>
</div> </div>
</template> </template>
<script setup> <script setup>
import { getTokenInfo, getToken } from "@/api/console"; import { getTokenInfo, getToken, createRecharge, getRecharge } from "@/api/console";
import { ElMessage, ElMessageBox } from "element-plus";
import QRCode from "qrcode";
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
...@@ -42,11 +55,21 @@ const hasToken = ref(false); ...@@ -42,11 +55,21 @@ const hasToken = ref(false);
const balance = ref("0.00"); const balance = ref("0.00");
const apiKey = ref(""); const apiKey = ref("");
const maskedKey = ref(""); const maskedKey = ref("");
const rechargeLoading = ref(false);
// 轮询相关
const queryInterval = ref(undefined);
const currentRechargeId = ref(undefined);
const rechargeForm = reactive({ const rechargeForm = reactive({
amount: 10 amount: 0
});
const qrCode = ref({
url: '',
title: '请使用微信或支付宝扫码支付',
visible: false
}); });
const rechargeDialogVisible = ref(false);
function maskKey(key) { function maskKey(key) {
if (!key || key.length < 12) return key; if (!key || key.length < 12) return key;
...@@ -59,7 +82,10 @@ function loadTokenInfo() { ...@@ -59,7 +82,10 @@ function loadTokenInfo() {
hasToken.value = true; hasToken.value = true;
apiKey.value = response.apiKey; apiKey.value = response.apiKey;
maskedKey.value = maskKey(response.apiKey); maskedKey.value = maskKey(response.apiKey);
balance.value = "100.00"; // 显示真实 New API 余额
if (response.balance) {
balance.value = response.balance;
}
} }
}).catch(() => { }).catch(() => {
// 忽略错误,保持当前状态 // 忽略错误,保持当前状态
...@@ -85,12 +111,107 @@ function handleGetToken() { ...@@ -85,12 +111,107 @@ function handleGetToken() {
} }
function handleRecharge() { function handleRecharge() {
rechargeDialogVisible.value = true; if (rechargeForm.amount <= 0) {
proxy.$modal.msgError("请输入正确的充值金额");
return;
}
rechargeLoading.value = true;
qrCode.value.url = "";
createRecharge(rechargeForm.amount).then(response => {
if (response && response.data && response.data.id) {
// 保存当前充值ID用于轮询
currentRechargeId.value = response.data.id;
// 生成二维码
if (response.data.qrCodeUrl) {
QRCode.toDataURL(response.data.qrCodeUrl, { errorCorrectionLevel: 'L', margin: 2, width: 200 }, (err, url) => {
if (err) {
proxy.$modal.msgError("生成二维码失败");
rechargeLoading.value = false;
return;
}
qrCode.value.url = url;
qrCode.value.visible = true;
// 开始轮询
createQueryInterval(currentRechargeId.value);
});
} else {
proxy.$modal.msgError("获取支付链接失败");
}
proxy.$modal.msgSuccess("充值订单已创建");
} else {
proxy.$modal.msgError("创建充值订单失败");
}
rechargeLoading.value = false;
}).catch(error => {
rechargeLoading.value = false;
proxy.$modal.msgError("充值失败: " + (error.message || "未知错误"));
});
} }
// 轮询查询充值状态
const createQueryInterval = (rechargeId) => {
if (queryInterval.value) {
return;
}
queryInterval.value = setInterval(async () => {
try {
const res = await getRecharge(rechargeId);
console.log('充值轮询结果:', res);
// 已支付
if (res.data && res.data.payStatus === 1) {
clearQueryInterval();
ElMessageBox.confirm(
'支付成功',
'提示',
{
confirmButtonText: '确认',
showCancelButton: false,
type: 'success'
}
).then(() => {
qrCode.value.visible = false;
});
}
// 支付失败
if (res.data && res.data.payStatus === -1) {
clearQueryInterval();
ElMessage.error('支付失败!');
qrCode.value.visible = false;
}
} catch (e) {
// 静默捕获轮询异常
}
}, 1000 * 2); // 每2秒轮询一次
};
// 清除轮询和弹窗
const clearQueryInterval = () => {
qrCode.value.visible = false;
qrCode.value.url = '';
qrCode.value.title = '请使用微信或支付宝扫码支付';
// 清除轮询任务
if (queryInterval.value) {
clearInterval(queryInterval.value);
queryInterval.value = undefined;
}
currentRechargeId.value = undefined;
};
onMounted(() => { onMounted(() => {
loadTokenInfo(); loadTokenInfo();
}); });
onUnmounted(() => {
// 组件销毁时清除轮询
try {
clearQueryInterval();
} catch (e) {}
});
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
...@@ -99,4 +220,4 @@ onMounted(() => { ...@@ -99,4 +220,4 @@ onMounted(() => {
font-size: 12px; font-size: 12px;
cursor: pointer; cursor: pointer;
} }
</style> </style>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment