Selaa lähdekoodia

扫码支付对接

licc 2 kuukautta sitten
vanhempi
commit
54c8ebca25
3 muutettua tiedostoa jossa 186 lisäystä ja 15 poistoa
  1. 11 0
      src/api/order.ts
  2. 174 14
      src/views/order/index.vue
  3. 1 1
      src/views/orders/list.vue

+ 11 - 0
src/api/order.ts

@@ -44,6 +44,17 @@ export function orderCheckout(params?: any) {
     return request.get({ url: '/order/checkout', params })
 }
 
+export function orderPay(params?: any) {
+    return request.get({ url: '/order/pay', params })
+}
+export function queryPayStatus(params?: any) {
+    return request.post({ url: '/sqb/query', params })
+}
+
+export function cancelOrder(params?: any) {
+    return request.post({ url: '/sqb/cancel', params })
+}
+
 export function deskOrderedDishListAll(params?: any) {
     return request.get({ url: '/orders/orderDishes', params }) //已点商品
 }

+ 174 - 14
src/views/order/index.vue

@@ -15,7 +15,6 @@
                 :key="i"
                 class="p-1 flex-wrap float-left text-center md:w-28 h-28 w-1/3"
             >
-
                 <a href="javascript:void(0);" @click="order_(i)"
                     ><div
                         class="rounded w-full h-full pt-3 relative"
@@ -88,12 +87,52 @@
             </div>
             <el-button class="w-full mt-1" plain @click="dialogVisible = false">关闭</el-button>
         </el-dialog>
+        <el-dialog
+            v-model="scanDialogVisible"
+            title="请使用扫码枪扫码支付"
+            width="300px"
+            center
+            :show-close="false"
+            :close-on-click-modal="false"
+            :close-on-press-escape="false"
+        >
+            <div class="text-center">
+                <img
+                    src="@/assets/images/scan.gif"
+                    alt="扫码"
+                    class="mx-auto mb-4"
+                    style="width: 150px"
+                />
+            </div>
+            <template #footer>
+                <div class="dialog-footer">
+                    <el-button @click="scanDialogVisible = false">取消支付</el-button>
+                </div>
+            </template>
+        </el-dialog>
+        <el-dialog
+            v-model="payingDialogVisible"
+            title="支付处理中"
+            width="300px"
+            :show-close="false"
+            :close-on-click-modal="false"
+            :close-on-press-escape="false"
+        >
+            <div class="flex flex-col items-center justify-center py-4">
+            <el-icon class="is-loading mb-4" :size="32">
+                <Loading />
+            </el-icon>
+            <p class="text-gray-600">正在支付中,请不要关闭或退出界面</p>
+            </div>
+        </el-dialog>
     </div>
     <console @init="init()" ref="consoleRef"></console>
 </template>
 <script lang="ts" setup>
+// 在 script setup 部分添加
+import { Loading } from '@element-plus/icons-vue'
 import { postAll } from '@/api/org/post'
-import { orderDeskList, createOrders, orderCheckout } from '@/api/order'
+import { orderDeskList, createOrders, orderCheckout, orderPay, queryPayStatus } from '@/api/order'
 import Console from './console.vue'
 import { getOrdersCurrent } from '@/api/orders'
 import feedback from '@/utils/feedback'
@@ -129,34 +168,143 @@ const order = () => {
         consoleRef.value?.open(currentDesk, data.userNum, res)
         init()
     })
-    console.warn("***order***",currentDesk)
+    console.warn('***order***', currentDesk)
     // router.push({ path: '/order/console', query: { deskID: id } })
 }
 const reorder = () => {
     dialogVisible.value = false
-    consoleRef.value?.open(currentDesk);//继续下单时会把当前餐桌上的订单号ordersId传进去
-    console.warn("***reorder***",currentDesk)
+    consoleRef.value?.open(currentDesk) //继续下单时会把当前餐桌上的订单号ordersId传进去
+    console.warn('***reorder***', currentDesk)
 }
 const refresh = () => {
     isLoading.value = true
     init()
 }
+const scanDialogVisible = ref(false)
+const scanCode = ref('')
+
+// 添加支付中对话框的控制变量
+const payingDialogVisible = ref(false)
+
+// 添加扫码事件监听函数
+const handleScanInput = (event: KeyboardEvent) => {
+    if (event.key === 'Enter') {
+        const code = scanCode.value
+        console.log('扫码内容:', code)
+        if (!data.canScan) {
+            return
+        }
+        data.canScan = false
+        payingDialogVisible.value = true // 显示支付中对话框
+
+// 修改支付处理逻辑
+      orderPay({ oid: currentDesk.oid, code: code })
+          .then((res) => {
+            document.removeEventListener('keydown', handleScanInput)
+            console.log(res)
+            if (res.data) {
+              console.log('支付中')
+              return queryPayStatusWithRetry(res.data)
+                  .then((paySuccess) => {
+                    if (paySuccess) {
+                      feedback.notifySuccess('成功结账' + currentDesk.amount + '元')
+                      scanDialogVisible.value = false
+                      dialogVisible.value = false
+                      init()
+                    }
+                  })
+            } else {
+              feedback.notifySuccess('成功结账' + currentDesk.amount + '元')
+              scanDialogVisible.value = false
+              dialogVisible.value = false
+              payingDialogVisible.value = false // 隐藏支付中对话框
+              init()
+            }
+          })
+          .catch(() => {
+            data.canScan = true
+            document.addEventListener('keydown', handleScanInput)
+          })
+        scanCode.value = ''
+    } else {
+        scanCode.value += event.key
+    }
+}
+
+// 定义查询支付状态的函数
+const queryPayStatusWithRetry = (sn: string): Promise<boolean> => {
+    const intervals = [3000, 5000, 10000]
+    let currentIndex = 0
+    payingDialogVisible.value = true
+
+    const tryQuery = () => {
+        return new Promise<boolean>((resolve) => {
+            setTimeout(() => {
+                queryPayStatus({ sn })
+                    .then((result) => {
+                        if (result.success) {
+                            resolve(true)
+                        } else if (currentIndex < intervals.length - 1) {
+                            currentIndex++
+                            tryQuery().then(resolve)
+                        } else {
+                            resolve(false)
+                        }
+                    })
+                    .catch(() => {
+                        if (currentIndex < intervals.length - 1) {
+                            currentIndex++
+                            tryQuery().then(resolve)
+                        } else {
+                            resolve(false)
+                        }
+                    })
+            }, intervals[currentIndex])
+        })
+    }
+
+    return tryQuery().then((success) => {
+        payingDialogVisible.value = false
+        if (!success) {
+            return cancelOrder({ sn })
+                .then(() => {
+                    feedback.notifyWarning('支付超时,订单已自动撤销')
+                    return false
+                })
+                .catch((error) => {
+                    console.error('撤单失败:', error)
+                    feedback.notifyError('支付失败,请重试')
+                    return false
+                })
+        }
+        return success
+    })
+}
+
 const checkout = () => {
     refresh()
     //结账
-    console.warn("***结账***",currentDesk)
-    if(currentDesk && !currentDesk.amount){
+    console.warn('***结账***', currentDesk)
+    if (currentDesk && !currentDesk.amount) {
         feedback.notify('当前桌未出单,无法结账')
         return false
     }
-    feedback.confirm('结账金额为' + currentDesk.amount + ',确定要结账吗?').then(() => {
-        orderCheckout({ did: currentDesk.id }).then(() => {
-            feedback.notifySuccess('成功结账' + currentDesk.amount + '元')
-            dialogVisible.value = false
-            init()
+    orderCheckout({ did: currentDesk.id }).then((res) => {
+        console.log('结账', res)
+        currentDesk.oid = res.id
+        feedback.confirm('结账金额为' + currentDesk.amount + ',确定要结账吗?').then(() => {
+            data.canScan = true
+            scanDialogVisible.value = true
+            // 添加键盘事件监听
+            document.addEventListener('keydown', handleScanInput)
         })
     })
 }
+
+// 在组件卸载时移除事件监听
+onUnmounted(() => {
+    document.removeEventListener('keydown', handleScanInput)
+})
 const tabChange = (name: any) => {
     if (name != 'all') {
         deskList.value = deskListAll.filter((ele: any) => {
@@ -167,11 +315,11 @@ const tabChange = (name: any) => {
     }
 }
 const init = async () => {
-    let _list: any[] = [];
+    let _list: any[] = []
     await orderDeskList().then((res: any) => {
         // deskList.value = res
         deskListAll = res
-        _list = res;
+        _list = res
         getOrdersCurrent().then((res) => {
             deskList.value = _list.map((item) => {
                 res.forEach((element: any) => {
@@ -208,3 +356,15 @@ onMounted(() => {
     init()
 })
 </script>
+<style scoped>
+.scan-dialog ::v-deep(.el-dialog__header) {
+    margin-right: 0;
+    padding: 20px;
+    text-align: center;
+}
+
+.scan-dialog ::v-deep(.el-dialog__title) {
+    font-size: 16px;
+    font-weight: 500;
+}
+</style>

+ 1 - 1
src/views/orders/list.vue

@@ -130,7 +130,7 @@
                 <el-table-column label="操作" width="200" fixed="right">
                     <template #default="{ row }">
                         <el-button type="primary" link @click="showDetail(row)">查看已点菜品</el-button>
-                        <el-button v-if="row.type == 1 && row.status=='2' && !row.refundAmount" type="danger" link @click="refund(row)">退款</el-button>
+                        <el-button v-if="row.status=='2' && !row.refundAmount" type="danger" link @click="refund(row)">退款</el-button>
                     </template>
                 </el-table-column>
             </el-table>