@uxda/appkit 4.3.8 → 4.3.12

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.
Files changed (135) hide show
  1. package/.eslintrc.mjs +7 -7
  2. package/COMPONENT_USAGE.md +1523 -1523
  3. package/PROJECT_DOCS.md +142 -142
  4. package/README.md +187 -187
  5. package/babel.config.js +12 -12
  6. package/dist/appkit.css +63 -15
  7. package/dist/index.js +881 -259
  8. package/package.json +79 -79
  9. package/project.config.json +15 -15
  10. package/project.tt.json +13 -13
  11. package/rollup.config.mjs +78 -78
  12. package/src/Appkit.ts +72 -72
  13. package/src/balance/api/endpoints.ts +133 -133
  14. package/src/balance/api/index.ts +118 -118
  15. package/src/balance/components/AccountView.vue +770 -770
  16. package/src/balance/components/BalanceCard.vue +210 -210
  17. package/src/balance/components/BalanceReminder.vue +84 -84
  18. package/src/balance/components/ConsumptionFilter.vue +218 -218
  19. package/src/balance/components/ConsumptionRules.vue +68 -68
  20. package/src/balance/components/DateFilter.vue +259 -259
  21. package/src/balance/components/DateRange.vue +111 -111
  22. package/src/balance/components/ListFilter.vue +62 -62
  23. package/src/balance/components/ListFilterPicker.vue +191 -191
  24. package/src/balance/components/PromoterCard.vue +308 -307
  25. package/src/balance/components/SecondBalance.vue +77 -77
  26. package/src/balance/components/Tip.vue +45 -45
  27. package/src/balance/components/index.ts +8 -8
  28. package/src/balance/types.ts +99 -99
  29. package/src/components/bt-cropper/index.vue +730 -730
  30. package/src/components/bt-cropper/utils/calcCropper.js +42 -42
  31. package/src/components/bt-cropper/utils/calcImagePosition.js +23 -23
  32. package/src/components/bt-cropper/utils/calcImageSize.js +37 -37
  33. package/src/components/bt-cropper/utils/calcPointDistance.js +12 -12
  34. package/src/components/bt-cropper/utils/calcRightAndBottom.js +7 -7
  35. package/src/components/bt-cropper/utils/ratio.js +3 -3
  36. package/src/components/bt-cropper/utils/tools.js +25 -25
  37. package/src/components/dd-area/index.vue +225 -225
  38. package/src/components/dd-icon/doc.md +21 -21
  39. package/src/components/dd-icon/index.vue +23 -23
  40. package/src/components/dd-notice-bar/index.vue +78 -78
  41. package/src/components/dd-search/doc.md +34 -34
  42. package/src/components/dd-search/index.vue +168 -168
  43. package/src/components/dd-selector/index.vue +124 -124
  44. package/src/components/dd-skeleton/doc.md +19 -19
  45. package/src/components/dd-skeleton/index.vue +36 -36
  46. package/src/global.ts +6 -6
  47. package/src/index.ts +101 -101
  48. package/src/main.scss +1 -1
  49. package/src/notice/api/endpoints.ts +54 -54
  50. package/src/notice/api/index.ts +121 -121
  51. package/src/notice/components/NoticeBanner.vue +247 -247
  52. package/src/notice/components/NoticeEntry.vue +99 -99
  53. package/src/notice/components/NoticeList.vue +311 -311
  54. package/src/notice/components/NoticeList2.vue +401 -400
  55. package/src/notice/components/NoticePopup.vue +163 -163
  56. package/src/notice/components/index.ts +6 -6
  57. package/src/notice/components/useCommonList.ts +87 -86
  58. package/src/notice/components/useNotice.ts +35 -35
  59. package/src/notice/index.ts +1 -1
  60. package/src/notice/types.ts +25 -25
  61. package/src/payment/api/config.ts +7 -7
  62. package/src/payment/api/endpoints.ts +98 -96
  63. package/src/payment/api/index.ts +108 -107
  64. package/src/payment/components/AmountPicker.vue +90 -90
  65. package/src/payment/components/RechargeResult.vue +68 -69
  66. package/src/payment/components/RechargeView.vue +195 -191
  67. package/src/payment/components/RightsPicker.vue +105 -105
  68. package/src/payment/components/TradeView.vue +573 -363
  69. package/src/payment/components/UserAgreement.vue +234 -234
  70. package/src/payment/components/index.ts +22 -22
  71. package/src/payment/index.ts +5 -5
  72. package/src/payment/services/index.ts +16 -16
  73. package/src/payment/services/invoke-recharge.ts +25 -25
  74. package/src/payment/services/request-payment.ts +132 -130
  75. package/src/payment/types.ts +34 -33
  76. package/src/register/components/SelfRegistration.vue +233 -233
  77. package/src/register/components/index.ts +2 -2
  78. package/src/scenarios/components/SharePoster.vue +364 -364
  79. package/src/scenarios/components/index.ts +2 -2
  80. package/src/scenarios/components/poster-paste.vue +93 -93
  81. package/src/scenarios/components/share-poster.md +273 -273
  82. package/src/shared/components/AppDrawer.vue +53 -53
  83. package/src/shared/components/AppVerify.vue +137 -128
  84. package/src/shared/components/DeviceVersion.vue +78 -78
  85. package/src/shared/components/EmptyView.vue +33 -33
  86. package/src/shared/components/OcrBank.vue +202 -0
  87. package/src/shared/components/OcrBusinessLicense.vue +120 -137
  88. package/src/shared/components/OcrIcon.vue +267 -229
  89. package/src/shared/components/OcrInvoice.vue +322 -0
  90. package/src/shared/components/PageHeader.vue +84 -84
  91. package/src/shared/components/index.ts +10 -8
  92. package/src/shared/composables/index.ts +10 -9
  93. package/src/shared/composables/useAmount.ts +46 -46
  94. package/src/shared/composables/useCompress.ts +64 -0
  95. package/src/shared/composables/useCountdown.ts +46 -46
  96. package/src/shared/composables/useCrypto.ts +76 -76
  97. package/src/shared/composables/useDeviceEnv.ts +26 -26
  98. package/src/shared/composables/useDragBox.ts +97 -97
  99. package/src/shared/composables/useEncode.ts +43 -43
  100. package/src/shared/composables/useLogger.ts +144 -144
  101. package/src/shared/composables/useSafeArea.ts +46 -46
  102. package/src/shared/composables/useTabbar.ts +24 -24
  103. package/src/shared/composables/useUpload.ts +106 -61
  104. package/src/shared/composables/useValidator.ts +32 -32
  105. package/src/shared/composables/useWxAuth.ts +48 -48
  106. package/src/shared/http/Http.ts +149 -148
  107. package/src/shared/http/index.ts +1 -1
  108. package/src/shared/http/types.ts +163 -163
  109. package/src/shared/index.ts +9 -9
  110. package/src/shared/tracking/directives/index.ts +40 -40
  111. package/src/shared/tracking/examples/page-tracking-template.vue +27 -27
  112. package/src/shared/tracking/tracking-sdk.ts +0 -1
  113. package/src/shared/weixin/index.ts +9 -9
  114. package/src/shared/weixin/jssdk.ts +104 -103
  115. package/src/shared/weixin/payment.ts +38 -38
  116. package/src/styles/vars.scss +3 -3
  117. package/src/user/api/endpoints.ts +17 -17
  118. package/src/user/api/index.ts +123 -123
  119. package/src/user/components/LoginSetting.vue +114 -114
  120. package/src/user/components/UserAuth.vue +218 -218
  121. package/src/user/components/UserBinding.vue +277 -277
  122. package/src/user/components/UserBindingSuccess.vue +80 -80
  123. package/src/user/components/UserEntry.vue +139 -139
  124. package/src/user/components/UserFeedback.vue +428 -427
  125. package/src/user/components/UserFeedbackEntry.vue +175 -175
  126. package/src/user/components/UserHeadCrop.vue +65 -65
  127. package/src/user/components/UserInfo.vue +711 -709
  128. package/src/user/components/UserResourceEmpty.vue +75 -75
  129. package/src/user/components/index.ts +23 -23
  130. package/src/user/index.ts +1 -1
  131. package/src/utils/utils.ts +33 -33
  132. package/tsconfig.json +30 -30
  133. package/types/global.d.ts +24 -22
  134. package/types/vue.d.ts +10 -10
  135. package/dist/assets/asset-DcH8Kg-2 +0 -1
@@ -1,363 +1,573 @@
1
- <template>
2
- <view class="view recharge-view2">
3
- <view class="flex-grow">
4
- <rights-picker :items="amounts" :selected="state.selected" @change="onAmountSelect" />
5
- <div class="bean-buy" v-if="amounts[state.selected]">
6
- <div class="left">
7
- <div class="title">使用云豆支付</div>
8
- <div class="amount" v-if="!selectBean">余额 {{ formatAmount(balance || 0) }}</div>
9
- <div class="amount" v-else>扣减后余额 {{ formatAmount(balance - amounts[state.selected].paymentAmount) }}</div>
10
- </div>
11
- <div class="right" v-if="balance >= amounts[state.selected].paymentAmount" @click="selectBean = !selectBean">
12
- <div class="amount">-{{ formatAmount(amounts[state.selected].paymentAmount || 0) }}</div>
13
- <img class="icon"
14
- :src="selectBean ? 'https://cdn.ddjf.com/static/images/appkit/select.svg' : 'https://cdn.ddjf.com/static/images/appkit/not-select.svg'" />
15
- </div>
16
- </div>
17
-
18
-
19
- <slot name="banner"></slot>
20
- </view>
21
-
22
- <view class="amount-footer">
23
- <view class="agreement" v-if="!selectBean">
24
- <nut-checkbox v-model="state.agreed">我已阅读并同意<a v-track-click class="link inline"
25
- @click="onAgreementLinkClick">《大道云平台云豆充值服务协议》</a></nut-checkbox>
26
- </view>
27
- <div class="buy-amount">
28
- <div class="left">
29
- 待支付:
30
- <span class="amount">
31
- <i>¥</i>{{ formatAmount(currentAmount) }}
32
- </span>
33
- </div>
34
- <nut-button block shape="square" :loading="state.buttonLoading" v-track-click @click="onPayClick"
35
- class="recharge-button">购买</nut-button>
36
- </div>
37
- </view>
38
- <nut-dialog title="确认购买" custom-class="trade-dialog" v-model:visible="showDialog" @cancel="showDialog = !showDialog"
39
- @ok="beanPay">
40
- <template v-if="amounts[state.selected]">
41
- <div class="item">云豆扣减:{{ formatAmount(amounts[state.selected].paymentAmount || 0) }}</div>
42
- <div class="item">权益增加:{{ formatAmount(amounts[state.selected].priceRightNum || 0) }}笔</div>
43
- <div class="item">扣减后云豆余额:{{ formatAmount(balance - amounts[state.selected].paymentAmount) }}</div>
44
- </template>
45
- </nut-dialog>
46
- </view>
47
- </template>
48
-
49
- <script lang="ts" setup>
50
- import { computed, onMounted, reactive, ref } from 'vue'
51
- import RightsPicker, { Amount } from './RightsPicker.vue'
52
- import { endpoints, useHttp } from '../api'
53
- import { requestBrandWCPayByBean, requestPaymentByBean } from '../services'
54
- import Taro, { showToast, useRouter } from '@tarojs/taro'
55
- import { useAmount } from '../../shared/composables/useAmount'
56
- import { isWechat } from '../../shared/composables/useDeviceEnv'
57
-
58
- // 充值用户界面
59
- // 配置了必须的属性后
60
- // 自动获取支付套餐包列表
61
- // 并发起微信支付
62
- export interface RechargeViewProps {
63
- /**
64
- * header头中的appcode,一般情况下与app参数一致,当无应用权限时,此参数未空
65
- **/
66
- headerApp: string,
67
- /**
68
- * 应用
69
- **/
70
- app: string,
71
- /**
72
- * 充值场景
73
- */
74
- // stage?: string, // 这个参数暂时不用
75
- /**
76
- * 租户
77
- */
78
- tenant: string,
79
- /**
80
- * h5支付完成后跳转地址
81
- */
82
- payFinishJumpUrl?: ''
83
- }
84
-
85
- const props = defineProps<RechargeViewProps>()
86
- const { formatAmount } = useAmount()
87
- const { params } = useRouter()
88
-
89
- const emit = defineEmits<{
90
- (event: 'complete', value: { result: boolean, type: string }): void,
91
- (event: 'agree'): void,
92
- }>()
93
-
94
- const state = reactive({
95
- agreed: false,
96
- selected: 0,
97
- // agreementOpen: false,
98
- buttonLoading: false,
99
- })
100
-
101
-
102
- const balance = ref<number>(0)
103
- const amounts = ref<Amount[]>([])
104
- const selectBean = ref<boolean>(false)
105
-
106
- const onAgreementLinkClick = (e) => {
107
- e.preventDefault()
108
- e.stopImmediatePropagation()
109
- emit('agree')
110
- // state.agreementOpen = true
111
- }
112
-
113
- const onAmountSelect = (selected: number) => {
114
- state.selected = selected
115
- selectBean.value = false
116
- }
117
-
118
- const currentAmount = computed(() => {
119
- return amounts.value[state.selected] && !selectBean.value ? amounts.value[state.selected].paymentAmount : 0
120
- })
121
-
122
- onMounted(() => {
123
- const $http = useHttp({ Appcode: props.headerApp, Tenant: props.tenant })
124
- $http.get<any[]>(endpoints.获取增值权益类目, {
125
- rightCode: props.app === 'corporateStar' ? 'riskQueryCompany' : 'riskQueryMulti',
126
- }).then((res: any) => {
127
- balance.value = res.balance
128
- amounts.value = res.paymentCaseConfigVOS
129
- })
130
- })
131
-
132
- // 云豆支付
133
- const showDialog = ref<boolean>(false)
134
- async function beanPay() {
135
- const $http = useHttp({ Appcode: props.headerApp, Tenant: props.tenant })
136
- $http.post(`/payment/paymentCaseConfig/purchase/${amounts.value[state.selected].id}`).then((response: any) => {
137
- if (response) {
138
- showDialog.value = false
139
- emit('complete', { result: response, type: 'bean' })
140
- } else {
141
- showToast({
142
- title: response.message,
143
- icon: 'none',
144
- })
145
- }
146
- })
147
- }
148
-
149
-
150
- const onPayClick = () => {
151
- // 用云豆支付
152
- if (selectBean.value) {
153
- showDialog.value = true
154
- return
155
- }
156
-
157
- // 微信支付
158
- if (!selectBean.value && !state.agreed) {
159
- showToast({
160
- title: '请勾选《大道云平台云豆充值协议》',
161
- icon: 'none',
162
- })
163
- return false
164
- }
165
- state.buttonLoading = true
166
-
167
- if (Taro.getEnv() === 'WEB') {
168
- if (!isWechat()) {
169
- showToast({
170
- title: '请使用微信浏览器打开',
171
- icon: 'none',
172
- })
173
- state.buttonLoading = false
174
- return false
175
- }
176
- requestBrandWCPayByBean({
177
- caseConfigId: amounts.value[state.selected].id,
178
- amount: amounts.value[state.selected].paymentAmount,
179
- app: 'loankitMp',
180
- tenant: props.tenant,
181
- accountAuthFlag: false,
182
- channelCode: 'centergzh',
183
- payFinishJumpUrl: props.payFinishJumpUrl,
184
- fromMini: !!params.from
185
- }).then(result => {
186
- console.log(result, '------requestBrandWCPay')
187
- state.buttonLoading = false
188
- if (typeof result === 'boolean' && result) {
189
- window.location.href = props.payFinishJumpUrl as string
190
- } else {
191
- emit('complete', { result, type: 'wePay' })
192
- }
193
- })
194
- } else {
195
- wx.login({
196
- success({ code }: { code: string }) {
197
- requestPaymentByBean({
198
- caseConfigId: amounts.value[state.selected].id,
199
- amount: amounts.value[state.selected].paymentAmount,
200
- app: props.app,
201
- tenant: props.tenant,
202
- user: code,
203
- }, props.headerApp).then(result => {
204
- state.buttonLoading = false
205
- if (result) {
206
- emit('complete', { result: true, type: 'wePay' })
207
- }
208
- })
209
- }
210
- })
211
- }
212
- }
213
- </script>
214
-
215
- <style lang="scss">
216
- .recharge-view2 {
217
- height: 100%;
218
- display: flex;
219
- flex-direction: column;
220
- --nut-primary-color: #017fff;
221
-
222
- .flex-grow {
223
- flex-grow: 1;
224
- }
225
-
226
- .bean-buy {
227
- margin: 0 15px;
228
- padding: 10px;
229
- background: #FFFBF3;
230
- border-radius: 5px;
231
- display: flex;
232
- justify-content: space-between;
233
- align-items: center;
234
-
235
- .left {
236
- .title {
237
- color: #FD6701;
238
- font-size: 14px;
239
- font-weight: 600;
240
- line-height: 20px;
241
- margin-bottom: 6px;
242
- }
243
-
244
- .amount {
245
- color: #353535;
246
- font-size: 13px;
247
- line-height: 16px;
248
- background-image: url('https://cdn.ddjf.com/static/images/appkit/yundou.png');
249
- background-repeat: no-repeat;
250
- background-size: 16px 16px;
251
- padding-left: 24px;
252
- }
253
- }
254
-
255
- .right {
256
- display: flex;
257
- align-items: center;
258
-
259
- .amount {
260
- color: #353535;
261
- font-size: 15px;
262
- line-height: 20px;
263
- margin-right: 10px;
264
- }
265
-
266
- .icon {
267
- display: block;
268
- width: 16px;
269
- height: 16px;
270
- font-size: 0;
271
- }
272
- }
273
- }
274
-
275
- .amount-footer {
276
- padding: 10px 0;
277
- padding-bottom: 20px;
278
-
279
- .agreement {
280
- font-size: 12px;
281
- display: flex;
282
- justify-content: center;
283
- align-items: cebter;
284
- height: 40px;
285
- }
286
-
287
- .buy-amount {
288
- display: flex;
289
- justify-content: space-between;
290
- align-items: center;
291
- padding: 0 10px;
292
- border-radius: 0px;
293
- box-shadow: 0px -5px 14px -5px rgba(0, 0, 0, 0.1);
294
-
295
- /* 上边框阴影 */
296
- .left {
297
- width: 70%;
298
- color: #353535;
299
- font-size: 13px;
300
-
301
- .amount {
302
- color: #FD6701;
303
- font-size: 20px;
304
- font-weight: 600;
305
-
306
- i {
307
- font-size: 14px;
308
- font-style: normal;
309
- }
310
- }
311
- }
312
-
313
- .recharge-button {
314
- background: linear-gradient(90deg, #FFEBC1 0%, #FFD7A7 52.29%, #FFB875 100%);
315
- color: #353535;
316
- margin: 12px 0;
317
- border: 0;
318
- border-radius: 8px;
319
- flex: 1;
320
- }
321
- }
322
-
323
- .nut-checkbox {
324
- line-height: 40px;
325
- }
326
-
327
- .nut-checkbox__label {
328
- margin-left: 8px;
329
- flex: flex;
330
- font-size: 12px;
331
- }
332
-
333
- .link {
334
- display: inline;
335
- color: #FD6701;
336
- }
337
- }
338
- }
339
-
340
- .trade-dialog {
341
- .nut-dialog__header {
342
- font-size: 16px;
343
- color: #262626
344
- }
345
-
346
- .item {
347
- font-size: 14px;
348
- color: #666666;
349
- line-height: 21px;
350
- }
351
-
352
- .nut-dialog__footer-cancel {
353
- color: #353535 !important;
354
- border-color: #CCCCCC !important;
355
- }
356
-
357
- .nut-dialog__footer-ok {
358
- border: none;
359
- color: #353535;
360
- background: linear-gradient(90deg, #FFEBC1 0%, #FFB875 100%);
361
- }
362
- }
363
- </style>
1
+ <template>
2
+ <view class="view recharge-view2">
3
+ <view class="flex-grow">
4
+ <rights-picker
5
+ :items="amounts"
6
+ :selected="state.selected"
7
+ @change="onAmountSelect"
8
+ />
9
+ <div class="bean-buy" v-if="amounts[state.selected]">
10
+ <div class="left">
11
+ <div class="title">使用云豆支付</div>
12
+ <div class="amount" v-if="!selectBean || isCombinedPayment">
13
+ 余额 {{ formatAmount(balance || 0) }}
14
+ </div>
15
+ <div class="amount" v-else>
16
+ 扣减后余额
17
+ {{ formatAmount(balance - amounts[state.selected].paymentAmount) }}
18
+ </div>
19
+ </div>
20
+ <div class="right" @click="selectBean = !selectBean">
21
+ <div class="amount">
22
+ -{{ formatAmount(amounts[state.selected].paymentAmount || 0) }}
23
+ </div>
24
+ <img
25
+ class="icon"
26
+ :src="
27
+ selectBean
28
+ ? 'https://cdn.ddjf.com/static/images/appkit/select.svg'
29
+ : 'https://cdn.ddjf.com/static/images/appkit/not-select.svg'
30
+ "
31
+ />
32
+ </div>
33
+
34
+ <div class="balance-warning" v-if="isCombinedPayment">
35
+ 云豆余额不足,还需额外支付{{ formatAmount(extraPaymentAmount) }}元
36
+ </div>
37
+ </div>
38
+
39
+ <div class="balance-warning-tip" v-if="isCombinedPayment">
40
+ 请在支付完成前确保元豆余额不被消耗,否则本次权益可能购买失败
41
+ </div>
42
+
43
+ <slot name="banner"></slot>
44
+ </view>
45
+
46
+ <view class="amount-footer">
47
+ <view class="agreement" v-if="!selectBean || isCombinedPayment">
48
+ <nut-checkbox v-model="state.agreed"
49
+ >我已阅读并同意<a
50
+ v-track-click
51
+ class="link inline"
52
+ @click="onAgreementLinkClick"
53
+ >《大道云平台云豆充值服务协议》</a
54
+ ></nut-checkbox
55
+ >
56
+ </view>
57
+ <div class="buy-amount">
58
+ <div class="left">
59
+ 待支付:
60
+ <span class="amount">
61
+ <i>¥</i>{{ formatAmount(currentAmount) }}
62
+ </span>
63
+ </div>
64
+ <nut-button
65
+ block
66
+ shape="square"
67
+ :loading="state.buttonLoading"
68
+ v-track-click
69
+ @click="onPayClick"
70
+ class="recharge-button"
71
+ >购买</nut-button
72
+ >
73
+ </div>
74
+ </view>
75
+ <nut-dialog
76
+ title="确认购买"
77
+ custom-class="trade-dialog"
78
+ v-model:visible="showDialog"
79
+ @cancel="showDialog = !showDialog"
80
+ @ok="beanPay"
81
+ >
82
+ <template v-if="amounts[state.selected]">
83
+ <div class="item">
84
+ 云豆扣减:{{
85
+ formatAmount(amounts[state.selected].paymentAmount || 0)
86
+ }}
87
+ </div>
88
+ <div class="item">
89
+ 权益增加:{{
90
+ formatAmount(amounts[state.selected].priceRightNum || 0)
91
+ }}笔
92
+ </div>
93
+ <div class="item">
94
+ 扣减后云豆余额:{{
95
+ formatAmount(balance - amounts[state.selected].paymentAmount)
96
+ }}
97
+ </div>
98
+ </template>
99
+ </nut-dialog>
100
+ </view>
101
+ </template>
102
+
103
+ <script lang="ts" setup>
104
+ import { computed, onMounted, reactive, ref } from "vue";
105
+ import RightsPicker, { Amount } from "./RightsPicker.vue";
106
+ import { endpoints, useHttp } from "../api";
107
+ import { endpoints as balanceEndpoints } from "../../balance/api";
108
+ import { requestBrandWCPayByBean, requestPaymentByBean } from "../services";
109
+ import Taro, { showToast, useRouter, showModal } from "@tarojs/taro";
110
+ import { useAmount } from "../../shared/composables/useAmount";
111
+ import { isWechat } from "../../shared/composables/useDeviceEnv";
112
+
113
+ // 充值用户界面
114
+ // 配置了必须的属性后
115
+ // 自动获取支付套餐包列表
116
+ // 并发起微信支付
117
+ export interface RechargeViewProps {
118
+ /**
119
+ * header头中的appcode,一般情况下与app参数一致,当无应用权限时,此参数未空
120
+ **/
121
+ headerApp: string;
122
+ /**
123
+ * 应用
124
+ **/
125
+ app: string;
126
+ /**
127
+ * 充值场景
128
+ */
129
+ // stage?: string, // 这个参数暂时不用
130
+ /**
131
+ * 租户
132
+ */
133
+ tenant: string;
134
+ /**
135
+ * h5支付完成后跳转地址
136
+ */
137
+ payFinishJumpUrl?: "";
138
+ /**
139
+ * 所有应用
140
+ **/
141
+ apps?: string;
142
+ }
143
+
144
+ const props = defineProps<RechargeViewProps>();
145
+ const { formatAmount } = useAmount();
146
+ const { params } = useRouter();
147
+
148
+ const emit = defineEmits<{
149
+ (event: 'complete', value: { result: boolean, type: string }): void,
150
+ (event: 'agree'): void,
151
+ (event: 'loaded'): void,
152
+ }>()
153
+
154
+ const state = reactive({
155
+ agreed: false,
156
+ selected: 0,
157
+ // agreementOpen: false,
158
+ buttonLoading: false,
159
+ });
160
+
161
+ const balance = ref<number>(0);
162
+ const amounts = ref<Amount[]>([]);
163
+ const selectBean = ref<boolean>(false);
164
+
165
+ const onAgreementLinkClick = (e) => {
166
+ e.preventDefault();
167
+ e.stopImmediatePropagation();
168
+ emit("agree");
169
+ // state.agreementOpen = true
170
+ };
171
+
172
+ const onAmountSelect = (selected: number) => {
173
+ state.selected = selected;
174
+ selectBean.value = false;
175
+ };
176
+
177
+ // 计算额外支付金额(当云豆余额不足时)
178
+ const extraPaymentAmount = computed(() => {
179
+ if (!selectBean.value || !amounts.value[state.selected]) {
180
+ return 0;
181
+ }
182
+ const paymentAmount = amounts.value[state.selected].paymentAmount || 0;
183
+ const currentBalance = balance.value || 0;
184
+ return Math.max(0, paymentAmount - currentBalance);
185
+ });
186
+
187
+ // 计算待支付金额
188
+ const currentAmount = computed(() => {
189
+ if (!amounts.value[state.selected]) {
190
+ return 0;
191
+ }
192
+
193
+ // 如果选择了云豆支付
194
+ if (selectBean.value) {
195
+ // 如果余额不足,返回额外需要支付的金额
196
+ if (balance.value < amounts.value[state.selected].paymentAmount) {
197
+ return extraPaymentAmount.value;
198
+ }
199
+ // 如果余额充足,返回0(全部用云豆支付)
200
+ return 0;
201
+ }
202
+
203
+ // 如果没有选择云豆支付,返回全额
204
+ return amounts.value[state.selected].paymentAmount || 0;
205
+ });
206
+
207
+ // 判断是否为组合支付
208
+ const isCombinedPayment = computed(() => {
209
+ return (
210
+ selectBean.value &&
211
+ amounts.value[state.selected] &&
212
+ balance.value < amounts.value[state.selected].paymentAmount
213
+ );
214
+ });
215
+
216
+ onMounted(() => {
217
+ const $http = useHttp({ Appcode: props.headerApp, Tenant: props.tenant });
218
+ $http
219
+ .get<any[]>(endpoints.获取增值权益类目, {
220
+ rightCode:
221
+ props.app === "corporateStar" ? "riskQueryCompany" : "riskQueryMulti",
222
+ })
223
+ .then((res: any) => {
224
+ balance.value = res.balance;
225
+ amounts.value = res.paymentCaseConfigVOS;
226
+ emit("loaded");
227
+ });
228
+ });
229
+
230
+ // 云豆支付对话框
231
+ const showDialog = ref<boolean>(false);
232
+
233
+ // 处理确认支付(纯云豆支付)
234
+ async function beanPay() {
235
+ const $http = useHttp({ Appcode: props.headerApp, Tenant: props.tenant });
236
+ try {
237
+ const response: any = await $http.post(
238
+ `/payment/paymentCaseConfig/purchase/${amounts.value[state.selected].id}`
239
+ );
240
+ if (response) {
241
+ showDialog.value = false;
242
+ emit("complete", { result: response, type: "bean" });
243
+ } else {
244
+ showToast({
245
+ title: (response as any)?.message || "支付失败",
246
+ icon: "none",
247
+ });
248
+ }
249
+ } catch (error: any) {
250
+ showToast({
251
+ title: error?.message || "支付失败",
252
+ icon: "none",
253
+ });
254
+ }
255
+ }
256
+
257
+ // 执行微信支付(用于组合支付或纯微信支付)
258
+ function proceedWechatPayment() {
259
+ if (!state.agreed) {
260
+ showToast({
261
+ title: "请勾选《大道云平台云豆充值协议》",
262
+ icon: "none",
263
+ });
264
+ return false;
265
+ }
266
+
267
+ state.buttonLoading = true;
268
+
269
+ if (Taro.getEnv() === "WEB") {
270
+ if (!isWechat()) {
271
+ showToast({
272
+ title: "请使用微信浏览器打开",
273
+ icon: "none",
274
+ });
275
+ state.buttonLoading = false;
276
+ return false;
277
+ }
278
+ // 组合支付或纯微信支付:传递caseConfigId和amount,后端会自动处理云豆扣减
279
+ requestBrandWCPayByBean({
280
+ caseConfigId: amounts.value[state.selected].id,
281
+ amount: currentAmount.value,
282
+ app: "loankitMp",
283
+ tenant: props.tenant,
284
+ accountAuthFlag: false,
285
+ channelCode: "centergzh",
286
+ payFinishJumpUrl: props.payFinishJumpUrl,
287
+ fromMini: !!params.from,
288
+ useCloudBean: isCombinedPayment.value
289
+ })
290
+ .then((result) => {
291
+ state.buttonLoading = false;
292
+ if (typeof result === "boolean" && result) {
293
+ window.location.href = props.payFinishJumpUrl as string;
294
+ } else {
295
+ emit("complete", {
296
+ result,
297
+ type: isCombinedPayment.value ? "combined" : "wePay",
298
+ });
299
+ }
300
+ })
301
+ .catch((error) => {
302
+ state.buttonLoading = false;
303
+ showToast({
304
+ title: error.message || "支付失败",
305
+ icon: "none",
306
+ });
307
+ });
308
+ } else {
309
+ wx.login({
310
+ success({ code }: { code: string }) {
311
+ requestPaymentByBean(
312
+ {
313
+ caseConfigId: amounts.value[state.selected].id,
314
+ amount: currentAmount.value,
315
+ app: props.app,
316
+ tenant: props.tenant,
317
+ user: code,
318
+ },
319
+ props.headerApp
320
+ )
321
+ .then((result) => {
322
+ state.buttonLoading = false;
323
+ if (result) {
324
+ emit("complete", {
325
+ result: true,
326
+ type: isCombinedPayment.value ? "combined" : "wePay",
327
+ });
328
+ }
329
+ })
330
+ .catch((error) => {
331
+ state.buttonLoading = false;
332
+ showToast({
333
+ title: error.message || "支付失败",
334
+ icon: "none",
335
+ });
336
+ });
337
+ },
338
+ fail() {
339
+ state.buttonLoading = false;
340
+ showToast({
341
+ title: "登录失败,请重试",
342
+ icon: "none",
343
+ });
344
+ },
345
+ });
346
+ }
347
+ }
348
+
349
+ const onPayClick = async () => {
350
+ // 用云豆支付(纯云豆支付)
351
+ if (selectBean.value && !isCombinedPayment.value) {
352
+ showDialog.value = true;
353
+ return;
354
+ }
355
+
356
+ if (isCombinedPayment.value) {
357
+ // 检验云豆是否已经改变,改变则刷新选择
358
+ const res = await checkBalance()
359
+ if (!res) return
360
+ }
361
+
362
+ // 纯微信支付
363
+ proceedWechatPayment();
364
+ }
365
+
366
+ /**
367
+ * 校验余额是否充足
368
+ */
369
+ async function checkBalance() {
370
+ const $http = useHttp()
371
+ return new Promise((resolve, reject) => {
372
+ state.buttonLoading = true;
373
+ $http
374
+ .get<any>(balanceEndpoints.获取余额明细, {
375
+ app: props.apps,
376
+ })
377
+ .then((data) => {
378
+ state.buttonLoading = false;
379
+ if (data.commonAccount < balance.value) {
380
+ showModal({
381
+ title: '温馨提示',
382
+ content: '云豆不足,请刷新后再次确认',
383
+ showCancel: false,
384
+ confirmText: '刷新',
385
+ confirmColor: '#017fff',
386
+ success: () => {
387
+ balance.value = data.commonAccount;
388
+ }
389
+ })
390
+ resolve(false)
391
+
392
+ } else {
393
+ resolve(true)
394
+ }
395
+ }).catch((error) => {
396
+ state.buttonLoading = false;
397
+ resolve(false)
398
+ })
399
+ })
400
+ }
401
+
402
+ </script>
403
+
404
+ <style lang="scss">
405
+ .recharge-view2 {
406
+ height: 100%;
407
+ display: flex;
408
+ flex-direction: column;
409
+ --nut-primary-color: #017fff;
410
+
411
+ .flex-grow {
412
+ flex-grow: 1;
413
+ }
414
+
415
+ .bean-buy {
416
+ margin: 0 15px;
417
+ padding: 10px;
418
+ background: #fffbf3;
419
+ border-radius: 5px;
420
+ display: flex;
421
+ justify-content: space-between;
422
+ align-items: center;
423
+ flex-wrap: wrap;
424
+
425
+ .left {
426
+ .title {
427
+ color: #fd6701;
428
+ font-size: 14px;
429
+ font-weight: 600;
430
+ line-height: 20px;
431
+ margin-bottom: 6px;
432
+ }
433
+
434
+ .amount {
435
+ color: #353535;
436
+ font-size: 13px;
437
+ line-height: 16px;
438
+ background-image: url("https://cdn.ddjf.com/static/images/appkit/yundou.png");
439
+ background-repeat: no-repeat;
440
+ background-size: 16px 16px;
441
+ padding-left: 24px;
442
+ }
443
+ }
444
+
445
+ .right {
446
+ display: flex;
447
+ align-items: center;
448
+
449
+ .amount {
450
+ color: #353535;
451
+ font-size: 15px;
452
+ line-height: 20px;
453
+ margin-right: 10px;
454
+ }
455
+
456
+ .icon {
457
+ display: block;
458
+ width: 16px;
459
+ height: 16px;
460
+ font-size: 0;
461
+ }
462
+ }
463
+ }
464
+
465
+ .balance-warning {
466
+ width: 100%;
467
+ padding: 8px 10px;
468
+ margin-top: 10px;
469
+ background: #fdefe6;
470
+ border-radius: 5px;
471
+ color: #fd6701;
472
+ font-size: 12px;
473
+
474
+ &-tip {
475
+ margin: 10px 26px 0;
476
+ color: #666666;
477
+ font-size: 10px;
478
+ }
479
+ }
480
+
481
+ .amount-footer {
482
+ padding: 10px 0;
483
+
484
+ .agreement {
485
+ font-size: 12px;
486
+ display: flex;
487
+ justify-content: center;
488
+ align-items: cebter;
489
+ height: 40px;
490
+ }
491
+
492
+ .buy-amount {
493
+ display: flex;
494
+ justify-content: space-between;
495
+ align-items: center;
496
+ padding: 0 10px;
497
+ border-radius: 0px;
498
+ box-shadow: 0px -5px 14px -5px rgba(0, 0, 0, 0.1);
499
+
500
+ /* 上边框阴影 */
501
+ .left {
502
+ width: 70%;
503
+ color: #353535;
504
+ font-size: 13px;
505
+
506
+ .amount {
507
+ color: #fd6701;
508
+ font-size: 20px;
509
+ font-weight: 600;
510
+
511
+ i {
512
+ font-size: 14px;
513
+ font-style: normal;
514
+ }
515
+ }
516
+ }
517
+
518
+ .recharge-button {
519
+ background: linear-gradient(
520
+ 90deg,
521
+ #ffebc1 0%,
522
+ #ffd7a7 52.29%,
523
+ #ffb875 100%
524
+ );
525
+ color: #353535;
526
+ margin: 12px 0;
527
+ border: 0;
528
+ border-radius: 8px;
529
+ flex: 1;
530
+ }
531
+ }
532
+
533
+ .nut-checkbox {
534
+ line-height: 40px;
535
+ }
536
+
537
+ .nut-checkbox__label {
538
+ margin-left: 8px;
539
+ flex: flex;
540
+ font-size: 12px;
541
+ }
542
+
543
+ .link {
544
+ display: inline;
545
+ color: #fd6701;
546
+ }
547
+ }
548
+ }
549
+
550
+ .trade-dialog {
551
+ .nut-dialog__header {
552
+ font-size: 16px;
553
+ color: #262626;
554
+ }
555
+
556
+ .item {
557
+ font-size: 14px;
558
+ color: #666666;
559
+ line-height: 21px;
560
+ }
561
+
562
+ .nut-dialog__footer-cancel {
563
+ color: #353535 !important;
564
+ border-color: #cccccc !important;
565
+ }
566
+
567
+ .nut-dialog__footer-ok {
568
+ border: none;
569
+ color: #353535;
570
+ background: linear-gradient(90deg, #ffebc1 0%, #ffb875 100%);
571
+ }
572
+ }
573
+ </style>