@2kog/pkg-widget 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,837 @@
1
+ <!-- 公共支付组件 -->
2
+ <template>
3
+ <el-dialog
4
+ class="c-pay-pop"
5
+ :title="title || t('payment.title')"
6
+ v-model="visible"
7
+ :close-on-click-modal="false"
8
+ :close-on-press-escape="false"
9
+ :width="width"
10
+ >
11
+ <!-- 支付成功 -->
12
+ <div v-if="paymentSuccess" class="success-container">
13
+ <el-icon color="#67c23a" :size="64"><CircleCheck /></el-icon>
14
+ <h3>{{ t('payment.success') }}</h3>
15
+ <p>{{ t('payment.successDesc') }}</p>
16
+ </div>
17
+
18
+ <!-- 支付界面 -->
19
+ <div v-else class="c-pay-pop-box">
20
+ <!-- 支付方式切换 -->
21
+ <el-tabs class="c-pay-pop-tab" v-model="payType" type="card" @tab-change="onPayTypeChange">
22
+ <el-tab-pane :label="t('payment.wepay')" name="wepay">
23
+ <template #label>
24
+ <span class="u-tab">
25
+ <img src="../../assets/img/pay/wepay.svg" />
26
+ {{ t('payment.wepay') }}
27
+ <em>{{ t('payment.wepayTip') }}</em>
28
+ </span>
29
+ </template>
30
+ </el-tab-pane>
31
+ <el-tab-pane :label="t('payment.alipay')" name="alipay">
32
+ <template #label>
33
+ <span class="u-tab">
34
+ <img src="../../assets/img/pay/alipay.svg" />
35
+ {{ t('payment.alipay') }}
36
+ <em>{{ t('payment.alipayTip') }}</em>
37
+ </span>
38
+ </template>
39
+ </el-tab-pane>
40
+ </el-tabs>
41
+
42
+ <!-- 支付内容 -->
43
+ <div class="c-pay-pop-content">
44
+ <h2 class="u-title">{{ productDesc }}</h2>
45
+ <div class="u-price" v-if="price">
46
+ <b>{{ formatPrice(price) }}</b>
47
+ <em>{{ t('payment.currency') }}</em>
48
+ </div>
49
+ <div class="u-paybox">
50
+ <i class="u-qrcode" :class="{ 'u-wechat': isWepay, 'u-alipay': isAlipay }">
51
+ <!-- 支付宝 PC 使用 iframe -->
52
+ <iframe
53
+ v-if="isAlipayPc && longUrl && !paymentSuccess"
54
+ :src="longUrl"
55
+ width="300"
56
+ height="300"
57
+ frameborder="0"
58
+ class="u-iframe"
59
+ ></iframe>
60
+
61
+ <!-- 其他支付方式使用二维码 -->
62
+ <qrcode-vue
63
+ v-else-if="qrcode && !paymentSuccess"
64
+ class="u-pic"
65
+ :value="qrcode"
66
+ :size="300"
67
+ level="H"
68
+ ></qrcode-vue>
69
+
70
+ <!-- 支付成功提示(显示在二维码区域) -->
71
+ <div v-else-if="paymentSuccess && isAlipayPc" class="u-success-inline">
72
+ <el-icon color="#67c23a" :size="64"><CircleCheck /></el-icon>
73
+ <p>{{ t('payment.success') }}</p>
74
+ </div>
75
+
76
+ <!-- 加载中 -->
77
+ <div v-else class="u-loading">
78
+ <el-icon class="is-loading"><Loading /></el-icon>
79
+ <p>{{ t('payment.loadingQrcode') }}</p>
80
+ </div>
81
+ </i>
82
+ <span class="u-skip u-skip-alipay" v-if="isAlipay && skipUrl">
83
+ {{ t('payment.pcAlipay') }}<a :href="skipUrl" target="_blank">{{ t('payment.pcAlipayLink') }}</a>{{ t('payment.pcAlipaySuffix') }}
84
+ </span>
85
+ <span class="u-exp">{{ t('payment.expireTip') }}</span>
86
+ <transition name="fade">
87
+ <el-alert
88
+ class="u-warning"
89
+ v-show="warningVisible"
90
+ :title="t('payment.warningTitle')"
91
+ type="error"
92
+ show-icon
93
+ @close="closeWarning"
94
+ >
95
+ </el-alert>
96
+ </transition>
97
+ </div>
98
+ </div>
99
+ </div>
100
+
101
+ <!-- 底部按钮 -->
102
+ <template #footer v-if="!paymentSuccess">
103
+ <el-button @click="cancel">{{ t('payment.cancel') }}</el-button>
104
+ <el-button type="primary" @click="checkPaymentStatus" :loading="checking">{{ t('payment.completed') }}</el-button>
105
+ </template>
106
+ </el-dialog>
107
+ </template>
108
+
109
+ <script>
110
+ import { Loading, CircleCheck } from '@element-plus/icons-vue';
111
+ import QrcodeVue from "qrcode.vue";
112
+ import { createI18n } from "vue-i18n";
113
+ import enUs from "../../locale/en-us";
114
+ import zhCn from "../../locale/zh-cn";
115
+
116
+ // 创建独立的 i18n 实例
117
+ const getLocale = () => {
118
+ const _val = localStorage.getItem('lang');
119
+ if (!_val) {
120
+ return navigator.language;
121
+ } else {
122
+ return _val;
123
+ }
124
+ }
125
+
126
+ const payI18n = createI18n({
127
+ locale: getLocale(),
128
+ fallbackLocale: "zh-CN",
129
+ messages: {
130
+ "en-US": enUs,
131
+ "zh-CN": zhCn,
132
+ },
133
+ legacy: false, // 使用 Composition API 模式
134
+ warnHtmlInMessage: "off",
135
+ });
136
+
137
+ export default {
138
+ name: "Payment",
139
+ components: {
140
+ Loading,
141
+ CircleCheck,
142
+ QrcodeVue,
143
+ },
144
+ // 使用独立的 i18n 实例
145
+ i18n: payI18n,
146
+ props: {
147
+ // 弹窗可见性
148
+ modelValue: {
149
+ type: Boolean,
150
+ default: false,
151
+ },
152
+ // 弹窗标题
153
+ title: {
154
+ type: String,
155
+ default: payI18n.global.t('payment.title'),
156
+ },
157
+ // 弹窗宽度
158
+ width: {
159
+ type: String,
160
+ default: '50%',
161
+ },
162
+ // 支付方式
163
+ payMode: {
164
+ type: String,
165
+ default: 'wepay',
166
+ },
167
+ // 商品数量
168
+ count: {
169
+ type: Number,
170
+ default: 1,
171
+ },
172
+ // 商品ID
173
+ productId: {
174
+ type: [String, Number],
175
+ required: true,
176
+ },
177
+ // 商品描述
178
+ productDesc: {
179
+ type: String,
180
+ default: '商品支付',
181
+ },
182
+ // 返回URL
183
+ returnUrl: {
184
+ type: String,
185
+ default: '',
186
+ },
187
+ // 订单数据(如有多个商品)
188
+ orderData: {
189
+ type: Object,
190
+ default: null,
191
+ },
192
+ // API 请求函数
193
+ apiRequest: {
194
+ type: Function,
195
+ required: true,
196
+ // 约定: (url, method, data) => Promise
197
+ },
198
+ // 轮询配置
199
+ pollingConfig: {
200
+ type: Object,
201
+ default: () => ({
202
+ orderInterval: 2000, // 订单状态轮询间隔(ms)
203
+ paymentInterval: 3000, // 支付状态轮询间隔(ms)
204
+ maxRetries: 60, // 最大轮询次数
205
+ }),
206
+ },
207
+ },
208
+ emits: ['update:modelValue', 'done', 'cancel', 'payment-success'],
209
+ data() {
210
+ return {
211
+ visible: this.modelValue,
212
+ loading: false,
213
+ loadingText: payI18n.global.t('payment.loading'),
214
+
215
+ // 订单相关
216
+ pendingOrderId: null, // 订单预处理ID
217
+ paymentId: null, // 支付单ID
218
+ price: null, // 支付金额
219
+
220
+ // 支付相关
221
+ payType: this.payMode || 'wepay', // 当前支付方式: wepay/alipay
222
+ qrcode: null, // 支付二维码URL或短链接
223
+ longUrl: null, // 支付宝长链接(用于 iframe)
224
+ skipUrl: null, // 支付宝跳转链接
225
+ paymentSuccess: false, // 支付是否成功
226
+
227
+ // UI 相关
228
+ warningVisible: false, // 警告提示
229
+ checking: false, // 是否正在检查支付状态
230
+
231
+ // 轮询定时器
232
+ orderPollingTimer: null,
233
+ paymentPollingTimer: null,
234
+ pollingRetries: 0,
235
+ };
236
+ },
237
+ computed: {
238
+ isWepay() {
239
+ return this.payType === 'wepay';
240
+ },
241
+ isAlipay() {
242
+ return this.payType === 'alipay';
243
+ },
244
+ // 检测是否为移动设备
245
+ isMobile() {
246
+ return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
247
+ },
248
+ // 实际使用的支付渠道
249
+ actualPayChannel() {
250
+ if (this.payType === 'wepay') {
251
+ return 'wepay';
252
+ }
253
+ // 支付宝根据设备类型选择渠道
254
+ if (this.payType === 'alipay') {
255
+ return this.isMobile ? 'alipay_wap' : 'alipay_pc';
256
+ }
257
+ return this.payType;
258
+ },
259
+ // 是否为 alipay_pc 模式
260
+ isAlipayPc() {
261
+ return this.actualPayChannel === 'alipay_pc';
262
+ },
263
+ params() {
264
+ return {
265
+ pay_type: this.payType,
266
+ product_id: this.productId,
267
+ return_url: this.returnUrl,
268
+ count: this.count || 1,
269
+ };
270
+ },
271
+ },
272
+ watch: {
273
+ // 双向绑定弹窗可见性
274
+ modelValue(val) {
275
+ this.visible = val;
276
+ if (val && !this.qrcode) {
277
+ this.startPaymentProcess();
278
+ }
279
+ },
280
+ visible(val) {
281
+ this.$emit('update:modelValue', val);
282
+ if (!val) {
283
+ // 关闭弹窗时清理定时器
284
+ this.clearAllTimers();
285
+ }
286
+ },
287
+ // 监听支付方式变化
288
+ payMode(val) {
289
+ this.payType = val;
290
+ },
291
+ // 监听参数变化重新创建订单
292
+ params: {
293
+ deep: true,
294
+ handler() {
295
+ if (this.visible) {
296
+ this.startPaymentProcess();
297
+ }
298
+ },
299
+ },
300
+ },
301
+ mounted() {
302
+ // 如果弹窗默认打开,则自动开始支付流程
303
+ if (this.visible) {
304
+ this.startPaymentProcess();
305
+ }
306
+ },
307
+ beforeUnmount() {
308
+ // 清理定时器
309
+ this.clearAllTimers();
310
+ },
311
+ methods: {
312
+ // 翻译函数
313
+ t(key) {
314
+ return payI18n.global.t(key);
315
+ },
316
+
317
+ // 格式化价格
318
+ formatPrice(price) {
319
+ return price / 100;
320
+ },
321
+
322
+ // 开始支付流程
323
+ async startPaymentProcess() {
324
+ await this.createOrder();
325
+ },
326
+
327
+ // 步骤1: 创建订单
328
+ async createOrder() {
329
+ try {
330
+ this.loading = true;
331
+ this.loadingText = payI18n.global.t('payment.loadingCreate');
332
+
333
+ // 准备订单数据
334
+ const orderParams = this.orderData || {
335
+ goods: [
336
+ {
337
+ product_sku_id: ~~this.productId,
338
+ count: this.count,
339
+ },
340
+ ]
341
+ };
342
+
343
+ // 调用下单接口
344
+ const response = await this.apiRequest(
345
+ '/api/client/order/make/batch',
346
+ 'POST',
347
+ orderParams
348
+ );
349
+
350
+ if (response && response.id) {
351
+ this.pendingOrderId = response.id;
352
+
353
+ // 开始轮询订单状态
354
+ this.startOrderPolling();
355
+ } else {
356
+ throw new Error('创建订单失败,未返回订单ID');
357
+ }
358
+ } catch (err) {
359
+ console.error('创建订单失败:', err);
360
+ this.loading = false;
361
+ }
362
+ },
363
+
364
+ // 步骤2: 轮询订单预处理状态
365
+ startOrderPolling() {
366
+ this.loadingText = payI18n.global.t('payment.loadingOrder');
367
+ this.pollingRetries = 0;
368
+
369
+ this.orderPollingTimer = setInterval(async () => {
370
+ try {
371
+ this.pollingRetries++;
372
+
373
+ // 检查是否超过最大重试次数
374
+ if (this.pollingRetries > this.pollingConfig.maxRetries) {
375
+ this.clearAllTimers();
376
+ this.loading = false;
377
+ console.error('订单处理超时');
378
+ return;
379
+ }
380
+
381
+ // 查询订单预处理状态
382
+ const response = await this.apiRequest(
383
+ `/api/client/order/pending/item/${this.pendingOrderId}`,
384
+ 'GET'
385
+ );
386
+
387
+ // status === 2 表示减库存成功,可以进行支付
388
+ if (response && response.status === 2) {
389
+ this.clearTimer('order');
390
+ this.paymentId = response.payment_id;
391
+ this.price = response.total_amount;
392
+
393
+ // 自动获取默认支付方式(微信)的二维码
394
+ await this.getPaymentQrcode();
395
+ } else if (response && response.status === -1) {
396
+ // 订单处理失败
397
+ this.clearAllTimers();
398
+ this.loading = false;
399
+ console.error('订单处理失败:', new Error(response.message || '订单处理失败'));
400
+ }
401
+ } catch (err) {
402
+ console.error('轮询订单状态失败:', err);
403
+ // 继续轮询,不中断
404
+ }
405
+ }, this.pollingConfig.orderInterval);
406
+ },
407
+
408
+ // 支付方式切换
409
+ async onPayTypeChange(newPayType) {
410
+ // 切换支付方式时重新获取二维码
411
+ this.qrcode = null;
412
+ this.longUrl = null;
413
+ this.skipUrl = null;
414
+ await this.getPaymentQrcode();
415
+ },
416
+
417
+ // 步骤3: 获取支付二维码
418
+ async getPaymentQrcode() {
419
+ if (!this.paymentId) {
420
+ return;
421
+ }
422
+
423
+ try {
424
+ // 构建请求 URL,使用实际支付渠道
425
+ let url = `/api/client/payment/item/${this.paymentId}/pay/${this.actualPayChannel}/qrcode`;
426
+
427
+ // 如果是 alipay_pc,添加 qr_pay_mode=4 参数
428
+ if (this.actualPayChannel === 'alipay_pc') {
429
+ url += '?qr_pay_mode=4';
430
+ }
431
+
432
+ // 调用获取支付二维码接口
433
+ const response = await this.apiRequest(url, 'GET');
434
+
435
+ if (response) {
436
+ // 根据支付渠道处理返回数据
437
+ if (this.actualPayChannel === 'alipay_pc') {
438
+ // PC 支付宝使用 long_url 显示 iframe
439
+ this.longUrl = response.long_url || response.longUrl;
440
+ this.qrcode = response.qrcode; // 备用
441
+ } else {
442
+ // 其他渠道使用 qrcode 生成二维码
443
+ this.qrcode = response.qrcode || response;
444
+ this.longUrl = response.long_url || response.longUrl;
445
+ }
446
+
447
+ this.skipUrl = response.skip_url || response.skipUrl; // 支付宝跳转链接
448
+ this.loading = false;
449
+
450
+ this.$emit('qrcode-generated', response);
451
+
452
+ // 开始轮询支付状态
453
+ if (!this.paymentPollingTimer) {
454
+ this.startPaymentPolling();
455
+ }
456
+ } else {
457
+ throw new Error('获取支付二维码失败');
458
+ }
459
+ } catch (err) {
460
+ this.loading = false;
461
+ console.error('获取支付二维码失败:', err);
462
+ }
463
+ },
464
+
465
+ // 步骤4: 轮询支付状态
466
+ startPaymentPolling() {
467
+ this.pollingRetries = 0;
468
+
469
+ this.paymentPollingTimer = setInterval(async () => {
470
+ try {
471
+ this.pollingRetries++;
472
+
473
+ // 检查是否超过最大重试次数
474
+ if (this.pollingRetries > this.pollingConfig.maxRetries) {
475
+ this.clearTimer('payment');
476
+ this.warningVisible = true;
477
+ return;
478
+ }
479
+
480
+ // 查询支付状态
481
+ const response = await this.apiRequest(
482
+ `/api/client/payment/item/${this.paymentId}/simple`,
483
+ 'GET'
484
+ );
485
+
486
+ // 根据实际API返回的支付状态字段判断
487
+ if (response && (response.status === 1)) {
488
+ this.clearTimer('payment');
489
+ this.paymentSuccess = true;
490
+ this.$emit('payment-success', response);
491
+ } else if (response && response.status === 'failed') {
492
+ this.clearTimer('payment');
493
+ this.warningVisible = true;
494
+ console.error('支付失败:', response);
495
+ }
496
+ } catch (err) {
497
+ console.error('轮询支付状态失败:', err);
498
+ // 继续轮询,不中断
499
+ }
500
+ }, this.pollingConfig.paymentInterval);
501
+ },
502
+
503
+ // 手动检查支付状态
504
+ async checkPaymentStatus() {
505
+ if (!this.paymentId) {
506
+ this.$message?.error('无效订单号');
507
+ return;
508
+ }
509
+
510
+ this.checking = true;
511
+ this.warningVisible = false;
512
+
513
+ try {
514
+ const response = await this.apiRequest(
515
+ `/api/client/payment/item/${this.paymentId}/simple`,
516
+ 'GET'
517
+ );
518
+
519
+ if (response && (response.status === 1)) {
520
+ this.clearTimer('payment');
521
+ this.paymentSuccess = true;
522
+ this.$emit('done', response);
523
+
524
+ // 延迟关闭弹窗并刷新
525
+ setTimeout(() => {
526
+ this.visible = false;
527
+ if (typeof location !== 'undefined') {
528
+ location.reload();
529
+ }
530
+ }, 2000);
531
+ } else {
532
+ this.warningVisible = true;
533
+ }
534
+ } catch (err) {
535
+ console.error('检查支付状态失败:', err);
536
+ } finally {
537
+ this.checking = false;
538
+ }
539
+ },
540
+
541
+ // 取消支付
542
+ cancel() {
543
+ this.visible = false;
544
+ this.$emit('cancel');
545
+ },
546
+
547
+ // 关闭警告
548
+ closeWarning() {
549
+ this.warningVisible = false;
550
+ }, // 清理定时器
551
+ clearTimer(type) {
552
+ if (type === 'order' && this.orderPollingTimer) {
553
+ clearInterval(this.orderPollingTimer);
554
+ this.orderPollingTimer = null;
555
+ } else if (type === 'payment' && this.paymentPollingTimer) {
556
+ clearInterval(this.paymentPollingTimer);
557
+ this.paymentPollingTimer = null;
558
+ }
559
+ },
560
+
561
+ clearAllTimers() {
562
+ this.clearTimer('order');
563
+ this.clearTimer('payment');
564
+ },
565
+
566
+ // 重新生成二维码
567
+ retry() {
568
+ this.warningVisible = false;
569
+ this.qrcode = null;
570
+ this.longUrl = null;
571
+ this.skipUrl = null;
572
+ this.pendingOrderId = null;
573
+ this.paymentId = null;
574
+ this.price = null;
575
+ this.paymentSuccess = false;
576
+ this.pollingRetries = 0;
577
+ this.loading = true;
578
+
579
+ this.clearAllTimers();
580
+ this.startPaymentProcess();
581
+ },
582
+ },
583
+ };
584
+ </script>
585
+
586
+ <style lang="less">
587
+ @import "../../assets/css/var.less";
588
+
589
+ .c-pay-pop {
590
+
591
+ :deep(.el-dialog) {
592
+ max-width: 980px;
593
+ }
594
+
595
+ :deep(.el-dialog__body) {
596
+ padding: 0 10px;
597
+ }
598
+
599
+ .loading-container,
600
+ .success-container {
601
+ text-align: center;
602
+ padding: 48px 24px;
603
+
604
+ .el-icon {
605
+ font-size: 48px;
606
+ margin-bottom: 16px;
607
+ }
608
+
609
+ p {
610
+ font-size: 16px;
611
+ color: #606266;
612
+ margin: 16px 0;
613
+ }
614
+ }
615
+
616
+ .u-btns {
617
+ text-align: center;
618
+ }
619
+
620
+ .c-pay-pop-box {
621
+ padding: 10px;
622
+
623
+ .c-pay-pop-tab {
624
+ :deep(.el-tabs__header) {
625
+ margin: 0;
626
+ }
627
+
628
+ :deep(.el-tabs__item) {
629
+ height: 60px;
630
+ line-height: 60px;
631
+ font-size: 16px;
632
+ }
633
+
634
+ :deep(.el-tabs--card > .el-tabs__header .el-tabs__item.is-active) {
635
+ background-color: #e6f0fb;
636
+ border-bottom: none;
637
+ }
638
+
639
+ .u-tab {
640
+ display: flex;
641
+ align-items: center;
642
+ color: @color;
643
+
644
+ img {
645
+ width: 24px;
646
+ height: 24px;
647
+ vertical-align: middle;
648
+ margin-right: 10px;
649
+ }
650
+
651
+ em {
652
+ font-size: 12px;
653
+ color: #999;
654
+ font-style: normal;
655
+ margin-left: 4px;
656
+ border: 1px solid #c0c4cc;
657
+ padding: 0 5px;
658
+ line-height: 14px;
659
+ background-color: #fff;
660
+ border-radius: 1px;
661
+ }
662
+ }
663
+ }
664
+
665
+ .c-pay-pop-content {
666
+ padding: 10px;
667
+
668
+ .u-title {
669
+ text-align: center;
670
+ font-size: 18px;
671
+ color: @color;
672
+ margin: 10px 0 5px 0;
673
+ font-weight: 500;
674
+ }
675
+
676
+ .u-price {
677
+ text-align: center;
678
+ font-size: 24px;
679
+ margin-bottom: 10px;
680
+
681
+ b {
682
+ font-weight: bold;
683
+ color: #c00;
684
+ }
685
+
686
+ em {
687
+ font-size: 15px;
688
+ font-style: normal;
689
+ margin-left: 5px;
690
+ }
691
+ }
692
+
693
+ .u-paybox {
694
+ text-align: center;
695
+
696
+ .u-qrcode {
697
+ width: 300px;
698
+ height: 300px;
699
+ display: block;
700
+ margin: 0 auto;
701
+ padding: 0;
702
+ background: #fff;
703
+ // border: 1px solid #dcdfe6;
704
+ // border-radius: 4px;
705
+
706
+ .u-pic {
707
+ width: 100%;
708
+ height: 100%;
709
+ display: block;
710
+ }
711
+
712
+ .u-iframe {
713
+ display: block;
714
+ border: none;
715
+ width: 300px;
716
+ height: 300px;
717
+ }
718
+
719
+ .u-success-inline {
720
+ display: flex;
721
+ flex-direction: column;
722
+ align-items: center;
723
+ justify-content: center;
724
+ height: 100%;
725
+ color: #67c23a;
726
+
727
+ .el-icon {
728
+ margin-bottom: 16px;
729
+ }
730
+
731
+ p {
732
+ font-size: 18px;
733
+ font-weight: 500;
734
+ margin: 0;
735
+ }
736
+ }
737
+
738
+ .u-loading {
739
+ display: flex;
740
+ flex-direction: column;
741
+ align-items: center;
742
+ justify-content: center;
743
+ height: 100%;
744
+ color: #909399;
745
+
746
+ .el-icon {
747
+ font-size: 32px;
748
+ margin-bottom: 12px;
749
+ }
750
+
751
+ p {
752
+ font-size: 14px;
753
+ margin: 0;
754
+ }
755
+ }
756
+
757
+ // &.u-wechat {
758
+ // border-color: #09bb07;
759
+ // }
760
+
761
+ // &.u-alipay {
762
+ // border-color: #1677ff;
763
+ // }
764
+ }
765
+
766
+ .u-skip {
767
+ display: block;
768
+ margin-top: 10px;
769
+ font-size: 14px;
770
+ color: #606266;
771
+
772
+ a {
773
+ color: @color-link;
774
+ text-decoration: none;
775
+
776
+ &:hover {
777
+ text-decoration: underline;
778
+ }
779
+ }
780
+ }
781
+
782
+ .u-exp {
783
+ color: #fba524;
784
+ display: block;
785
+ text-align: center;
786
+ font-size: 12px;
787
+ margin-top: 10px;
788
+ }
789
+
790
+ .u-warning {
791
+ width: 260px;
792
+ max-width: 100%;
793
+ margin: 20px auto 0 auto;
794
+ }
795
+ }
796
+ }
797
+ }
798
+ }
799
+
800
+ // Fade 过渡动画
801
+ .fade-enter-active,
802
+ .fade-leave-active {
803
+ transition: opacity 0.5s;
804
+ }
805
+
806
+ .fade-enter-from,
807
+ .fade-leave-to {
808
+ opacity: 0;
809
+ }
810
+
811
+ // 移动端适配
812
+ @media screen and (max-width: @phone) {
813
+ .c-payment {
814
+ width: 100% !important;
815
+ max-width: 100%;
816
+
817
+ .c-pay-pop-box {
818
+ border-radius: 0;
819
+ box-shadow: none;
820
+ max-height: 100%;
821
+ overflow: auto;
822
+
823
+ .c-pay-pop-content {
824
+ .u-qrcode {
825
+ width: 100%;
826
+ max-width: 260px;
827
+ }
828
+
829
+ .u-warning {
830
+ width: 100%;
831
+ max-width: 260px;
832
+ }
833
+ }
834
+ }
835
+ }
836
+ }
837
+ </style>