index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. <script setup lang="ts">
  2. import { mapState } from 'pinia'
  3. import { useI18n } from 'vue-i18n'
  4. import { ref, watch, onMounted, nextTick } from 'vue'
  5. import logoCn from '@/assets/images/logoCn.png'
  6. import logoEn from '@/assets/images/logoEn.png'
  7. import { useUserStore } from '@/stores/user'
  8. import QrcodeVue from 'qrcode.vue'
  9. import { show, showConfirm } from '@/components/Toast'
  10. import { openPay, queryOrderStatus, getOrderInfo } from '@/api/api'
  11. import { useRouter, useRoute } from 'vue-router'
  12. import { GetRequest, getRemark } from '@/utils/index'
  13. import { paysidtype } from '@/utils/status'
  14. import { getCurrentInstance } from 'vue'
  15. //得到i18n的locale token, info,
  16. const { locale: language, t } = useI18n()
  17. let t1 = null
  18. const route = useRoute()
  19. const { isEur, info } = useUserStore()
  20. const orderSn = ref(route.query.id || GetRequest('orderSn'))
  21. let { $cdn } = getCurrentInstance()?.proxy
  22. const selectedPayType = ref(isEur ? 'paypal' : 'alipay')
  23. watch(selectedPayType, () => {
  24. getCode()
  25. })
  26. const qrCodeUrl = ref('')
  27. const orderDetal = ref({})
  28. const response = ref({
  29. price: 0.01,
  30. src: ''
  31. })
  32. onMounted(() => {
  33. // getDetial()
  34. })
  35. function inverRequest() {
  36. clearInterval(t1)
  37. t1 = null
  38. t1 = setInterval(() => {
  39. handleQueryOrderStatus()
  40. }, 5000)
  41. }
  42. async function handleQueryOrderStatus() {
  43. if (t1) {
  44. let response = await getOrderInfo(orderSn.value)
  45. orderDetal.value = response
  46. if (response.payStatus === 0) {
  47. //未支付
  48. } else {
  49. //支付失败
  50. t1 = null
  51. t1 && clearInterval(t1)
  52. showConfirm({
  53. text: response.autoPay
  54. ? t('payInfo.autoPayTips', {paytype: response.payType == 5 ? 'PayPal' : 'Stripe'})
  55. : response.payStatus === 2
  56. ? t('payInfo.payfail')
  57. : t('mall.paySuccessTip'),
  58. type: response.payStatus === 2 ? 'err' : 'success',
  59. callback: () => {
  60. if (response.payStatus === 2) {
  61. getCode()
  62. } else {
  63. window.close()
  64. }
  65. }
  66. })
  67. }
  68. }
  69. }
  70. function getDetial() {
  71. getOrderInfo(orderSn.value).then((res) => {
  72. orderDetal.value = res
  73. if (isEur) {
  74. selectedPayType.value = orderDetal.value.payType == 6 ? 'stripe' : 'paypal'
  75. }
  76. getCode()
  77. })
  78. }
  79. getDetial()
  80. function handlePay() {
  81. if (isEur) {
  82. //打开一个不被拦截的新窗口
  83. // var win = window.open();
  84. // win.document.body.innerHTML="loading......";
  85. openPay({
  86. orderSn: orderSn.value,
  87. payType: paysidtype[selectedPayType.value],
  88. productName: getRemark(orderDetal.value.goodsInfo, orderDetal.value.orderType, t),
  89. openId: ''
  90. }).then((res) => {
  91. qrCodeUrl.value = res.qrCodeUrl || res.redirect
  92. window.location.href = qrCodeUrl.value
  93. })
  94. } else {
  95. window.open(qrCodeUrl.value)
  96. }
  97. }
  98. async function getCode() {
  99. inverRequest()
  100. if (orderDetal.value.payType == 5 || orderDetal.value.payType == 6) return
  101. qrCodeUrl.value = ''
  102. openPay({
  103. orderSn: orderSn.value,
  104. payType: paysidtype[selectedPayType.value],
  105. productName: getRemark(orderDetal.value.goodsInfo, orderDetal.value.orderType, t),
  106. openId: ''
  107. }).then((res) => {
  108. qrCodeUrl.value = res.qrCodeUrl || res.redirect
  109. })
  110. }
  111. </script>
  112. <template>
  113. <div class="pcPage">
  114. <div class="mall-pay">
  115. <div class="container">
  116. <div class="pay-header">
  117. <!-- <div class="logo">
  118. <img :src="language === 'zh' ? logoCn : logoEn" alt="" />
  119. </div> -->
  120. <p>{{ $t('mall.payCenter') }}</p>
  121. </div>
  122. <div class="pay-content">
  123. <div class="account">
  124. <span class="label">{{ $t('mall.nowAccount') }}:</span
  125. ><span>{{ orderDetal.userName }}</span>
  126. </div>
  127. <div class="account">
  128. <span class="label">
  129. {{
  130. $t(
  131. `mall.${
  132. orderDetal.orderType == 'incrementOrder'
  133. ? 'vip'
  134. : orderDetal.orderType == 'cooperationOrder'
  135. ? 'cooperationOrder'
  136. : orderDetal.orderType == 'downOrder'
  137. ? 'downdesc'
  138. : 'goqy'
  139. }`
  140. )
  141. }}:
  142. <span
  143. v-for="(item, index) in orderDetal.goodsInfo"
  144. :key="index"
  145. style="margin-right: 10px"
  146. >
  147. <span v-if="item">
  148. <span v-if="index != 0">、</span>
  149. <span style="margin-right: 5px" v-if="orderDetal.orderType == 'cooperationOrder'">
  150. {{ $t('mall.cooperationOrderName', { count: item.count }) }}
  151. </span>
  152. <span
  153. style="margin-right: 5px"
  154. v-else-if="orderDetal.orderType != 'incrementOrder'"
  155. >
  156. {{
  157. orderDetal.orderType == 'downOrder'
  158. ? `${item.name} (${item.sceneNum})`
  159. : language === 'zh'
  160. ? item.name
  161. : item.nameEn
  162. }}
  163. </span>
  164. <span style="margin-right: 5px" v-else>
  165. {{
  166. item.type == 1
  167. ? $t('payInfo.gjhy')
  168. : isEur
  169. ? $t('payInfo.zyhys')
  170. : $t('payInfo.zyhy')
  171. }}
  172. </span>
  173. <span
  174. v-if="
  175. orderDetal.orderType != 'downOrder' &&
  176. orderDetal.orderType != 'cooperationOrder'
  177. "
  178. >× {{ item.count }}</span
  179. >
  180. </span>
  181. <!-- <span v-else>1</span> -->
  182. <span v-if="orderDetal.orderType == 'incrementOrder'"
  183. >,{{
  184. item.type == 1
  185. ? $t(`payInfo.expirationmon`, { num: item.monthQy || 1 })
  186. : $t(`payInfo.expiration`, { num: 1 })
  187. }}</span
  188. >
  189. </span></span
  190. >
  191. </div>
  192. <div class="pay-types">
  193. <p class="label">{{ $t('mall.payType') }}:</p>
  194. <div
  195. v-if="!isEur"
  196. class="pay-type ali-pay"
  197. @click="selectedPayType = 'alipay'"
  198. :class="{ 'is-active': selectedPayType === 'alipay' }"
  199. >
  200. <img :src="`${$cdn}images/ali-pay.png`" class="t-icon" alt />
  201. <h-icon type="vip_true" class="select-icon"></h-icon>
  202. <img src="@/assets/images/vip_true.svg" class="t-click" alt />
  203. {{ $t('mall.aliPay') }}
  204. </div>
  205. <div
  206. v-if="!isEur"
  207. class="pay-type wechat-pay"
  208. @click="selectedPayType = 'wechatPay'"
  209. :class="{ 'is-active': selectedPayType === 'wechatPay' }"
  210. >
  211. <img :src="`${$cdn}images/wechat-pay.png`" class="t-icon" alt />
  212. <h-icon type="vip_true" class="select-icon"></h-icon>
  213. <img src="@/assets/images/vip_true.svg" class="t-click" alt />
  214. {{ $t('mall.wechatPay') }}
  215. </div>
  216. <div
  217. v-if="isEur"
  218. class="pay-type paypal-pay"
  219. @click="selectedPayType = 'paypal'"
  220. :class="{ 'is-active': selectedPayType === 'paypal' }"
  221. >
  222. <img
  223. style="height: 26px; width: 100px"
  224. src="@/assets/images/paypal.png"
  225. class="t-icon"
  226. alt
  227. />
  228. <h-icon type="vip_true" class="select-icon"></h-icon>
  229. <img src="@/assets/images/vip_true.svg" class="t-click" alt />
  230. </div>
  231. <div
  232. v-if="isEur"
  233. class="pay-type paypal-pay"
  234. @click="selectedPayType = 'stripe'"
  235. :class="{ 'is-active': selectedPayType === 'stripe' }"
  236. >
  237. <img
  238. style="height: 26px; width: 62px"
  239. src="@/assets/images/stripe.png"
  240. class="t-icon"
  241. alt
  242. />
  243. <h-icon type="vip_true" class="select-icon"></h-icon>
  244. <img src="@/assets/images/vip_true.svg" class="t-click" alt />
  245. </div>
  246. </div>
  247. <div class="pay-info">
  248. <p class="label">{{ $t('mall.payNum') }}:</p>
  249. <p class="price">{{ isEur ? '$' : '¥' }}{{ orderDetal.orderMoney }}</p>
  250. <div class="pay-qrcode" style="min-height: 220px" v-if="!isEur">
  251. <QrcodeVue
  252. v-if="qrCodeUrl"
  253. :value="qrCodeUrl"
  254. class="enter-x flex justify-center xl:justify-start"
  255. :size="185"
  256. />
  257. <p>
  258. {{
  259. $t('mall.payTip', {
  260. type: selectedPayType === 'alipay' ? $t('mall.aliPay') : $t('mall.wechat')
  261. })
  262. }}
  263. </p>
  264. </div>
  265. <div v-else class="payment" @click="handlePay">
  266. {{ orderDetal.autoPay == 1 ? $t('payInfo.autoRenew') : $t('payInfo.payOrder') }}
  267. </div>
  268. <div v-show="!isEur" :class="`pay-scan-tip ${language === 'zh' ? '' : 'isEn'}`"></div>
  269. </div>
  270. </div>
  271. </div>
  272. </div>
  273. </div>
  274. </template>
  275. <style lang="less" scoped>
  276. .mall-pay {
  277. padding: 61px 0 61px;
  278. background: #f7f7f7;
  279. .container {
  280. background: #fff;
  281. }
  282. .pay-header {
  283. border-bottom: 1px solid #e4e4e4;
  284. padding: 26px 0 21px 92px;
  285. font-size: 24px;
  286. line-height: 32px;
  287. .logo,
  288. p {
  289. display: inline-block;
  290. vertical-align: middle;
  291. }
  292. .logo {
  293. margin-right: 52px;
  294. position: relative;
  295. &::after {
  296. content: '';
  297. display: block;
  298. width: 1px;
  299. height: 34px;
  300. background: #c8c8c8;
  301. position: absolute;
  302. right: -30px;
  303. top: 11px;
  304. }
  305. }
  306. }
  307. .pay-content {
  308. padding: 0 92px 80px;
  309. }
  310. .account {
  311. // height: 56px;
  312. line-height: 56px;
  313. font-weight: bold;
  314. border-bottom: 1px solid #e4e4e4;
  315. }
  316. .label {
  317. font-weight: bold;
  318. margin-right: 13px;
  319. }
  320. .pay-types {
  321. padding: 50px 0;
  322. border-bottom: 1px solid #e4e4e4;
  323. & > p,
  324. & > div {
  325. display: inline-block;
  326. }
  327. .pay-type {
  328. width: 190px;
  329. height: 40px;
  330. line-height: 40px;
  331. margin-right: 30px;
  332. border: 1px solid #909090;
  333. border-radius: 2px;
  334. padding-left: 60px;
  335. cursor: pointer;
  336. position: relative;
  337. &.is-active {
  338. border-color: @primary-color;
  339. &::after {
  340. content: '';
  341. display: block;
  342. position: absolute;
  343. right: 0;
  344. bottom: 0;
  345. border-bottom: 20px solid @primary-color;
  346. border-left: 22px solid transparent;
  347. }
  348. .t-click {
  349. display: block;
  350. z-index: 1;
  351. }
  352. }
  353. .select-icon {
  354. color: #fff;
  355. position: absolute;
  356. bottom: 0;
  357. right: 0;
  358. z-index: 1;
  359. line-height: 1;
  360. font-size: 12px;
  361. }
  362. .t-icon {
  363. width: 30px;
  364. height: 30px;
  365. padding: 6px;
  366. left: 0;
  367. position: absolute;
  368. }
  369. .t-click {
  370. position: absolute;
  371. right: 0;
  372. bottom: 0;
  373. display: none;
  374. display: none;
  375. }
  376. }
  377. .pay-icon {
  378. position: absolute;
  379. left: 4px;
  380. top: 0;
  381. height: 40px;
  382. width: 34px;
  383. display: inline-block;
  384. background: url(~@/assets/images/refactor/mall/ali-icon.png) no-repeat center center;
  385. background-size: 34px 34px;
  386. &.wechat-icon {
  387. background: url(~@/assets/images/refactor/mall/wechat-icon.png) no-repeat center center;
  388. background-size: 28px 25px;
  389. }
  390. }
  391. }
  392. .pay-info {
  393. padding-top: 24px;
  394. position: relative;
  395. & > p {
  396. display: inline-block;
  397. vertical-align: middle;
  398. }
  399. .price {
  400. color: #ff0000;
  401. font-size: 40px;
  402. line-height: 50px;
  403. }
  404. }
  405. .pay-qrcode {
  406. padding: 60px 0 0 0px;
  407. text-align: center;
  408. img {
  409. width: 190px;
  410. height: 190px;
  411. margin-bottom: 7px;
  412. display: block;
  413. }
  414. }
  415. .payment {
  416. width: 216px;
  417. height: 55px;
  418. line-height: 55px;
  419. background: #29b2ff;
  420. margin: 60px auto 0 auto;
  421. border-radius: 4px 4px 4px 4px;
  422. opacity: 1;
  423. text-align: center;
  424. font-size: 16px;
  425. font-family: PingFang SC-Regular, PingFang SC;
  426. font-weight: 400;
  427. color: #ffffff;
  428. cursor: pointer;
  429. }
  430. .pay-scan-tip {
  431. width: 186px;
  432. height: 165.5px;
  433. background: url(@/assets/images/scan-tip.png) no-repeat center center;
  434. background-size: contain;
  435. position: absolute;
  436. top: 113px;
  437. left: calc(50% + 40px + 92px);
  438. &.isEn {
  439. background-image: url(@/assets/images/scan-tip-en.png);
  440. }
  441. }
  442. }
  443. </style>