Просмотр исходного кода

```
feat(app): 添加支付成功提示弹窗和登录对话框功能

- 新增支付成功确认弹窗功能,替换原有的消息提示
- 添加全局登录对话框显示控制机制
- 修改API响应拦截器,当认证失败时显示登录弹窗而非跳转页面
- 在多语言文件中添加支付成功相关文案
- 更新订单确认页面的支付流程处理逻辑
- 修复PayPal支付集成中的数据传递问题
```

zhangningning 1 месяц назад
Родитель
Сommit
942c20149b

+ 1 - 1
.env.development

@@ -1,6 +1,6 @@
 # 乔功
 VITE_API_BASE_URL=http://192.168.100.134:8080/api
 # 高运甲
-VITE_API_BASE_URL=http://192.168.100.89:8080/api
+# VITE_API_BASE_URL=http://192.168.100.89:8080/api
 
 

+ 9 - 2
src/App.vue

@@ -58,7 +58,7 @@
 <script setup>
 import { logout } from '@/api/auth.js'
 import LoginDialog from './components/LoginDialog.vue'
-import { computed,ref,onMounted, provide } from 'vue'
+import { computed,ref,onMounted, provide, watch } from 'vue'
 import LangSwitch from './components/LangSwitch.vue'
 import { ElConfigProvider, ElMessage } from 'element-plus'
 import { useRoute, useRouter } from 'vue-router'
@@ -79,8 +79,15 @@ const router = useRouter()
 // 登录弹框引用
 const loginDialogRef = ref(null)
 
+//监听showLoginDialog变化
+watch(() => appStore.showLoginDialog, (newVal, oldVal) => {
+  if(newVal){
+    openLoginDialog();
+  }
+})
+
 onMounted(() => {
-  appStore.USERINFO()
+  appStore.USERINFO();
 })
 
 // 打开登录弹框

+ 6 - 2
src/api/request.js

@@ -1,6 +1,7 @@
 import axios from 'axios'
 import { ElMessage } from 'element-plus'
 import { useLangStore } from '@/pinia/langStore'
+import { useAppStore } from '@/pinia/appStore'
 // 创建 axios 实例
 const request = axios.create({
   baseURL: import.meta.env.VITE_API_BASE_URL,
@@ -50,6 +51,7 @@ request.interceptors.request.use(
 // 响应拦截器
 request.interceptors.response.use(
   response => {
+    const appStore = useAppStore();
     // 根据后端约定的响应结构进行状态判断
     const { code, data, msg } = response.data
     
@@ -57,8 +59,11 @@ request.interceptors.response.use(
     if (code === 200) {
       return response.data
     } else if ([410000, 410001, 410002, 401, 403].includes(code)){
+      appStore.LOGOUT();
       localStorage.removeItem('token')
-      window.location.href = '/login'
+      //弹出登录框
+      appStore.showLoginDialog = true;
+      // window.location.href = '/login'
       
       return response.data
     }else {
@@ -76,7 +81,6 @@ request.interceptors.response.use(
         case 401:
           // 未授权
           localStorage.removeItem('token')
-          window.location.href = '/login'
           break
         case 403:
           // 禁止访问

+ 1 - 0
src/locales/en.js

@@ -104,6 +104,7 @@ export default {
     exchange:"Exchange",
     placeholderInput:"Please input",
     modify:"Modify",
+    paySuccess:"Pay Success",
   },
   login: {
     smsLogin: 'Captcha Login',

+ 1 - 0
src/locales/zh-CN.js

@@ -109,6 +109,7 @@ export default {
     placeholderInput:"请输入",
     addTags:'添加标签',
     modify:"修改",
+    paySuccess:"支付成功",
   },
   login: {
     smsLogin: '验证码登录',

+ 2 - 0
src/pages/Home.vue

@@ -167,6 +167,8 @@ const getList = async (type) => {
   const res = await getPublishList({
     pageNum: 1,
     pageSize: 8,
+    orderByColumn: 'publishId',
+    isAsc: 'desc'
   })
   if(res.code === 200){
     list.value = res.rows || [];

+ 2 - 1
src/pages/LearningSystem/LearningSystemDetail.vue

@@ -48,7 +48,7 @@
             </el-tab-pane>
             <el-tab-pane :label="$t('common.kechengmulu')" name="kechengmulu">
               <keep-alive>
-                <CourseDirectory :info="info" formPage="LearningSystemDetail"/>
+                <CourseDirectory :info="info" formPage="LearningSystemDetail" :chapterId="info.listTimeChapterId"/>
               </keep-alive>
             </el-tab-pane>
             <el-tab-pane :label="$t('common.pinglun')" name="pinglun">
@@ -143,6 +143,7 @@
       path: `/learning-system/detail/${item.courseId}/course/${item.courseId}`,
       query: {
         courseId: item.courseId,
+        chapterId: item.listTimeChapterId || '',
         metaTitle: '课程详情'
       }
     })

+ 2 - 0
src/pages/SearchPlatform.vue

@@ -123,6 +123,8 @@
     workflowTitle: '',
     pageNum: 1,
     pageSize: 16,
+    orderByColumn: 'publishId',
+    isAsc: 'desc'
   })
 
   onMounted(() => {

+ 10 - 6
src/pages/order/orderConfirm.vue

@@ -188,7 +188,7 @@
         <!-- PayPal 支付按钮挂载容器(必须唯一ID) -->
         <div id="paypal-button-container" v-if="pageRedirectionData && orderInfo.payMethod == 'paypal'"></div>
       </div>
-      <div class="mt20 font_size14">录播和体验课课程属于虚拟商品,购买后无特殊原因,不支持退款</div>
+      <!-- <div class="mt20 font_size14">录播和体验课课程属于虚拟商品,购买后无特殊原因,不支持退款</div> -->
       <div class="mt20 gap10 cursor-pointer" @click="agreement = !agreement">
         <div class="checkType" :class="{'active': agreement}"></div>
         我已阅读并同意 <span class="color_theme bold">《AI学习论坛服务协议》</span> 和 <span class="color_theme bold">《AI学习论坛知识产权保护协议》</span>
@@ -203,7 +203,7 @@ import yinlianIcon from '@/assets/imgs/pay/yinlian.png'
 import paypalIcon from '@/assets/imgs/pay/paypal.png'
 import qianbaoIcon from '@/assets/imgs/pay/qianbao.png'
 
-
+import { paySuccess } from '@/utils/util.js'
 import FileUploader from '@/components/FileUploader.vue'
 import { calRate, createOrder,payResult,payConfigDearch } from '@/api/order.js'
 import qrcode from 'qrcode'
@@ -215,6 +215,8 @@ import { useRoute, useRouter } from 'vue-router'
 import DGTMessage from '@/utils/message'
 import { useAppStore } from '@/pinia/appStore'
 const appStore = useAppStore()
+import { useI18n } from 'vue-i18n' 
+const { t } = useI18n()
 //获取参数
 const route = useRoute()
 const router = useRouter()
@@ -293,7 +295,7 @@ const payNowFn = () => {
           loading.value = false;
           break;
         case 'paypal':
-          pageRedirectionData.value = payData.body || '';
+          pageRedirectionData.value = payData || '';
           nextTick(() => {
             pay_paypal();
           })
@@ -327,7 +329,9 @@ const startPolling = () => {
   pollingTimer.value = setInterval(() => {
     payResult({id:orderId.value}).then((res) => {
       if (res.code == 200 && res.data) {
-        DGTMessage.success('支付成功!');
+        // DGTMessage.success('支付成功!');
+        // 确认弹框
+        paySuccess({t});
         appStore.USERINFO();
         stopPolling()
       }
@@ -350,11 +354,11 @@ const pay_paypal = () => {
   loading.value = false;
   paypal.Buttons({
     createOrder: (data, actions) => {
-      return "06S82458P0047241R"
+      return pageRedirectionData.value
     },
     onApprove: (data, actions) => {
       return actions.order.capture().then((details) => {
-        DGTMessage.success('支付成功!')
+        paySuccess({t});
         stopPolling()
       });
     }

+ 2 - 0
src/pages/workflowTrade/workflowTrade.vue

@@ -187,6 +187,8 @@
     publishTimeEnd: '',
     pageNum: 1,
     pageSize: 10,
+    orderByColumn: 'questId',
+    isAsc: 'desc'
   })
   onMounted(() => {
     getList();

+ 1 - 0
src/pinia/appStore.js

@@ -9,6 +9,7 @@ export const useAppStore = defineStore('app', {
     userInfo: localStorage.getItem('userInfo') ? JSON.parse(localStorage.getItem('userInfo')) : null,
     token: localStorage.getItem('token') || null,
     avatarDefault: 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png',
+    showLoginDialog: false,
   }),
   getters: {
     avatar() {

+ 16 - 1
src/utils/util.js

@@ -91,7 +91,8 @@ export function confirmBuy({
         orderNum:1
       })
       if(res.code === 200){
-        DGTMessage.success(t('common.buy')+t('common.success'));
+        // DGTMessage.success(t('common.buy')+t('common.success'));
+        paySuccess({t});
         if(callback && typeof callback === 'function'){
           callback(callbackParams);
         }
@@ -139,3 +140,17 @@ export function copyText(text, t, msg=t('common.copySuccess')) {
   document.body.removeChild(input);
   DGTMessage.success(msg);
 }
+
+// 支付成功确认弹框
+export function paySuccess({t,callback}){
+  ElMessageBox.alert(t('common.paySuccess'), t('common.tip'), {
+    // if you want to disable its autofocus
+    // autofocus: false,
+    confirmButtonText: t('common.confirm'),
+    callback: (action) => {
+       if(callback && typeof callback === 'function'){
+        callback();
+      }
+    },
+  })
+};