From 414c1de963c013218dc4b4c44dae54fd853bee96 Mon Sep 17 00:00:00 2001 From: RockYang Date: Fri, 10 Nov 2023 14:39:27 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E5=80=92=E8=AE=A1=E6=97=B6=E7=BB=84=E4=BB=B6=EF=BC=8C=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E6=B8=85=E7=90=86=E8=BF=87=E6=9C=9F=E6=9C=AA=E6=94=AF?= =?UTF-8?q?=E4=BB=98=E8=AE=A2=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/core/types/config.go | 15 ++--- api/service/xxl_job_service.go | 28 +++++++-- web/src/components/CountDown.vue | 97 +++++++++++++++++++++++++++++++ web/src/views/Member.vue | 41 +++++++++++-- web/src/views/admin/SysConfig.vue | 17 ++++++ 5 files changed, 180 insertions(+), 18 deletions(-) create mode 100644 web/src/components/CountDown.vue diff --git a/api/core/types/config.go b/api/core/types/config.go index fdf6b9a0..54add0d1 100644 --- a/api/core/types/config.go +++ b/api/core/types/config.go @@ -139,11 +139,12 @@ type SystemConfig struct { InitImgCalls int `json:"init_img_calls"` VipMonthCalls int `json:"vip_month_calls"` // 会员每个赠送的调用次数 EnabledRegister bool `json:"enabled_register"` - EnabledMsg bool `json:"enabled_msg"` // 启用短信验证码服务 - EnabledDraw bool `json:"enabled_draw"` // 启动 AI 绘画功能 - RewardImg string `json:"reward_img"` // 众筹收款二维码地址 - EnabledFunction bool `json:"enabled_function"` // 启用 API 函数功能 - EnabledReward bool `json:"enabled_reward"` // 启用众筹功能 - EnabledAlipay bool `json:"enabled_alipay"` // 是否启用支付宝支付通道 - DefaultModels []string `json:"default_models"` // 默认开通的 AI 模型 + EnabledMsg bool `json:"enabled_msg"` // 启用短信验证码服务 + EnabledDraw bool `json:"enabled_draw"` // 启动 AI 绘画功能 + RewardImg string `json:"reward_img"` // 众筹收款二维码地址 + EnabledFunction bool `json:"enabled_function"` // 启用 API 函数功能 + EnabledReward bool `json:"enabled_reward"` // 启用众筹功能 + EnabledAlipay bool `json:"enabled_alipay"` // 是否启用支付宝支付通道 + OrderPayTimeout int `json:"order_pay_timeout"` //订单支付超时时间 + DefaultModels []string `json:"default_models"` // 默认开通的 AI 模型 } diff --git a/api/service/xxl_job_service.go b/api/service/xxl_job_service.go index 1822429b..f112ae40 100644 --- a/api/service/xxl_job_service.go +++ b/api/service/xxl_job_service.go @@ -40,9 +40,25 @@ func (e *XXLJobExecutor) Run() error { // ClearOrder 清理未支付的订单,如果没有抛出异常则表示执行成功 func (e *XXLJobExecutor) ClearOrder(cxt context.Context, param *xxl.RunReq) (msg string) { - timeout := time.Now().Unix() - 600 + logger.Debug("执行清理未支付订单...") + var sysConfig model.Config + res := e.db.Where("marker", "system").First(&sysConfig) + if res.Error != nil { + return "error with get system config: " + res.Error.Error() + } + + var config types.SystemConfig + err := utils.JsonDecode(sysConfig.Config, &config) + if err != nil { + return "error with decode system config: " + err.Error() + } + + if config.OrderPayTimeout == 0 { // 默认未支付订单的生命周期为 30 分钟 + config.OrderPayTimeout = 1800 + } + timeout := time.Now().Unix() - int64(config.OrderPayTimeout) start := utils.Stamp2str(timeout) - res := e.db.Where("status != ? AND created_at < ?", types.OrderPaidSuccess, start).Delete(&model.Order{}) + res = e.db.Where("status != ? AND created_at < ?", types.OrderPaidSuccess, start).Delete(&model.Order{}) return fmt.Sprintf("Clear order successfully, affect rows: %d", res.RowsAffected) } @@ -58,13 +74,13 @@ func (e *XXLJobExecutor) ResetVipCalls(cxt context.Context, param *xxl.RunReq) ( var sysConfig model.Config res = e.db.Where("marker", "system").First(&sysConfig) if res.Error != nil { - panic(res.Error) + return "error with get system config: " + res.Error.Error() } var config types.SystemConfig err := utils.JsonDecode(sysConfig.Config, &config) if err != nil { - panic(err) + return "error with decode system config: " + err.Error() } // 获取本月月初时间 @@ -115,9 +131,9 @@ func (e *XXLJobExecutor) ResetVipCalls(cxt context.Context, param *xxl.RunReq) ( type customLogger struct{} func (l *customLogger) Info(format string, a ...interface{}) { - logger.Debug(format, a) + logger.Debugf(format, a...) } func (l *customLogger) Error(format string, a ...interface{}) { - logger.Error(format, a) + logger.Errorf(format, a...) } diff --git a/web/src/components/CountDown.vue b/web/src/components/CountDown.vue new file mode 100644 index 00000000..f21a31b4 --- /dev/null +++ b/web/src/components/CountDown.vue @@ -0,0 +1,97 @@ + + + + \ No newline at end of file diff --git a/web/src/views/Member.vue b/web/src/views/Member.vue index b67ea5bc..33a07740 100644 --- a/web/src/views/Member.vue +++ b/web/src/views/Member.vue @@ -100,7 +100,11 @@ :width="400" title="充值订单支付">
-
+
+ +
+ +
@@ -135,6 +139,7 @@ import BindMobile from "@/components/BindMobile.vue"; import RewardVerify from "@/components/RewardVerify.vue"; import {useRouter} from "vue-router"; import {removeUserToken} from "@/store/session"; +import CountDown from "@/components/CountDown.vue"; const listBoxHeight = window.innerHeight - 97 const list = ref([]) @@ -153,6 +158,11 @@ const text = ref("") const user = ref(null) const isLogin = ref(false) const router = useRouter() +const curPayProduct = ref(null) +const activeOrderNo = ref("") +const countDown = ref(null) +const orderTimeout = ref(1800) +const loading = ref(true) onMounted(() => { @@ -171,6 +181,9 @@ onMounted(() => { httpGet("/api/admin/config/get?key=system").then(res => { rewardImg.value = res.data['reward_img'] enableReward.value = res.data['enabled_reward'] + if (res.data['order_pay_timeout'] > 0) { + orderTimeout.value = res.data['order_pay_timeout'] + } }).catch(e => { ElMessage.error("获取系统配置失败:" + e.message) }) @@ -181,10 +194,20 @@ const orderPay = (row) => { showLoginDialog.value = true return } - httpPost("/api/payment/alipay/qrcode", {product_id: row.id, user_id: user.value.id}).then(res => { + if (row) { + curPayProduct.value = row + } + loading.value = true + httpPost("/api/payment/alipay/qrcode", {product_id: curPayProduct.value.id, user_id: user.value.id}).then(res => { showPayDialog.value = true qrcode.value = res.data['image'] - queryOrder(res.data['order_no']) + activeOrderNo.value = res.data['order_no'] + queryOrder(activeOrderNo.value) + loading.value = false + // 重置计数器 + if (countDown.value) { + countDown.value.resetTimer() + } }).catch(e => { ElMessage.error("生成支付订单失败:" + e.message) }) @@ -199,7 +222,10 @@ const queryOrder = (orderNo) => { text.value = "支付成功,正在刷新页面" setTimeout(() => location.reload(), 500) } else { - queryOrder(orderNo) + // 如果当前订单没有过期,继续等待订单的下一个状态 + if (activeOrderNo.value === orderNo) { + queryOrder(orderNo) + } } }).catch(e => { ElMessage.error("查询支付状态失败:" + e.message) @@ -225,9 +251,14 @@ const logout = function () { .el-dialog { .el-dialog__body { - padding-top 0 + padding-top 10px .pay-container { + .count-down { + display flex + justify-content center + } + .pay-qrcode { display flex justify-content center diff --git a/web/src/views/admin/SysConfig.vue b/web/src/views/admin/SysConfig.vue index 3a612692..b9e7e776 100644 --- a/web/src/views/admin/SysConfig.vue +++ b/web/src/views/admin/SysConfig.vue @@ -103,6 +103,23 @@ + +
+ +
+ + + + + +
+
+