@uxda/appkit 1.2.8 → 1.2.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 (66) hide show
  1. package/.eslintrc.mjs +7 -7
  2. package/README.md +187 -187
  3. package/babel.config.js +12 -12
  4. package/dist/appkit.css +289 -71
  5. package/dist/index.js +862 -341
  6. package/dist/styles.css +1 -0
  7. package/package.json +78 -78
  8. package/project.config.json +15 -15
  9. package/project.tt.json +13 -13
  10. package/rollup.config.mjs +54 -54
  11. package/src/Appkit.ts +65 -65
  12. package/src/balance/api/endpoints.ts +125 -122
  13. package/src/balance/api/index.ts +82 -82
  14. package/src/balance/components/AccountView.vue +754 -649
  15. package/src/balance/components/BalanceCard.vue +209 -209
  16. package/src/balance/components/BalanceReminder.vue +83 -83
  17. package/src/balance/components/ConsumptionFilter.vue +218 -218
  18. package/src/balance/components/ConsumptionRules.vue +68 -68
  19. package/src/balance/components/DateFilter.vue +235 -235
  20. package/src/balance/components/SecondBalance.vue +71 -71
  21. package/src/balance/components/Tip.vue +46 -0
  22. package/src/balance/components/index.ts +9 -9
  23. package/src/balance/types.ts +90 -88
  24. package/src/components/dd-area/index.vue +222 -222
  25. package/src/components/dd-icon/doc.md +21 -21
  26. package/src/components/dd-icon/index.vue +23 -23
  27. package/src/components/dd-selector/index.vue +124 -124
  28. package/src/components/ocr-id/index.vue +110 -110
  29. package/src/components/ocr-id/types.d.ts +12 -12
  30. package/src/global.ts +6 -6
  31. package/src/index.ts +88 -86
  32. package/src/main.scss +1 -1
  33. package/src/payment/api/config.ts +7 -7
  34. package/src/payment/api/endpoints.ts +103 -78
  35. package/src/payment/api/index.ts +71 -71
  36. package/src/payment/components/AmountPicker.vue +93 -93
  37. package/src/payment/components/RechargeResult.vue +66 -54
  38. package/src/payment/components/RechargeView.vue +154 -154
  39. package/src/payment/components/RightsPicker.vue +106 -0
  40. package/src/payment/components/TradeView.vue +298 -0
  41. package/src/payment/components/UserAgreement.vue +141 -141
  42. package/src/payment/components/index.ts +22 -19
  43. package/src/payment/index.ts +5 -5
  44. package/src/payment/services/index.ts +16 -16
  45. package/src/payment/services/invoke-recharge.ts +25 -25
  46. package/src/payment/services/request-payment.ts +58 -31
  47. package/src/payment/types.ts +28 -23
  48. package/src/register/components/SelfRegistration.vue +227 -227
  49. package/src/register/components/index.ts +2 -2
  50. package/src/shared/components/AppDrawer.vue +58 -58
  51. package/src/shared/components/EmptyView.vue +33 -33
  52. package/src/shared/components/PageHeader.vue +79 -79
  53. package/src/shared/components/index.ts +6 -6
  54. package/src/shared/composables/index.ts +2 -2
  55. package/src/shared/composables/useSafeArea.ts +43 -43
  56. package/src/shared/composables/useTabbar.ts +24 -24
  57. package/src/shared/http/Http.ts +126 -126
  58. package/src/shared/http/index.ts +1 -1
  59. package/src/shared/http/types.ts +157 -157
  60. package/src/shared/index.ts +3 -3
  61. package/src/shared/weixin/payment.ts +38 -38
  62. package/src/styles/fonts.scss +2 -2
  63. package/src/styles/vars.scss +3 -3
  64. package/tsconfig.json +30 -30
  65. package/types/global.d.ts +21 -21
  66. package/types/vue.d.ts +10 -10
@@ -1,649 +1,754 @@
1
- <template>
2
- <scroll-view
3
- class="account-view"
4
- :class="{ popupOpen: isAnyPopupOpen }"
5
- :scroll-y="!isAnyPopupOpen"
6
- :refresher-enabled="!isAnyPopupOpen"
7
- :refresher-triggered="refreshing"
8
- @scroll="onScroll"
9
- @refresherrefresh="onPullDownRefresh"
10
- :lower-threshold="50"
11
- @scrolltolower="onReachBottom"
12
- >
13
- <div class="scroll-content">
14
- <page-header
15
- color-mode="dark"
16
- title="我的账户"
17
- :class="{ 'with-background': scrolled > 0 }"
18
- @close="onPageHeaderClose"
19
- />
20
- <div class="row jusify-right">
21
- <div class="small-bean-button" @click="onSecondBalanceButtonClick">
22
- <label>权益余额</label>
23
- </div>
24
- </div>
25
- <div class="balance">
26
- <div class="bean-box spa-between">
27
- <div class="bean-img">
28
- <img
29
- class="bean-icon"
30
- src="https://cdn.ddjf.com/static/images/bpms-workBench/gold-bean.png"
31
- />
32
- <div class="bean-tag tag">云豆</div>
33
- </div>
34
- <div class="rule" @click="rulesPopupOpen = true">规则说明</div>
35
- </div>
36
- <div class="bean-counts spa-between">
37
- <div class="counts number">{{ balance.total || 0 }}</div>
38
- <div class="pay" @click="gotoRecharge">云豆充值</div>
39
- </div>
40
- </div>
41
- <div
42
- class="operation-title spa-between"
43
- :class="{ 'with-shadow': scrolled > 0 }"
44
- :style="{ top: `${safeArea.status + safeArea.nav}px` }"
45
- >
46
- <div class="search-time">
47
- <div class="title">收支明细</div>
48
- <div class="time" @click="openDateFilter" v-show="filtering.dateFrom">
49
- <div class="text number">{{ dateRangeDisplay }}</div>
50
- <img
51
- style="margin-top: -2px"
52
- class="time-icon"
53
- src="https://cdn.ddjf.com/static/images/bpms-workBench/clound-bean-down.png"
54
- />
55
- </div>
56
- </div>
57
- <div class="search" @click="filterOpen = true">
58
- <span class="text">筛选</span>
59
- <img
60
- class="time-icon"
61
- src="https://cdn.ddjf.com/static/images/bpms-workBench/clound-bean-select-icon.png"
62
- />
63
- </div>
64
- </div>
65
- <div class="operation-list">
66
- <div class="box" v-if="consumptionGroups.length > 0">
67
- <div
68
- class="box-detail"
69
- v-for="(item, index) in consumptionGroups"
70
- :key="index"
71
- >
72
- <div class="title number">{{ item.date }}</div>
73
- <div class="item" v-for="(it, i) in item.consumptions" :key="i">
74
- <div class="item-type">
75
- {{ it.交易类型 }}
76
- </div>
77
- <div class="item-detail">
78
- <div class="item-info spa-between">
79
- <div>
80
- <div class="item-info-type">
81
- {{ it.账户类型 }}
82
- </div>
83
- <div class="item-info-title">{{ it.title }}</div>
84
- </div>
85
- <div class="item-info-amount number">
86
- {{ it.收入还是支出 == "支出" ? "-" : "+" }}{{ it.amount }}
87
- </div>
88
- </div>
89
- <div class="item-detail-remark">{{ it.description }}</div>
90
- </div>
91
- </div>
92
- </div>
93
- <div class="box-not-text" v-if="reachedLastPage">没有更多了</div>
94
- </div>
95
- <empty-view v-else></empty-view>
96
- </div>
97
- </div>
98
- </scroll-view>
99
- <nut-popup
100
- pop-class="consumption-rules-popup"
101
- v-model:visible="rulesPopupOpen"
102
- :close-on-click-overlay="false"
103
- >
104
- <consumption-rules @complete="rulesPopupOpen = false" />
105
- </nut-popup>
106
- <nut-popup
107
- position="bottom"
108
- :style="{ height: '40%' }"
109
- round
110
- :close-on-click-overlay="true"
111
- v-model:visible="datePickerOpen"
112
- >
113
- <date-filter
114
- v-if="datePickerOpen"
115
- :from="filtering.dateFrom"
116
- :to="filtering.dateTo"
117
- @reset="onDateReset"
118
- @complete="onDateFilterComplete"
119
- />
120
- </nut-popup>
121
- <nut-popup
122
- position="bottom"
123
- :style="{ height: '75%' }"
124
- round
125
- :close-on-click-overlay="true"
126
- v-model:visible="filterOpen"
127
- >
128
- <consumption-filter
129
- :modelValue="[
130
- filtering.账户类型,
131
- filtering.收入还是支出,
132
- filtering.交易类型,
133
- filtering.权益类目,
134
- ]"
135
- @complete="onFilterComplete"
136
- />
137
- </nut-popup>
138
- <app-drawer v-model="secondBalanceOpen" title="权益余额">
139
- <second-balance :data="balance.privileges" />
140
- </app-drawer>
141
- </template>
142
-
143
- <script lang="ts" setup>
144
- import Taro, { useDidShow } from "@tarojs/taro";
145
- import { computed, onMounted, reactive, ref, watch } from "vue";
146
- import { endpoints, useHttp } from "../api";
147
- import { 账户流水筛选项, Balance, ConsumptionGroup, 账户流水 } from "../types";
148
- import ConsumptionFilter from "./ConsumptionFilter.vue";
149
- import DateFilter from "./DateFilter.vue";
150
- import ConsumptionRules from "./ConsumptionRules.vue";
151
- import { AppDrawer, PageHeader, WithPaging } from "../../shared";
152
- import SecondBalance from "./SecondBalance.vue";
153
- import dayjs from "dayjs";
154
- import EmptyView from "../../shared/components/EmptyView.vue";
155
- import { useSafeArea } from "../../shared";
156
-
157
- const safeArea = useSafeArea();
158
-
159
- const refreshing = ref(false);
160
-
161
- type AccountViewProps = {
162
- app: string;
163
- };
164
- const props = withDefaults(defineProps<AccountViewProps>(), {
165
- app: "",
166
- });
167
-
168
- const emit = defineEmits(["recharge"]);
169
-
170
- const filterOpen = ref<boolean>(false);
171
-
172
- // 规则说明弹窗
173
- const rulesPopupOpen = ref<boolean>(false);
174
-
175
- const filtering = reactive<账户流水筛选项>({
176
- 账户类型: "全部",
177
- 收入还是支出: "全部",
178
- 交易类型: "全部",
179
- 权益类目: "",
180
- dateFrom: "",
181
- dateTo: "",
182
- page: 1,
183
- pageSize: 20,
184
- });
185
-
186
- const reachedLastPage = ref<boolean>(false);
187
-
188
- /**
189
- * 全新搜索
190
- * 重置某些查询条件
191
- */
192
- function restartSearch() {
193
- // 从第一页开始
194
- filtering.page = 1;
195
- consumptionGroups.value = [];
196
- loadConsumptions();
197
- }
198
-
199
- // 时间筛选
200
- const datePickerOpen = ref<boolean>(false);
201
-
202
- function openDateFilter() {
203
- datePickerOpen.value = true;
204
- }
205
-
206
- const dateRangeDisplay = computed(() => {
207
- let startTime = filtering.dateFrom?.replace(/-/g, ".").substring(2);
208
- let endTime = filtering.dateTo?.replace(/-/g, ".").substring(2);
209
- return startTime + " - " + endTime;
210
- });
211
-
212
- const consumptionGroups = ref<ConsumptionGroup[]>([]);
213
-
214
- /**
215
- * 余额数据
216
- */
217
- const balance = ref<Balance>({
218
- total: 0,
219
- privileges: [],
220
- });
221
-
222
- useDidShow(() => {
223
- Taro.setNavigationBarTitle({
224
- title: "我的账户",
225
- });
226
- loadConsumptions();
227
- loadBalance();
228
- });
229
-
230
- function groupDataByDate(data: 账户流水[]): ConsumptionGroup[] {
231
- // 按照日期分组
232
- const groups: ConsumptionGroup[] = consumptionGroups.value || [];
233
- // [
234
- // date: '2023-10-1',
235
- // consumptions: []
236
- // ]
237
- // 组装成按日期分组
238
- data.forEach((d) => {
239
- const date = dayjs(d.time).format("YYYY-MM-DD");
240
- let group: ConsumptionGroup | undefined = groups.find(
241
- (g) => g.date === date
242
- );
243
- if (!group) {
244
- group = {
245
- date,
246
- consumptions: [],
247
- };
248
- groups.push(group);
249
- }
250
- group.consumptions.push(d);
251
- });
252
- groups.sort((a, b) => (a.date > b.date ? -1 : 1));
253
- return groups;
254
- }
255
-
256
- /**
257
- * 请求账户流水
258
- * @param append 搜索结果累加 上拉分页时
259
- */
260
- async function loadConsumptions(append: boolean = false) {
261
- if (!append) {
262
- consumptionGroups.value = [];
263
- }
264
- const $http = useHttp();
265
- Taro.showLoading({
266
- title: `加载中...`,
267
- mask: true,
268
- });
269
- $http
270
- .get<WithPaging<账户流水[]>>(endpoints.获取账户流水, {
271
- app: props.app,
272
- ...filtering,
273
- })
274
- .then((response) => {
275
- consumptionGroups.value = groupDataByDate(response.data);
276
- if (filtering.page >= response.totalPages) {
277
- filtering.page = response.totalPages;
278
- reachedLastPage.value = true;
279
- } else {
280
- reachedLastPage.value = false;
281
- }
282
- Taro.hideLoading();
283
- });
284
- }
285
-
286
- /**
287
- * 获取账户余额明细
288
- */
289
- async function loadBalance() {
290
- const $http = useHttp();
291
- $http
292
- .get<Balance>(endpoints.获取余额明细, {
293
- app: props.app,
294
- })
295
- .then((data) => {
296
- balance.value = data;
297
- });
298
- }
299
-
300
- const onFilterComplete = (value) => {
301
- filtering.账户类型 = value[0];
302
- filtering.收入还是支出 = value[1];
303
- filtering.交易类型 = value[2];
304
- filtering.权益类目 = value[3];
305
- filterOpen.value = false;
306
- restartSearch();
307
- };
308
-
309
- const onDateFilterComplete = (value) => {
310
- filtering.dateFrom = value.from;
311
- filtering.dateTo = value.to;
312
- datePickerOpen.value = false;
313
- restartSearch();
314
- };
315
-
316
- function gotoRecharge() {
317
- emit("recharge");
318
- }
319
-
320
- function loadNextPage() {
321
- filtering.page++;
322
- loadConsumptions(true);
323
- }
324
-
325
- // 以下这一大段处理下拉刷新、上滑分页以及弹窗与页面滑动的逻辑
326
- const scrolled = ref<number>(0);
327
-
328
- /**
329
- * 记录 scroll-view 滚动的位置
330
- */
331
- const onScroll = (e) => {
332
- const { scrollTop } = e;
333
- scrolled.value = scrollTop;
334
- };
335
-
336
- /**
337
- * 下拉刷新 pull down refresh
338
- */
339
- const onPullDownRefresh = () => {
340
- refreshing.value = true;
341
- // 重新请求余额数据
342
- loadBalance();
343
- setTimeout(() => {
344
- refreshing.value = false;
345
- }, 500);
346
- };
347
-
348
- /**
349
- * 滑动到底部请求下一页并合并查询结果
350
- */
351
- const onReachBottom = () => {
352
- if (reachedLastPage.value) {
353
- return false;
354
- }
355
- loadNextPage();
356
- };
357
-
358
- /**
359
- * 浮窗弹出时不允许
360
- * 1. 下拉刷新
361
- * 2. 上滑分页
362
- */
363
- const isAnyPopupOpen = computed(() => {
364
- return (
365
- rulesPopupOpen.value ||
366
- datePickerOpen.value ||
367
- filterOpen.value ||
368
- secondBalanceOpen.value
369
- );
370
- });
371
-
372
- const secondBalanceOpen = ref<boolean>(false);
373
-
374
- function onSecondBalanceButtonClick() {
375
- secondBalanceOpen.value = true;
376
- }
377
-
378
- watch(secondBalanceOpen, () => {
379
- Taro.setNavigationBarColor({
380
- frontColor: secondBalanceOpen.value ? "#000000" : "#ffffff",
381
- backgroundColor: "#ffffff",
382
- animation: {
383
- duration: 400,
384
- timingFunc: "easeIn",
385
- },
386
- });
387
- });
388
-
389
- function onDateReset() {
390
- resetDateRange();
391
- }
392
-
393
- /**
394
- * 充值筛选的起止时间
395
- */
396
- function resetDateRange() {
397
- // 筛选的起止时间
398
- filtering.dateTo = dayjs().format("YYYY-MM-DD");
399
- filtering.dateFrom = dayjs().add(-3, "M").format("YYYY-MM-DD");
400
- }
401
-
402
- function onPageHeaderClose() {
403
- Taro.navigateBack({
404
- delta: 1,
405
- });
406
- }
407
-
408
- onMounted(() => {
409
- resetDateRange();
410
- });
411
- </script>
412
-
413
- <style lang="scss">
414
- .account-view {
415
- height: 100vh;
416
- .scroll-content {
417
- background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzUwIiBoZWlnaHQ9IjQwNiIgdmlld0JveD0iMCAwIDc1MCA0MDYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0zODIuNSA0MDcuNUM1NzcuMzU3IDQwNy41IDc1My43ODggMzgxLjI0OCA4ODEuNTIxIDMzOC43OTFDOTQ1LjM4NiAzMTcuNTYzIDk5Ny4xMDQgMjkyLjI3NiAxMDMyLjg3IDI2NC4xNzFDMTA2OC42MiAyMzYuMDcxIDEwODguNSAyMDUuMDk3IDEwODguNSAxNzIuNUMxMDg4LjUgMTM5LjkwMyAxMDY4LjYyIDEwOC45MjkgMTAzMi44NyA4MC44Mjg5Qzk5Ny4xMDQgNTIuNzI0NSA5NDUuMzg2IDI3LjQzNjcgODgxLjUyMSA2LjIwODk4Qzc1My43ODggLTM2LjI0ODIgNTc3LjM1NyAtNjIuNSAzODIuNSAtNjIuNUMxODcuNjQzIC02Mi41IDExLjIxMjIgLTM2LjI0ODIgLTExNi41MjIgNi4yMDg5OEMtMTgwLjM4NiAyNy40MzY3IC0yMzIuMTA0IDUyLjcyNDUgLTI2Ny44NjcgODAuODI4OUMtMzAzLjYyNCAxMDguOTI5IC0zMjMuNSAxMzkuOTAzIC0zMjMuNSAxNzIuNUMtMzIzLjUgMjA1LjA5NyAtMzAzLjYyNCAyMzYuMDcxIC0yNjcuODY3IDI2NC4xNzFDLTIzMi4xMDQgMjkyLjI3NiAtMTgwLjM4NiAzMTcuNTYzIC0xMTYuNTIyIDMzOC43OTFDMTEuMjEyMiAzODEuMjQ4IDE4Ny42NDMgNDA3LjUgMzgyLjUgNDA3LjVaIiBmaWxsPSIjM0IzOTNDIiBzdHJva2U9ImJsYWNrIi8+Cjwvc3ZnPgo=");
418
- background-position: center -200px;
419
- background-repeat: no-repeat;
420
- }
421
- .page-header {
422
- background-color: #3b393c;
423
- position: sticky;
424
- top: 0;
425
- z-index: 1;
426
- transition: background-color 0.3s;
427
- &.with-background {
428
- background-color: #3b393c;
429
- }
430
- }
431
- &.popupOpen {
432
- height: 100vh;
433
- overflow: hidden;
434
- }
435
- .spa-between {
436
- display: flex;
437
- justify-content: space-between;
438
- align-items: center;
439
- }
440
- .row {
441
- display: flex;
442
- flex-direction: row;
443
- margin: 10px 15px;
444
- }
445
- .jusify-right {
446
- justify-content: flex-end;
447
- }
448
- .small-bean-button {
449
- height: 22px;
450
- border-radius: 11px;
451
- border: 1px solid #ffffff10;
452
- background-color: #ffffff18;
453
- display: inline-block;
454
- padding: 0 10px;
455
- line-height: 22px;
456
- color: #e7caad;
457
- font-size: 12px;
458
- label {
459
- background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEwIDZMMTYgMTJMMTAgMThWNloiIGZpbGw9IiNFN0NBQUQiIHN0cm9rZT0iI0U3Q0FBRCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+Cjwvc3ZnPgo=");
460
- padding-right: 18px;
461
- background-repeat: no-repeat;
462
- background-position: right center;
463
- background-size: 16px;
464
- }
465
- }
466
- .balance {
467
- border-radius: 15px;
468
- background: linear-gradient(105deg, #f4e2ce 1.88%, #debb9b 98.18%);
469
- box-shadow: 0px -10px 9px -3px rgba(0, 0, 0, 0.33);
470
- height: 112px;
471
- padding: 20px;
472
- margin: 0 15px;
473
- box-sizing: border-box;
474
- font-size: 10px;
475
- .bean-img {
476
- display: flex;
477
- justify-content: flex-start;
478
- align-items: center;
479
- .bean-icon {
480
- display: block;
481
- font-size: 0;
482
- width: 20px;
483
- height: 20px;
484
- margin-right: 4px;
485
- }
486
- .bean-tag {
487
- color: #353535;
488
- height: 15px;
489
- line-height: 15px;
490
- border-radius: 30px 50px 50px 0px;
491
- background: rgba(#ff8320, 0.3);
492
- padding-left: 5px;
493
- padding-right: 10px;
494
- }
495
- .tag {
496
- background: #ff8320;
497
- color: #fff;
498
- }
499
- }
500
- .rule {
501
- color: #353535;
502
- opacity: 0.5;
503
- }
504
- }
505
- .bean-counts {
506
- margin-top: 12px;
507
- .counts {
508
- color: #3d3835;
509
- font-size: 32px;
510
- font-weight: 700;
511
- }
512
- .pay {
513
- padding: 0 20px;
514
- height: 32px;
515
- line-height: 32px;
516
- background: linear-gradient(187.18deg, #353535 10.04%, #433f46 90.21%);
517
- border-radius: 16px;
518
- color: #e7caad;
519
- font-size: 15px;
520
- font-weight: 500;
521
- }
522
- }
523
- .operation-title {
524
- padding: 10px 15px;
525
- background: #fff;
526
- position: sticky;
527
- z-index: 10;
528
- transition: box-shadow 0.3s;
529
- &.with-shadow {
530
- box-shadow: 0px 1px 10px 0px #99999933;
531
- }
532
- .text {
533
- color: #353535;
534
- font-size: 12px;
535
- opacity: 0.5;
536
- }
537
- .time-icon {
538
- display: block;
539
- font-size: 0;
540
- width: 12px;
541
- height: 12px;
542
- margin-left: 4px;
543
- }
544
- .search-time {
545
- display: flex;
546
- align-items: center;
547
- .title {
548
- color: #000;
549
- font-weight: 500;
550
- font-size: 17px;
551
- margin-right: 10px;
552
- }
553
- .time {
554
- height: 22px;
555
- padding-right: 5px;
556
- flex: 1;
557
- display: flex;
558
- align-items: center;
559
- }
560
- }
561
- .search {
562
- display: flex;
563
- align-items: center;
564
- height: 22px;
565
- padding-left: 5px;
566
- }
567
- }
568
- .operation-list {
569
- margin: 0 15px;
570
- padding-bottom: 15px;
571
- .box {
572
- &-detail {
573
- .title {
574
- line-height: 22px;
575
- font-weight: 700;
576
- font-size: 12px;
577
- color: #000;
578
- opacity: 0.5;
579
- margin-bottom: 10px;
580
- }
581
- .item {
582
- border-radius: 5px;
583
- background: rgba(255, 255, 255, 0.5);
584
- box-shadow: 0px 2.5px 9.5px 2px rgba(0, 0, 0, 0.05);
585
- border-radius: 5px;
586
- padding: 12px 10px;
587
- display: flex;
588
- margin-bottom: 10px;
589
- &-type {
590
- background: linear-gradient(
591
- 113.95deg,
592
- #f4e2ce 1.2%,
593
- #debb9b 77.63%
594
- );
595
- width: 30px;
596
- height: 30px;
597
- border-radius: 15px;
598
- margin-right: 15px;
599
- line-height: 30px;
600
- font-size: 10px;
601
- font-weight: 500;
602
- color: #000;
603
- text-align: center;
604
- }
605
- &-detail {
606
- flex: 1;
607
- .item-info {
608
- padding: 0;
609
- font-size: 14px;
610
- font-weight: 700;
611
- color: #000;
612
- &-type {
613
- line-height: 15px;
614
- }
615
- &-title {
616
- font-weight: 400;
617
- opacity: 0.8;
618
- font-size: 11px;
619
- }
620
- &-amount {
621
- color: #9e7b5a;
622
- }
623
- }
624
- &-remark {
625
- opacity: 0.3;
626
- line-height: 15px;
627
- font-size: 10px;
628
- }
629
- }
630
- }
631
- }
632
- &-not-text {
633
- opacity: 0.4;
634
- color: #353535;
635
- font-size: 12px;
636
- line-height: 20px;
637
- margin: 0 auto 40px;
638
- text-align: center;
639
- }
640
- }
641
- }
642
- }
643
- .consumption-rules-popup {
644
- border-radius: 16px;
645
- width: 70%;
646
- max-height: 80%;
647
- padding: 24px;
648
- }
649
- </style>
1
+ <template>
2
+ <div class="account-view">
3
+ <div class="scroll-content">
4
+ <page-header
5
+ color-mode="dark"
6
+ title="我的账户"
7
+ :class="{ 'with-background': scrolled > 0 }"
8
+ @close="onPageHeaderClose"
9
+ />
10
+ <div class="row jusify-right">
11
+ <div class="small-bean-button" @click="onSecondBalanceButtonClick">
12
+ <label>收支明细</label>
13
+ </div>
14
+ </div>
15
+ <div class="balance">
16
+ <div class="bean-box spa-between">
17
+ <div class="bean-img">
18
+ <img
19
+ class="bean-icon"
20
+ src="https://cdn.ddjf.com/static/images/bpms-workBench/gold-bean.png"
21
+ />
22
+ <div class="bean-tag tag">云豆</div>
23
+ </div>
24
+ <div class="rule" @click="rulesPopupOpen = true">规则说明</div>
25
+ </div>
26
+ <div class="bean-counts spa-between">
27
+ <div class="counts number">{{ balance.total || 0 }}</div>
28
+ <div class="pay" @click="gotoRecharge">云豆充值</div>
29
+ </div>
30
+ </div>
31
+ <Tip />
32
+ <div class="rights-card" v-if="balance.privileges.corporateStar">
33
+ <div class="title">启明星权益</div>
34
+ <div class="list">
35
+ <div class="item star-item" v-for="(item, index) in balance.privileges.corporateStar" :key="index">
36
+ <div class="item-count">{{ item.count }}</div>
37
+ <div class="item-title">
38
+ <div>{{ item.title }}</div>
39
+ <div class="item-title-button" v-if="item.activityId">
40
+ <div @click="gotoTrade(item)">超值换购</div>
41
+ <img class="button-icon" src="https://cdn.ddjf.com/static/images/bpms-workBench/button-hg.svg" />
42
+ </div>
43
+ </div>
44
+ </div>
45
+ </div>
46
+ </div>
47
+ <div class="rights-card" v-if="balance.privileges.aiapprove">
48
+ <div class="title">AI审批权益</div>
49
+ <div class="list">
50
+ <div class="item" v-for="(item, index) in balance.privileges.aiapprove" :key="index">
51
+ <div class="item-count">{{ item.count }}</div>
52
+ <div class="item-title">{{ item.title }}</div>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ </div>
57
+ </div>
58
+ <nut-popup
59
+ pop-class="consumption-rules-popup"
60
+ v-model:visible="rulesPopupOpen"
61
+ :close-on-click-overlay="false"
62
+ >
63
+ <consumption-rules @complete="rulesPopupOpen = false" />
64
+ </nut-popup>
65
+ <nut-popup
66
+ position="bottom"
67
+ :style="{ height: '40%' }"
68
+ round
69
+ :close-on-click-overlay="true"
70
+ v-model:visible="datePickerOpen"
71
+ >
72
+ <date-filter
73
+ v-if="datePickerOpen"
74
+ :from="filtering.dateFrom"
75
+ :to="filtering.dateTo"
76
+ @reset="onDateReset"
77
+ @complete="onDateFilterComplete"
78
+ />
79
+ </nut-popup>
80
+ <nut-popup
81
+ position="bottom"
82
+ :style="{ height: '75%' }"
83
+ round
84
+ :close-on-click-overlay="true"
85
+ v-model:visible="filterOpen"
86
+ >
87
+ <consumption-filter
88
+ :modelValue="[
89
+ filtering.账户类型,
90
+ filtering.收入还是支出,
91
+ filtering.交易类型,
92
+ filtering.权益类目,
93
+ ]"
94
+ @complete="onFilterComplete"
95
+ />
96
+ </nut-popup>
97
+ <app-drawer v-model="secondBalanceOpen" title="收支明细">
98
+ <div class="operation-box">
99
+ <div
100
+ class="operation-title spa-between"
101
+ :class="{ 'with-shadow': scrolled > 0 }"
102
+ >
103
+ <div class="search-time">
104
+ <div class="title">收支明细</div>
105
+ <div class="time" @click="openDateFilter" v-show="filtering.dateFrom">
106
+ <div class="text number">{{ dateRangeDisplay }}</div>
107
+ <img
108
+ style="margin-top: -2px"
109
+ class="time-icon"
110
+ src="https://cdn.ddjf.com/static/images/bpms-workBench/clound-bean-down.png"
111
+ />
112
+ </div>
113
+ </div>
114
+ <div class="search" @click="filterOpen = true">
115
+ <span class="text">筛选</span>
116
+ <img
117
+ class="time-icon"
118
+ src="https://cdn.ddjf.com/static/images/bpms-workBench/clound-bean-select-icon.png"
119
+ />
120
+ </div>
121
+ </div>
122
+ <div class="operation-list">
123
+ <scroll-view
124
+ class="operation-scroll"
125
+ :scroll-y="true"
126
+ @scroll="onScroll"
127
+ :lower-threshold="50"
128
+ @scrolltolower="onReachBottom"
129
+ >
130
+ <div class="box" v-if="consumptionGroups.length > 0">
131
+ <div
132
+ class="box-detail"
133
+ v-for="(item, index) in consumptionGroups"
134
+ :key="index"
135
+ >
136
+ <div class="title number">{{ item.date }}</div>
137
+ <div class="item" v-for="(it, i) in item.consumptions" :key="i">
138
+ <div class="item-type">
139
+ {{ it.交易类型 }}
140
+ </div>
141
+ <div class="item-detail">
142
+ <div class="item-info spa-between">
143
+ <div>
144
+ <div class="item-info-type">
145
+ {{ it.账户类型 }}
146
+ </div>
147
+ <div class="item-info-title">{{ it.title }}</div>
148
+ </div>
149
+ <div class="item-info-amount number">
150
+ {{ it.收入还是支出 == "支出" ? "-" : "+" }}{{ it.amount }}
151
+ </div>
152
+ </div>
153
+ <div class="item-detail-remark">{{ it.description }}</div>
154
+ </div>
155
+ </div>
156
+ </div>
157
+ <div class="box-not-text" v-if="reachedLastPage">没有更多了</div>
158
+ </div>
159
+ <empty-view v-else></empty-view>
160
+ </scroll-view>
161
+ </div>
162
+ </div>
163
+ </app-drawer>
164
+ </template>
165
+
166
+ <script lang="ts" setup>
167
+ import Taro, { useDidShow } from "@tarojs/taro";
168
+ import { computed, onMounted, reactive, ref, watch } from "vue";
169
+ import { endpoints, useHttp } from "../api";
170
+ import { 账户流水筛选项, Balance, ConsumptionGroup, 账户流水 } from "../types";
171
+ import ConsumptionFilter from "./ConsumptionFilter.vue";
172
+ import DateFilter from "./DateFilter.vue";
173
+ import ConsumptionRules from "./ConsumptionRules.vue";
174
+ import { AppDrawer, PageHeader, WithPaging } from "../../shared";
175
+ import dayjs from "dayjs";
176
+ import EmptyView from "../../shared/components/EmptyView.vue";
177
+ import Tip from './Tip.vue'
178
+ import _ from "lodash";
179
+
180
+ const refreshing = ref(false);
181
+
182
+ type AccountViewProps = {
183
+ app: string;
184
+ };
185
+ const props = withDefaults(defineProps<AccountViewProps>(), {
186
+ app: "",
187
+ });
188
+
189
+ const emit = defineEmits(["recharge", "trade"]);
190
+
191
+ const filterOpen = ref<boolean>(false);
192
+
193
+ // 规则说明弹窗
194
+ const rulesPopupOpen = ref<boolean>(false);
195
+
196
+ const filtering = reactive<账户流水筛选项>({
197
+ 账户类型: "全部",
198
+ 收入还是支出: "全部",
199
+ 交易类型: "全部",
200
+ 权益类目: "",
201
+ dateFrom: "",
202
+ dateTo: "",
203
+ page: 1,
204
+ pageSize: 20,
205
+ });
206
+
207
+ const reachedLastPage = ref<boolean>(false);
208
+
209
+ /**
210
+ * 全新搜索
211
+ * 重置某些查询条件
212
+ */
213
+ function restartSearch() {
214
+ // 从第一页开始
215
+ filtering.page = 1;
216
+ consumptionGroups.value = [];
217
+ loadConsumptions();
218
+ }
219
+
220
+ // 时间筛选
221
+ const datePickerOpen = ref<boolean>(false);
222
+
223
+ function openDateFilter() {
224
+ datePickerOpen.value = true;
225
+ }
226
+
227
+ const dateRangeDisplay = computed(() => {
228
+ let startTime = filtering.dateFrom?.replace(/-/g, ".").substring(2);
229
+ let endTime = filtering.dateTo?.replace(/-/g, ".").substring(2);
230
+ return startTime + " - " + endTime;
231
+ });
232
+
233
+ const consumptionGroups = ref<ConsumptionGroup[]>([]);
234
+
235
+ /**
236
+ * 余额数据
237
+ */
238
+ const balance = ref<Balance>({
239
+ total: 0,
240
+ privileges: {},
241
+ });
242
+
243
+ useDidShow(() => {
244
+ Taro.setNavigationBarTitle({
245
+ title: "我的账户",
246
+ });
247
+ loadBalance();
248
+ });
249
+
250
+ function groupDataByDate(data: 账户流水[]): ConsumptionGroup[] {
251
+ // 按照日期分组
252
+ const groups: ConsumptionGroup[] = consumptionGroups.value || [];
253
+ // [
254
+ // date: '2023-10-1',
255
+ // consumptions: []
256
+ // ]
257
+ // 组装成按日期分组
258
+ data.forEach((d) => {
259
+ const date = dayjs(d.time).format("YYYY-MM-DD");
260
+ let group: ConsumptionGroup | undefined = groups.find(
261
+ (g) => g.date === date
262
+ );
263
+ if (!group) {
264
+ group = {
265
+ date,
266
+ consumptions: [],
267
+ };
268
+ groups.push(group);
269
+ }
270
+ group.consumptions.push(d);
271
+ });
272
+ groups.sort((a, b) => (a.date > b.date ? -1 : 1));
273
+ return groups;
274
+ }
275
+
276
+ /**
277
+ * 请求账户流水
278
+ * @param append 搜索结果累加 上拉分页时
279
+ */
280
+ async function loadConsumptions(append: boolean = false) {
281
+ if (!append) {
282
+ consumptionGroups.value = [];
283
+ }
284
+ const $http = useHttp();
285
+ Taro.showLoading({
286
+ title: `加载中...`,
287
+ mask: true,
288
+ });
289
+ $http
290
+ .get<WithPaging<账户流水[]>>(endpoints.获取账户流水, {
291
+ app: props.app,
292
+ ...filtering,
293
+ })
294
+ .then((response) => {
295
+ consumptionGroups.value = groupDataByDate(response.data);
296
+ if (filtering.page >= response.totalPages) {
297
+ filtering.page = response.totalPages;
298
+ reachedLastPage.value = true;
299
+ } else {
300
+ reachedLastPage.value = false;
301
+ }
302
+ Taro.hideLoading();
303
+ });
304
+ }
305
+
306
+ /**
307
+ * 获取账户余额明细
308
+ */
309
+ async function loadBalance() {
310
+ const $http = useHttp();
311
+ $http
312
+ .get<Balance>(endpoints.获取余额明细, {
313
+ app: props.app,
314
+ })
315
+ .then((data) => {
316
+ const { privileges, total } = data
317
+ const filterData = {
318
+ total,
319
+ privileges: _.groupBy(privileges, 'appCode')
320
+ }
321
+ balance.value = filterData;
322
+ });
323
+ }
324
+
325
+ const onFilterComplete = (value) => {
326
+ filtering.账户类型 = value[0];
327
+ filtering.收入还是支出 = value[1];
328
+ filtering.交易类型 = value[2];
329
+ filtering.权益类目 = value[3];
330
+ filterOpen.value = false;
331
+ restartSearch();
332
+ };
333
+
334
+ const onDateFilterComplete = (value) => {
335
+ filtering.dateFrom = value.from;
336
+ filtering.dateTo = value.to;
337
+ datePickerOpen.value = false;
338
+ restartSearch();
339
+ };
340
+
341
+ function gotoRecharge() {
342
+ emit("recharge");
343
+ }
344
+
345
+ function gotoTrade(item: any){
346
+ emit("trade", item);
347
+ }
348
+
349
+ function loadNextPage() {
350
+ filtering.page++;
351
+ loadConsumptions(true);
352
+ }
353
+
354
+ // 以下这一大段处理下拉刷新、上滑分页以及弹窗与页面滑动的逻辑
355
+ const scrolled = ref<number>(0);
356
+
357
+ /**
358
+ * 记录 scroll-view 滚动的位置
359
+ */
360
+ const onScroll = (e) => {
361
+ const { scrollTop } = e;
362
+ scrolled.value = scrollTop;
363
+ };
364
+
365
+ /**
366
+ * 下拉刷新 pull down refresh
367
+ */
368
+ const onPullDownRefresh = () => {
369
+ refreshing.value = true;
370
+ // 重新请求余额数据
371
+ loadBalance();
372
+ setTimeout(() => {
373
+ refreshing.value = false;
374
+ }, 500);
375
+ };
376
+
377
+ /**
378
+ * 滑动到底部请求下一页并合并查询结果
379
+ */
380
+ const onReachBottom = () => {
381
+ console.log('到底了')
382
+ if (reachedLastPage.value) {
383
+ return false;
384
+ }
385
+ loadNextPage();
386
+ };
387
+
388
+ /**
389
+ * 浮窗弹出时不允许
390
+ * 1. 下拉刷新
391
+ * 2. 上滑分页
392
+ */
393
+ const isAnyPopupOpen = computed(() => {
394
+ return (
395
+ rulesPopupOpen.value ||
396
+ datePickerOpen.value ||
397
+ filterOpen.value ||
398
+ secondBalanceOpen.value
399
+ );
400
+ });
401
+
402
+ const secondBalanceOpen = ref<boolean>(false);
403
+
404
+ function onSecondBalanceButtonClick() {
405
+ secondBalanceOpen.value = true;
406
+ loadConsumptions();
407
+ }
408
+
409
+ watch(secondBalanceOpen, () => {
410
+ Taro.setNavigationBarColor({
411
+ frontColor: secondBalanceOpen.value ? "#000000" : "#ffffff",
412
+ backgroundColor: "#ffffff",
413
+ animation: {
414
+ duration: 400,
415
+ timingFunc: "easeIn",
416
+ },
417
+ });
418
+ });
419
+
420
+ function onDateReset() {
421
+ resetDateRange();
422
+ }
423
+
424
+ /**
425
+ * 充值筛选的起止时间
426
+ */
427
+ function resetDateRange() {
428
+ // 筛选的起止时间
429
+ filtering.dateTo = dayjs().format("YYYY-MM-DD");
430
+ filtering.dateFrom = dayjs().add(-3, "M").format("YYYY-MM-DD");
431
+ }
432
+
433
+ function onPageHeaderClose() {
434
+ Taro.navigateBack({
435
+ delta: 1,
436
+ });
437
+ }
438
+
439
+ onMounted(() => {
440
+ resetDateRange();
441
+ });
442
+ </script>
443
+
444
+ <style lang="scss">
445
+ .account-view {
446
+ height: 100vh;
447
+ .scroll-content {
448
+ background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzUwIiBoZWlnaHQ9IjQwNiIgdmlld0JveD0iMCAwIDc1MCA0MDYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0zODIuNSA0MDcuNUM1NzcuMzU3IDQwNy41IDc1My43ODggMzgxLjI0OCA4ODEuNTIxIDMzOC43OTFDOTQ1LjM4NiAzMTcuNTYzIDk5Ny4xMDQgMjkyLjI3NiAxMDMyLjg3IDI2NC4xNzFDMTA2OC42MiAyMzYuMDcxIDEwODguNSAyMDUuMDk3IDEwODguNSAxNzIuNUMxMDg4LjUgMTM5LjkwMyAxMDY4LjYyIDEwOC45MjkgMTAzMi44NyA4MC44Mjg5Qzk5Ny4xMDQgNTIuNzI0NSA5NDUuMzg2IDI3LjQzNjcgODgxLjUyMSA2LjIwODk4Qzc1My43ODggLTM2LjI0ODIgNTc3LjM1NyAtNjIuNSAzODIuNSAtNjIuNUMxODcuNjQzIC02Mi41IDExLjIxMjIgLTM2LjI0ODIgLTExNi41MjIgNi4yMDg5OEMtMTgwLjM4NiAyNy40MzY3IC0yMzIuMTA0IDUyLjcyNDUgLTI2Ny44NjcgODAuODI4OUMtMzAzLjYyNCAxMDguOTI5IC0zMjMuNSAxMzkuOTAzIC0zMjMuNSAxNzIuNUMtMzIzLjUgMjA1LjA5NyAtMzAzLjYyNCAyMzYuMDcxIC0yNjcuODY3IDI2NC4xNzFDLTIzMi4xMDQgMjkyLjI3NiAtMTgwLjM4NiAzMTcuNTYzIC0xMTYuNTIyIDMzOC43OTFDMTEuMjEyMiAzODEuMjQ4IDE4Ny42NDMgNDA3LjUgMzgyLjUgNDA3LjVaIiBmaWxsPSIjM0IzOTNDIiBzdHJva2U9ImJsYWNrIi8+Cjwvc3ZnPgo=");
449
+ background-position: center -200px;
450
+ background-repeat: no-repeat;
451
+ }
452
+ .page-header {
453
+ background-color: #3b393c;
454
+ position: sticky;
455
+ top: 0;
456
+ z-index: 1;
457
+ transition: background-color 0.3s;
458
+ &.with-background {
459
+ background-color: #3b393c;
460
+ }
461
+ }
462
+ .spa-between {
463
+ display: flex;
464
+ justify-content: space-between;
465
+ align-items: center;
466
+ }
467
+ .row {
468
+ display: flex;
469
+ flex-direction: row;
470
+ margin: 10px 15px;
471
+ }
472
+ .jusify-right {
473
+ justify-content: flex-end;
474
+ }
475
+ .small-bean-button {
476
+ height: 22px;
477
+ border-radius: 11px;
478
+ border: 1px solid #ffffff10;
479
+ background-color: #ffffff18;
480
+ display: inline-block;
481
+ padding: 0 10px;
482
+ line-height: 22px;
483
+ color: #e7caad;
484
+ font-size: 12px;
485
+ label {
486
+ background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEwIDZMMTYgMTJMMTAgMThWNloiIGZpbGw9IiNFN0NBQUQiIHN0cm9rZT0iI0U3Q0FBRCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+Cjwvc3ZnPgo=");
487
+ padding-right: 18px;
488
+ background-repeat: no-repeat;
489
+ background-position: right center;
490
+ background-size: 16px;
491
+ }
492
+ }
493
+ .balance {
494
+ border-radius: 15px;
495
+ background: linear-gradient(105deg, #f4e2ce 1.88%, #debb9b 98.18%);
496
+ box-shadow: 0px -10px 9px -3px rgba(0, 0, 0, 0.33);
497
+ height: 112px;
498
+ padding: 20px;
499
+ margin: 0 15px;
500
+ box-sizing: border-box;
501
+ font-size: 10px;
502
+ .bean-img {
503
+ display: flex;
504
+ justify-content: flex-start;
505
+ align-items: center;
506
+ .bean-icon {
507
+ display: block;
508
+ font-size: 0;
509
+ width: 20px;
510
+ height: 20px;
511
+ margin-right: 4px;
512
+ }
513
+ .bean-tag {
514
+ color: #353535;
515
+ height: 15px;
516
+ line-height: 15px;
517
+ border-radius: 30px 50px 50px 0px;
518
+ background: rgba(#ff8320, 0.3);
519
+ padding-left: 5px;
520
+ padding-right: 10px;
521
+ }
522
+ .tag {
523
+ background: #ff8320;
524
+ color: #fff;
525
+ }
526
+ }
527
+ .rule {
528
+ color: #353535;
529
+ opacity: 0.5;
530
+ }
531
+ }
532
+ .bean-counts {
533
+ margin-top: 12px;
534
+ .counts {
535
+ color: #3d3835;
536
+ font-size: 32px;
537
+ font-weight: 700;
538
+ }
539
+ .pay {
540
+ padding: 0 20px;
541
+ height: 32px;
542
+ line-height: 32px;
543
+ background: linear-gradient(187.18deg, #353535 10.04%, #433f46 90.21%);
544
+ border-radius: 16px;
545
+ color: #e7caad;
546
+ font-size: 15px;
547
+ font-weight: 500;
548
+ }
549
+ }
550
+ }
551
+ .consumption-rules-popup {
552
+ border-radius: 16px;
553
+ width: 70%;
554
+ max-height: 80%;
555
+ padding: 24px;
556
+ }
557
+
558
+ .operation-box{
559
+ width: 100vw;
560
+ overflow: hidden;
561
+ display: flex;
562
+ flex-direction: column;
563
+ height: calc(100vh - 87px);
564
+ .operation-title {
565
+ padding: 10px 15px;
566
+ background: #fff;
567
+ transition: box-shadow 0.3s;
568
+
569
+ &.with-shadow {
570
+ box-shadow: 0px 1px 10px 0px #99999933;
571
+ }
572
+ .text {
573
+ color: #353535;
574
+ font-size: 12px;
575
+ opacity: 0.5;
576
+ }
577
+ .time-icon {
578
+ display: block;
579
+ font-size: 0;
580
+ width: 12px;
581
+ height: 12px;
582
+ margin-left: 4px;
583
+ }
584
+ .search-time {
585
+ display: flex;
586
+ align-items: center;
587
+ .title {
588
+ color: #000;
589
+ font-weight: 500;
590
+ font-size: 17px;
591
+ margin-right: 10px;
592
+ }
593
+ .time {
594
+ height: 22px;
595
+ padding-right: 5px;
596
+ flex: 1;
597
+ display: flex;
598
+ align-items: center;
599
+ }
600
+ }
601
+ .search {
602
+ display: flex;
603
+ align-items: center;
604
+ height: 22px;
605
+ padding-left: 5px;
606
+ }
607
+ }
608
+ .spa-between {
609
+ display: flex;
610
+ justify-content: space-between;
611
+ align-items: center;
612
+ }
613
+ .operation-list {
614
+ flex: 1;
615
+ margin: 0 15px;
616
+ .operation-scroll{
617
+ height: calc(100vh - 130px)
618
+ }
619
+ .box {
620
+ &-detail {
621
+ .title {
622
+ line-height: 22px;
623
+ font-weight: 700;
624
+ font-size: 12px;
625
+ color: #000;
626
+ opacity: 0.5;
627
+ margin-bottom: 10px;
628
+ }
629
+ .item {
630
+ border-radius: 5px;
631
+ background: rgba(255, 255, 255, 0.5);
632
+ box-shadow: 0px 2.5px 9.5px 2px rgba(0, 0, 0, 0.05);
633
+ border-radius: 5px;
634
+ padding: 12px 10px;
635
+ display: flex;
636
+ margin-bottom: 10px;
637
+ &-type {
638
+ background: linear-gradient(
639
+ 113.95deg,
640
+ #f4e2ce 1.2%,
641
+ #debb9b 77.63%
642
+ );
643
+ width: 30px;
644
+ height: 30px;
645
+ border-radius: 15px;
646
+ margin-right: 15px;
647
+ line-height: 30px;
648
+ font-size: 10px;
649
+ font-weight: 500;
650
+ color: #000;
651
+ text-align: center;
652
+ }
653
+ &-detail {
654
+ flex: 1;
655
+ .item-info {
656
+ padding: 0;
657
+ font-size: 14px;
658
+ font-weight: 700;
659
+ color: #000;
660
+ &-type {
661
+ line-height: 15px;
662
+ }
663
+ &-title {
664
+ font-weight: 400;
665
+ opacity: 0.8;
666
+ font-size: 11px;
667
+ }
668
+ &-amount {
669
+ color: #9e7b5a;
670
+ }
671
+ }
672
+ &-remark {
673
+ opacity: 0.3;
674
+ line-height: 15px;
675
+ font-size: 10px;
676
+ }
677
+ }
678
+ }
679
+ }
680
+ &-not-text {
681
+ opacity: 0.4;
682
+ color: #353535;
683
+ font-size: 12px;
684
+ line-height: 20px;
685
+ margin: 0 auto 40px;
686
+ text-align: center;
687
+ }
688
+ }
689
+ }
690
+ }
691
+ .rights-card{
692
+ margin: 10px 15px 0px;
693
+ background: #FFF8F3;
694
+ border-radius: 5px;
695
+ box-shadow: 0px 5px 18.9px 2px #0000000D;
696
+ padding: 15px 20px;
697
+ .title{
698
+ height: 25px;
699
+ line-height: 25px;
700
+ background: rgba($color: #FF8320, $alpha: 0.3);
701
+ border-radius: 20px 50px 50px 0px;
702
+ color: #353535;
703
+ font-size: 12px;
704
+ display: inline-block;
705
+ padding-left: 5px;
706
+ padding-right: 12px;
707
+ }
708
+ .list{
709
+ display: flex;
710
+ flex-wrap: wrap;
711
+ .item{
712
+ width: 50%;
713
+ margin-top: 15px;
714
+ .item-count{
715
+ font-size: 20px;
716
+ color:#353535;
717
+ font-weight: 700;
718
+ line-height: 23px;
719
+ }
720
+ .item-title{
721
+ line-height: 23px;
722
+ color: #987356;
723
+ font-size: 11px;
724
+ display: flex;
725
+ align-items: center;
726
+ .item-title-button{
727
+ padding: 0 27rpx;
728
+ height: 54rpx;
729
+ line-height: 54rpx;
730
+ background: -webkit-linear-gradient(262.82deg, #353535 10.04%, #433f46 90.21%);
731
+ background: linear-gradient(187.18deg, #353535 10.04%, #433f46 90.21%);
732
+ border-radius: 27rpx;
733
+ color: #E7CAAD;
734
+ font-size: 24rpx;
735
+ font-weight: 400;
736
+ margin-left: 40rpx;
737
+ display: flex;
738
+ align-items: center;
739
+ .button-icon{
740
+ display: block;
741
+ width: 24rpx;
742
+ height: 24rpx;
743
+ font-size: 0;
744
+ margin-left: 4px;
745
+ }
746
+ }
747
+ }
748
+ }
749
+ .star-item{
750
+ width: 100%;
751
+ }
752
+ }
753
+ }
754
+ </style>