From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目
---
src/views/pay/cashier/index.vue | 494 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 494 insertions(+), 0 deletions(-)
diff --git a/src/views/pay/cashier/index.vue b/src/views/pay/cashier/index.vue
new file mode 100644
index 0000000..f07536f
--- /dev/null
+++ b/src/views/pay/cashier/index.vue
@@ -0,0 +1,494 @@
+<template>
+ <!-- 鏀粯淇℃伅 -->
+ <el-card v-loading="loading">
+ <el-descriptions title="鏀粯淇℃伅" :column="3" border>
+ <el-descriptions-item label="鏀粯鍗曞彿">{{ payOrder.id }}</el-descriptions-item>
+ <el-descriptions-item label="鍟嗗搧鏍囬">{{ payOrder.subject }}</el-descriptions-item>
+ <el-descriptions-item label="鍟嗗搧鍐呭">{{ payOrder.body }}</el-descriptions-item>
+ <el-descriptions-item label="鏀粯閲戦">
+ 锟{ (payOrder.price / 100.0).toFixed(2) }}
+ </el-descriptions-item>
+ <el-descriptions-item label="鍒涘缓鏃堕棿">
+ {{ formatDate(payOrder.createTime) }}
+ </el-descriptions-item>
+ <el-descriptions-item label="杩囨湡鏃堕棿">
+ {{ formatDate(payOrder.expireTime) }}
+ </el-descriptions-item>
+ </el-descriptions>
+ </el-card>
+
+ <!-- 鏀粯閫夋嫨妗� -->
+ <el-card style="margin-top: 10px" v-loading="submitLoading" element-loading-text="鎻愪氦鏀粯涓�...">
+ <!-- 鏀粯瀹� -->
+ <el-descriptions title="閫夋嫨鏀粯瀹濇敮浠�" />
+ <div class="pay-channel-container">
+ <div
+ class="box"
+ v-for="channel in channelsAlipay"
+ :key="channel.code"
+ @click="submit(channel.code)"
+ >
+ <img :src="channel.icon" />
+ <div class="title">{{ channel.name }}</div>
+ </div>
+ </div>
+ <!-- 寰俊鏀粯 -->
+ <el-descriptions title="閫夋嫨寰俊鏀粯" style="margin-top: 20px" />
+ <div class="pay-channel-container">
+ <div
+ class="box"
+ v-for="channel in channelsWechat"
+ :key="channel.code"
+ @click="submit(channel.code)"
+ >
+ <img :src="channel.icon" />
+ <div class="title">{{ channel.name }}</div>
+ </div>
+ </div>
+ <!-- 鍏跺畠鏀粯 -->
+ <el-descriptions title="閫夋嫨鍏跺畠鏀粯" style="margin-top: 20px" />
+ <div class="pay-channel-container">
+ <div
+ class="box"
+ v-for="channel in channelsMock"
+ :key="channel.code"
+ @click="submit(channel.code)"
+ >
+ <img :src="channel.icon" />
+ <div class="title">{{ channel.name }}</div>
+ </div>
+ </div>
+ </el-card>
+
+ <!-- 灞曠ず褰㈠紡锛氫簩缁寸爜 URL -->
+ <Dialog
+ :title="qrCode.title"
+ v-model="qrCode.visible"
+ width="350px"
+ append-to-body
+ :close-on-press-escape="false"
+ >
+ <Qrcode :text="qrCode.url" :width="310" />
+ </Dialog>
+
+ <!-- 灞曠ず褰㈠紡锛欱arCode 鏉″舰鐮� -->
+ <Dialog
+ :title="barCode.title"
+ v-model="barCode.visible"
+ width="500px"
+ append-to-body
+ :close-on-press-escape="false"
+ >
+ <el-form ref="form" label-width="80px">
+ <el-row>
+ <el-col :span="24">
+ <el-form-item label="鏉″舰鐮�" prop="name">
+ <el-input v-model="barCode.value" placeholder="璇疯緭鍏ユ潯褰㈢爜" required />
+ </el-form-item>
+ </el-col>
+ <el-col :span="24">
+ <div style="text-align: right">
+ 鎴栦娇鐢�
+ <el-link
+ type="danger"
+ target="_blank"
+ href="https://baike.baidu.com/item/鏉$爜鏀粯/10711903"
+ >
+ (鎵爜鏋�/鎵爜鐩�)
+ </el-link>
+ 鎵爜
+ </div>
+ </el-col>
+ </el-row>
+ </el-form>
+ <template #footer>
+ <el-button
+ type="primary"
+ @click="submit0(barCode.channelCode)"
+ :disabled="barCode.value.length === 0"
+ >
+ 纭鏀粯
+ </el-button>
+ <el-button @click="barCode.visible = false">鍙� 娑�</el-button>
+ </template>
+ </Dialog>
+</template>
+
+<script lang="ts" setup>
+import { Qrcode } from '@/components/Qrcode'
+import * as PayOrderApi from '@/api/pay/order'
+import { PayChannelEnum, PayDisplayModeEnum, PayOrderStatusEnum } from '@/utils/constants'
+import { formatDate } from '@/utils/formatTime'
+import { useTagsViewStore } from '@/store/modules/tagsView'
+
+// 瀵煎叆鍥炬爣
+import svg_alipay_pc from '@/assets/svgs/pay/icon/alipay_pc.svg'
+import svg_alipay_wap from '@/assets/svgs/pay/icon/alipay_wap.svg'
+import svg_alipay_app from '@/assets/svgs/pay/icon/alipay_app.svg'
+import svg_alipay_qr from '@/assets/svgs/pay/icon/alipay_qr.svg'
+import svg_alipay_bar from '@/assets/svgs/pay/icon/alipay_bar.svg'
+import svg_wx_pub from '@/assets/svgs/pay/icon/wx_pub.svg'
+import svg_wx_lite from '@/assets/svgs/pay/icon/wx_lite.svg'
+import svg_wx_app from '@/assets/svgs/pay/icon/wx_app.svg'
+import svg_wx_native from '@/assets/svgs/pay/icon/wx_native.svg'
+import svg_wx_bar from '@/assets/svgs/pay/icon/wx_bar.svg'
+import svg_wallet from '@/assets/svgs/pay/icon/wallet.svg'
+import svg_mock from '@/assets/svgs/pay/icon/mock.svg'
+
+defineOptions({ name: 'PayCashier' })
+
+const message = useMessage() // 娑堟伅寮圭獥
+const route = useRoute() // 璺敱
+const { push, currentRoute } = useRouter() // 璺敱
+const { delView } = useTagsViewStore() // 瑙嗗浘鎿嶄綔
+
+const id = ref(undefined) // 鏀粯鍗曞彿
+const returnUrl = ref<string | undefined>(undefined) // 鏀粯瀹岀殑鍥炶皟鍦板潃
+const loading = ref(false) // 鏀粯淇℃伅鐨� loading
+const payOrder = ref({}) // 鏀粯淇℃伅
+const channelsAlipay = [
+ {
+ name: '鏀粯瀹� PC 缃戠珯鏀粯',
+ icon: svg_alipay_pc,
+ code: 'alipay_pc'
+ },
+ {
+ name: '鏀粯瀹� Wap 缃戠珯鏀粯',
+ icon: svg_alipay_wap,
+ code: 'alipay_wap'
+ },
+ {
+ name: '鏀粯瀹� App 缃戠珯鏀粯',
+ icon: svg_alipay_app,
+ code: 'alipay_app'
+ },
+ {
+ name: '鏀粯瀹濇壂鐮佹敮浠�',
+ icon: svg_alipay_qr,
+ code: 'alipay_qr'
+ },
+ {
+ name: '鏀粯瀹濇潯鐮佹敮浠�',
+ icon: svg_alipay_bar,
+ code: 'alipay_bar'
+ }
+]
+const channelsWechat = [
+ {
+ name: '寰俊鍏紬鍙锋敮浠�',
+ icon: svg_wx_pub,
+ code: 'wx_pub'
+ },
+ {
+ name: '寰俊灏忕▼搴忔敮浠�',
+ icon: svg_wx_lite,
+ code: 'wx_lite'
+ },
+ {
+ name: '寰俊 App 鏀粯',
+ icon: svg_wx_app,
+ code: 'wx_app'
+ },
+ {
+ name: '寰俊鎵爜鏀粯',
+ icon: svg_wx_native,
+ code: 'wx_native'
+ },
+ {
+ name: '寰俊鏉$爜鏀粯',
+ icon: svg_wx_bar,
+ code: 'wx_bar'
+ }
+]
+const channelsMock = [
+ {
+ name: '閽卞寘鏀粯',
+ icon: svg_wallet,
+ code: 'wallet'
+ },
+ {
+ name: '妯℃嫙鏀粯',
+ icon: svg_mock,
+ code: 'mock'
+ }
+]
+
+const submitLoading = ref(false) // 鎻愪氦鏀粯鐨� loading
+const interval = ref<any>(undefined) // 瀹氭椂浠诲姟锛岃疆璇㈡槸鍚﹀畬鎴愭敮浠�
+const qrCode = ref({
+ // 灞曠ず褰㈠紡锛氫簩缁寸爜
+ url: '',
+ title: '',
+ visible: false
+})
+const barCode = ref({
+ // 灞曠ず褰㈠紡锛氭潯褰㈢爜
+ channelCode: '',
+ value: '',
+ title: '',
+ visible: false
+})
+
+/** 鑾峰緱鏀粯淇℃伅 */
+const getDetail = async () => {
+ // 1.1 鏈紶閫掕鍗曠紪鍙�
+ if (!id.value) {
+ message.error('鏈紶閫掓敮浠樺崟鍙凤紝鏃犳硶鏌ョ湅瀵瑰簲鐨勬敮浠樹俊鎭�')
+ goReturnUrl('cancel')
+ return
+ }
+ const data = await PayOrderApi.getOrder(id.value, true)
+ // 1.2 鏃犳硶鏌ヨ鍒版敮浠樹俊鎭�
+ if (!data) {
+ message.error('鏀粯璁㈠崟涓嶅瓨鍦紝璇锋鏌ワ紒')
+ goReturnUrl('cancel')
+ return
+ }
+ // 1.3 濡傛灉宸叉敮浠樸�佹垨鑰呭凡鍏抽棴锛屽垯鐩存帴璺宠浆
+ if (data.status === PayOrderStatusEnum.SUCCESS.status) {
+ message.success('鏀粯鎴愬姛')
+ goReturnUrl('success')
+ return
+ } else if (data.status === PayOrderStatusEnum.CLOSED.status) {
+ message.error('鏃犳硶鏀粯锛屽師鍥狅細璁㈠崟宸插叧闂�')
+ goReturnUrl('close')
+ return
+ }
+ // 2. 姝e父灞曠ず鏀粯淇℃伅
+ payOrder.value = data
+}
+
+/** 鎻愪氦鏀粯 */
+const submit = (channelCode) => {
+ // 鏉″舰鐮佹敮浠橈紝闇�瑕佺壒娈婂鐞�
+ if (channelCode === PayChannelEnum.ALIPAY_BAR.code) {
+ barCode.value = {
+ channelCode: channelCode,
+ value: '',
+ title: '鈥滄敮浠樺疂鈥濇潯鐮佹敮浠�',
+ visible: true
+ }
+ return
+ }
+ if (channelCode === PayChannelEnum.WX_BAR.code) {
+ barCode.value = {
+ channelCode: channelCode,
+ value: '',
+ title: '鈥滃井淇♀�濇潯鐮佹敮浠�',
+ visible: true
+ }
+ return
+ }
+
+ // 寰俊鍏紬鍙枫�佸皬绋嬪簭鏀粯锛屾棤娉曞湪 PC 缃戦〉涓繘琛�
+ if (channelCode === PayChannelEnum.WX_PUB.code) {
+ message.error('寰俊鍏紬鍙锋敮浠橈細涓嶆敮鎸� PC 缃戠珯')
+ return
+ }
+ if (channelCode === PayChannelEnum.WX_LITE.code) {
+ message.error('寰俊灏忕▼搴忥細涓嶆敮鎸� PC 缃戠珯')
+ return
+ }
+
+ // 榛樿鐨勬彁浜ゅ鐞�
+ submit0(channelCode)
+}
+
+const submit0 = async (channelCode) => {
+ submitLoading.value = true
+ try {
+ const formData = {
+ id: id.value,
+ channelCode: channelCode,
+ returnUrl: location.href, // 鏀粯鎴愬姛鍚庯紝鏀粯娓犻亾璺宠浆鍥炲綋鍓嶉〉锛涘啀鐢卞綋鍓嶉〉锛岃烦杞洖 {@link returnUrl} 瀵瑰簲鐨勫湴鍧�
+ ...buildSubmitParam(channelCode)
+ }
+ const data = await PayOrderApi.submitOrder(formData)
+ // 鐩存帴杩斿洖宸叉敮浠樼殑鎯呭喌锛屼緥濡傝鎵爜鏀粯
+ if (data.status === PayOrderStatusEnum.SUCCESS.status) {
+ clearQueryInterval()
+ message.success('鏀粯鎴愬姛锛�')
+ goReturnUrl('success')
+ return
+ }
+
+ // 灞曠ず瀵瑰簲鐨勭晫闈�
+ if (data.displayMode === PayDisplayModeEnum.URL.mode) {
+ displayUrl(channelCode, data)
+ } else if (data.displayMode === PayDisplayModeEnum.QR_CODE.mode) {
+ displayQrCode(channelCode, data)
+ } else if (data.displayMode === PayDisplayModeEnum.APP.mode) {
+ displayApp(channelCode)
+ }
+
+ // 鎵撳紑杞浠诲姟
+ createQueryInterval()
+ } finally {
+ submitLoading.value = false
+ }
+}
+
+/** 鏋勫缓鎻愪氦鏀粯鐨勯澶栧弬鏁� */
+const buildSubmitParam = (channelCode) => {
+ // 鈶� 鏀粯瀹� BarCode 鏀粯鏃讹紝闇�瑕佷紶閫� authCode 鏉″舰鐮�
+ if (channelCode === PayChannelEnum.ALIPAY_BAR.code) {
+ return {
+ channelExtras: {
+ auth_code: barCode.value.value
+ }
+ }
+ }
+ // 鈶� 寰俊 BarCode 鏀粯鏃讹紝闇�瑕佷紶閫� authCode 鏉″舰鐮�
+ if (channelCode === PayChannelEnum.WX_BAR.code) {
+ return {
+ channelExtras: {
+ authCode: barCode.value.value
+ }
+ }
+ }
+ return {}
+}
+
+/** 鎻愪氦鏀粯鍚庯紝URL 鐨勫睍绀哄舰寮� */
+const displayUrl = (_channelCode, data) => {
+ location.href = data.displayContent
+ submitLoading.value = false
+}
+
+/** 鎻愪氦鏀粯鍚庯紙鎵爜鏀粯锛� */
+const displayQrCode = (channelCode, data) => {
+ let title = '璇蜂娇鐢ㄦ墜鏈烘祻瑙堝櫒鈥滄壂涓�鎵��'
+ if (channelCode === PayChannelEnum.ALIPAY_WAP.code) {
+ // 鑰冭檻鍒� WAP 娴嬭瘯锛屾墍浠ュ紩瀵兼墜鏈烘祻瑙堝櫒鎼�
+ } else if (channelCode.indexOf('alipay_') === 0) {
+ title = '璇蜂娇鐢ㄦ敮浠樺疂鈥滄壂涓�鎵�濇壂鐮佹敮浠�'
+ } else if (channelCode.indexOf('wx_') === 0) {
+ title = '璇蜂娇鐢ㄥ井淇♀�滄壂涓�鎵�濇壂鐮佹敮浠�'
+ }
+ qrCode.value = {
+ title: title,
+ url: data.displayContent,
+ visible: true
+ }
+ submitLoading.value = false
+}
+
+/** 鎻愪氦鏀粯鍚庯紙App锛� */
+const displayApp = (channelCode) => {
+ if (channelCode === PayChannelEnum.ALIPAY_APP.code) {
+ message.error('鏀粯瀹� App 鏀粯锛氭棤娉曞湪缃戦〉鏀粯锛�')
+ }
+ if (channelCode === PayChannelEnum.WX_APP.code) {
+ message.error('寰俊 App 鏀粯锛氭棤娉曞湪缃戦〉鏀粯锛�')
+ }
+ submitLoading.value = false
+}
+
+/** 杞鏌ヨ浠诲姟 */
+const createQueryInterval = () => {
+ if (interval.value) {
+ return
+ }
+ interval.value = setInterval(async () => {
+ const data = await PayOrderApi.getOrder(id.value)
+ // 宸叉敮浠�
+ if (data.status === PayOrderStatusEnum.SUCCESS.status) {
+ clearQueryInterval()
+ message.success('鏀粯鎴愬姛锛�')
+ goReturnUrl('success')
+ }
+ // 宸插彇娑�
+ if (data.status === PayOrderStatusEnum.CLOSED.status) {
+ clearQueryInterval()
+ message.error('鏀粯宸插叧闂紒')
+ goReturnUrl('close')
+ }
+ }, 1000 * 2)
+}
+
+/** 娓呯┖鏌ヨ浠诲姟 */
+const clearQueryInterval = () => {
+ // 娓呯┖鍚勭寮圭獥
+ qrCode.value = {
+ title: '',
+ url: '',
+ visible: false
+ }
+ // 娓呯┖浠诲姟
+ clearInterval(interval.value)
+ interval.value = undefined
+}
+
+/**
+ * 鍥炲埌涓氬姟鐨� URL
+ *
+ * @param payResult 鏀粯缁撴灉
+ * 鈶� success锛氭敮浠樻垚鍔�
+ * 鈶� cancel锛氬彇娑堟敮浠�
+ * 鈶� close锛氭敮浠樺凡鍏抽棴
+ */
+const goReturnUrl = (payResult) => {
+ // 娓呯悊浠诲姟
+ clearQueryInterval()
+
+ // 鏈厤缃殑鎯呭喌涓嬶紝鍙兘鍏抽棴
+ if (!returnUrl.value) {
+ delView(unref(currentRoute))
+ return
+ }
+
+ const url =
+ returnUrl.value.indexOf('?') >= 0
+ ? returnUrl.value + '&payResult=' + payResult
+ : returnUrl.value + '?payResult=' + payResult
+ // 濡傛灉鏈夐厤缃紝涓旀槸 http 寮�澶达紝鍒欐祻瑙堝櫒璺宠浆
+ if (returnUrl.value.indexOf('http') === 0) {
+ location.href = url
+ } else {
+ delView(unref(currentRoute))
+ push({
+ path: url
+ })
+ }
+}
+
+/** 鍒濆鍖� */
+onMounted(() => {
+ id.value = route.query.id
+ if (route.query.returnUrl) {
+ returnUrl.value = decodeURIComponent(route.query.returnUrl)
+ }
+ getDetail()
+})
+
+/** 閿�姣� */
+onBeforeUnmount(() => {
+ clearQueryInterval()
+})
+</script>
+
+<style lang="scss" scoped>
+.pay-channel-container {
+ display: flex;
+ margin-top: -10px;
+
+ .box {
+ width: 160px;
+ padding-top: 10px;
+ padding-bottom: 5px;
+ margin-right: 10px;
+ text-align: center;
+ cursor: pointer;
+ border: 1px solid #e6ebf5;
+
+ img {
+ width: 40px;
+ height: 40px;
+ }
+
+ .title {
+ padding-top: 5px;
+ }
+ }
+}
+</style>
--
Gitblit v1.8.0