@uxda/appkit 1.0.66 → 1.0.70

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.
@@ -9,11 +9,11 @@
9
9
  <div class="info">
10
10
  <div
11
11
  v-for="(it, i) in item.data"
12
- @click="() => onFilterSectionClick(index, it)"
13
- :class="getItemClass(index, it)"
12
+ @click="() => onFilterSectionClick(index, it.code)"
13
+ :class="getItemClass(index, it.code)"
14
14
  class="info-item"
15
15
  :key="i">
16
- {{ it }}
16
+ {{ typeof it === 'string' ? it : it.name }}
17
17
  </div>
18
18
  </div>
19
19
  </template>
@@ -27,25 +27,32 @@
27
27
  </template>
28
28
 
29
29
  <script lang="ts" setup>
30
- import { reactive } from 'vue'
30
+ import { reactive, ref } from 'vue'
31
31
  import {
32
32
  type ConsumptionDirection,
33
33
  type ConsumptionPosition,
34
34
  type ConsumptionType,
35
35
  consumptionDirections,
36
36
  consumptionPositions,
37
- consumptionTypes
37
+ consumptionTypes,
38
+ 权益类目,
38
39
  } from '../types'
40
+ import { endpoints, useHttp } from '../api'
41
+
42
+ const $http = useHttp()
39
43
 
40
44
  type ConsumptionFilterModelValue = [
41
45
  ConsumptionPosition | '全部',
42
46
  ConsumptionDirection | '全部',
43
47
  ConsumptionType | '全部',
48
+ string | '',
49
+
44
50
  ]
45
51
  type MixteValues =
46
52
  ConsumptionPosition |
47
53
  ConsumptionDirection |
48
- ConsumptionType | '全部'
54
+ ConsumptionType |
55
+ string |''
49
56
 
50
57
  interface ConsumptionFilterProps {
51
58
  modelValue: ConsumptionFilterModelValue
@@ -53,27 +60,42 @@ interface ConsumptionFilterProps {
53
60
 
54
61
  const props = withDefaults(
55
62
  defineProps<ConsumptionFilterProps>(), {
56
- modelValue: () => ['全部', '全部', '全部']
63
+ modelValue: () => ['全部', '全部', '全部', '']
57
64
  }
58
65
  )
59
66
  const emit = defineEmits(['complete'])
60
67
 
61
68
  const result = reactive<ConsumptionFilterModelValue>(props.modelValue)
62
69
 
63
- const filterSections = [
70
+ type FilterSecion = {
71
+ title: string,
72
+ data: {
73
+ code: string,
74
+ name: string
75
+ }[]
76
+ }
77
+
78
+ /**
79
+ * 筛选项目里面所有按钮
80
+ */
81
+ const filterSections = ref<FilterSecion[]>([
64
82
  {
65
83
  title: '类型',
66
- data: consumptionPositions,
84
+ data: consumptionPositions.map(s => ({code: s, name: s})),
67
85
  },
68
86
  {
69
87
  title: '收入/支出',
70
- data: consumptionDirections,
88
+ data: consumptionDirections.map(s => ({code: s, name: s})),
71
89
  },
72
90
  {
73
91
  title: '明细类型',
74
- data: consumptionTypes,
92
+ data: consumptionTypes.map(s => ({code: s, name: s})),
93
+ },
94
+ {
95
+ title: '权益类目',
96
+ data: []
75
97
  }
76
- ]
98
+ ])
77
99
 
78
100
  const getItemClass = (index: number, value) => result[index] === value ? ['current'] : ['']
79
101
 
@@ -85,13 +107,23 @@ const reset = () => {
85
107
  result[0] = '全部'
86
108
  result[1] = '全部'
87
109
  result[2] = '全部'
110
+ result[3] = ''
88
111
  }
89
112
 
90
- const onOkClick = () => {
91
- emit('complete', result)
113
+ const 请求权益类目 = () => {
114
+ $http.get<权益类目[]>(endpoints.获取权益类目).then(data => {
115
+ filterSections.value[3].data = [
116
+ { code: '', name: '全部' },
117
+ ...data
118
+ ]
119
+ })
92
120
  }
93
121
 
122
+ 请求权益类目()
94
123
 
124
+ const onOkClick = () => {
125
+ emit('complete', result)
126
+ }
95
127
  </script>
96
128
  <style lang="scss">
97
129
  .consumption-filter {
@@ -131,18 +163,9 @@ const onOkClick = () => {
131
163
  text-align: center;
132
164
  }
133
165
  .current {
134
- border: 1px solid;
135
- border-image-source: linear-gradient(
136
- 180deg,
137
- rgba(239, 208, 130, 0.8) 0%,
138
- rgba(255, 185, 120, 0.8) 100%
139
- );
140
- background: linear-gradient(
141
- 180deg,
142
- rgba(239, 208, 130, 0.8) 0%,
143
- rgba(255, 185, 120, 0.8) 100%
144
- ),
145
- linear-gradient(180deg, #fff7e3 0%, #fefde6 100%);
166
+ border-radius: 5px;
167
+ border: 1px solid #EFD082;
168
+ background: linear-gradient(180deg, #FFF7E3 0%, #FEFDE6 100%);
146
169
  }
147
170
  }
148
171
  }
@@ -36,7 +36,7 @@
36
36
  </template>
37
37
 
38
38
  <script lang="ts" setup>
39
- import { reactive, ref } from 'vue'
39
+ import { reactive, ref, watch } from 'vue'
40
40
 
41
41
  type DateFilterProps = {
42
42
  from: string,
@@ -45,7 +45,15 @@ type DateFilterProps = {
45
45
 
46
46
  const props = defineProps<DateFilterProps>()
47
47
 
48
- const emit = defineEmits(['complete'])
48
+ const emit = defineEmits(['complete', 'reset'])
49
+
50
+ watch(
51
+ () => `${props.from}${props.to}`,
52
+ () => {
53
+ result.from = props.from
54
+ result.to = props.to
55
+ }
56
+ )
49
57
 
50
58
  /**
51
59
  * 日期范围结果
@@ -66,8 +74,7 @@ const datePickerOpen = ref<boolean>(false)
66
74
  * 日期重置
67
75
  */
68
76
  function reset() {
69
- result.from = props.from
70
- result.to = props.to
77
+ emit('reset')
71
78
  }
72
79
 
73
80
  /**
@@ -0,0 +1,72 @@
1
+ <template>
2
+ <div class="second-balance">
3
+ <page-header title="小云豆余额" />
4
+ <div class="positions">
5
+ <div class="position"
6
+ v-for="(item, index) in data"
7
+ :key="index">
8
+ <div class="icon"></div>
9
+ <label class="title">{{ item.title }}</label>
10
+ <label class="number amount">{{ item.count }}</label>
11
+ </div>
12
+ </div>
13
+ </div>
14
+ </template>
15
+
16
+ <script lang="ts" setup>
17
+ import { Privilege } from '../types'
18
+
19
+ // 小云豆余额
20
+ // 由账户页 AccountView 使用 AppDrawer 弹出
21
+ type SecondBalanceProps = {
22
+ data: Privilege[]
23
+ }
24
+
25
+ withDefaults(
26
+ defineProps<SecondBalanceProps>(), {
27
+ data: () => []
28
+ }
29
+ )
30
+ </script>
31
+
32
+ <style lang="scss">
33
+ .second-balance {
34
+ width: 100vw;
35
+ .positions {
36
+ padding: 15px;
37
+ .position {
38
+ border-radius: 5px;
39
+ background: #F7F8FA;
40
+ height: 54px;
41
+ display: flex;
42
+ align-items: center;
43
+ justify-content: space-around;
44
+ margin-bottom: 10px;
45
+ padding: 0 10px;
46
+ gap: 10px;
47
+ .icon {
48
+ width: 30px;
49
+ height: 30px;
50
+ background-image:
51
+ url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIHZpZXdCb3g9IjAgMCA2MCA2MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE3LjIyODUgMzcuMjY0M0wxMy43OTk5IDQyLjc1QzEzLjYyODUgNDMuMDkyOSAxMy43OTk5IDQzLjUyMTQgMTQuMjI4NSA0My41MjE0TDE4Ljg1NzEgNDMuNzc4NkMxOS4wMjg1IDQzLjc3ODYgMTkuMTE0MiA0My44NjQzIDE5LjE5OTkgNDMuOTVMMjIuMDI4NSA0Ny43MjE0QzIyLjI4NTcgNDcuOTc4NiAyMi43MTQyIDQ3Ljk3ODYgMjIuODg1NyA0Ny43MjE0TDI2LjE0MjggNDIuMzIxNEMyNi4zMTQyIDQyLjA2NDMgMjYuMjI4NSA0MS44MDcxIDI1Ljk3MTQgNDEuNjM1N0wxNy45MTQyIDM3LjA5MjlDMTcuNjU3MSAzNy4wMDcxIDE3LjM5OTkgMzcuMDkyOSAxNy4yMjg1IDM3LjI2NDNaTTQyLjc3MTQgMzcuMTc4Nkw0Ni4xOTk5IDQyLjY2NDNDNDYuMzcxNCA0My4wMDcxIDQ2LjE5OTkgNDMuNDM1NyA0NS43NzE0IDQzLjQzNTdMNDEuMTQyOCA0My42OTI5QzQwLjk3MTQgNDMuNjkyOSA0MC44ODU3IDQzLjc3ODYgNDAuNzk5OSA0My44NjQzTDM3Ljk3MTQgNDcuNjM1N0MzNy43MTQyIDQ3Ljg5MjkgMzcuMjg1NyA0Ny44OTI5IDM3LjExNDIgNDcuNjM1N0wzMy44NTcxIDQyLjIzNTdDMzMuNjg1NyA0MS45Nzg2IDMzLjc3MTQgNDEuNzIxNCAzNC4wMjg1IDQxLjU1TDQyLjA4NTcgMzcuMDA3MUM0Mi4zNDI4IDM2LjgzNTcgNDIuNTk5OSAzNi45MjE0IDQyLjc3MTQgMzcuMTc4NlpNNDIuMDg1NyAxOC40OTI5TDMxLjE5OTkgMTIuMzIxNEMzMC40Mjg1IDExLjg5MjkgMjkuMzk5OSAxMS44OTI5IDI4LjYyODUgMTIuMzIxNEwxNy44Mjg1IDE4LjQwNzFDMTcuMDU3MSAxOC44MzU3IDE2LjU0MjggMTkuNjkyOSAxNi41NDI4IDIwLjU1VjMyLjgwNzFDMTYuNTQyOCAzMy42NjQzIDE3LjA1NzEgMzQuNTIxNCAxNy44Mjg1IDM0Ljk1TDI4LjcxNDIgNDEuMTIxNEMyOS40ODU3IDQxLjU1IDMwLjUxNDIgNDEuNTUgMzEuMjg1NyA0MS4xMjE0TDQyLjA4NTcgMzUuMTIxNEM0Mi44NTcxIDM0LjY5MjkgNDMuMzcxNCAzMy44MzU3IDQzLjM3MTQgMzIuOTc4NlYyMC43MjE0QzQzLjM3MTQgMTkuNzc4NiA0Mi44NTcxIDE4LjkyMTQgNDIuMDg1NyAxOC40OTI5Wk0zNi45NDI4IDIzLjcyMTRMMzAuNTk5OSAzMi44OTI5QzMwLjQyODUgMzMuMTUgMzAuMDg1NyAzMy4zMjE0IDI5Ljc0MjggMzMuMzIxNEMyOS4zOTk5IDMzLjMyMTQgMjkuMDU3MSAzMy4xNSAyOC44ODU3IDMyLjg5MjlMMjIuNzk5OSAyMy43MjE0QzIyLjQ1NzEgMjMuMjkyOSAyMi42Mjg1IDIyLjYwNzEgMjMuMDU3MSAyMi4zNUMyMy40ODU3IDIyLjA5MjkgMjQuMTcxNCAyMi4xNzg2IDI0LjQyODUgMjIuNjA3MUwyOS42NTcxIDMwLjQ5MjlMMzUuMTQyOCAyMi41MjE0QzM1LjQ4NTcgMjIuMDkyOSAzNi4wODU3IDIxLjkyMTQgMzYuNTE0MiAyMi4yNjQzQzM3LjE5OTkgMjIuNjkyOSAzNy4yODU3IDIzLjI5MjkgMzYuOTQyOCAyMy43MjE0WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+Cg=="),
52
+ linear-gradient(100deg, #F4E2CE -67.2%, #DEBB9B 98.15%);
53
+ background-repeat: no-repeat;
54
+ border-radius: 15px;
55
+ background-size: 30px;
56
+ flex-basis: 30px;
57
+ flex-grow: 0;
58
+ }
59
+ .title {
60
+ flex-grow: 1;color: #353535;
61
+ font-size: 14px;
62
+ font-weight: 500;
63
+ }
64
+ .amount {
65
+ flex-grow: 0;color: #9E7B5A;
66
+ font-size: 14px;
67
+ font-weight: 700;
68
+ }
69
+ }
70
+ }
71
+ }
72
+ </style>
@@ -31,7 +31,7 @@ export type ConsumptionDirection = typeof consumptionDirections[number]
31
31
  /**
32
32
  * 账户流水
33
33
  */
34
- export type Consumption = {
34
+ export type 账户流水 = {
35
35
  /**
36
36
  * 数量
37
37
  */
@@ -51,42 +51,47 @@ export type Consumption = {
51
51
  /**
52
52
  * 交易类型类型
53
53
  */
54
- type: ConsumptionType,
54
+ 交易类型: ConsumptionType,
55
+ 权益类目: string,
55
56
  /**
56
57
  * 账户类型
57
58
  */
58
- position: ConsumptionPosition
59
+ 账户类型: ConsumptionPosition
59
60
  /**
60
61
  * 收入/支出
61
62
  */
62
- direction: ConsumptionDirection
63
+ 收入还是支出: ConsumptionDirection
63
64
  }
64
65
 
65
66
  /**
66
67
  * 账户流水筛选项
67
68
  */
68
- export type ConsumptionFiltering = Pick<Consumption, 'type' | 'position' | 'direction'> & {
69
+ export type 账户流水筛选项 = Pick<
70
+ 账户流水,
71
+ '交易类型' | '账户类型' | '收入还是支出' | '权益类目'
72
+ > & {
69
73
  dateFrom: string,
70
- dateTo: string
74
+ dateTo: string,
75
+ page: number,
76
+ pageSize: 20,
71
77
  }
72
78
 
73
79
  export type ConsumptionGroup = {
74
80
  date: string,
75
- consumptions: Consumption[]
76
- }
77
-
78
- export type ConsumptionGroups = {
79
- list: ConsumptionGroup[]
80
- from: string,
81
- to: string,
81
+ consumptions: 账户流水[]
82
82
  }
83
83
 
84
84
  export type Privilege = {
85
85
  title: string,
86
- amount: number
86
+ count: number
87
87
  }
88
88
 
89
89
  export type Balance = {
90
90
  total: number,
91
91
  privileges: Privilege[]
92
- }
92
+ }
93
+
94
+ export type 权益类目 = {
95
+ name: string,
96
+ code: string
97
+ }
package/src/index.ts CHANGED
@@ -8,9 +8,7 @@ import {
8
8
  Checkbox,
9
9
  Popup,
10
10
  OverLay,
11
- Icon,
12
11
  DatePicker,
13
- Picker,
14
12
  } from '@nutui/nutui-taro'
15
13
  import { type AppKitOptions, useAppKitOptions, DollarApp } from './Appkit'
16
14
  import { PaymentParams, RechargeParams } from './payment/types'
@@ -23,9 +21,7 @@ const nutComponents = [
23
21
  Checkbox,
24
22
  Popup,
25
23
  OverLay,
26
- Icon,
27
24
  DatePicker,
28
- Picker,
29
25
  ]
30
26
 
31
27
  const appComponents = {
@@ -7,7 +7,7 @@ const endpointsList: HttpEndpoints = {
7
7
  * (查询某应用某场景可充值的金额列表)
8
8
  * http://ytech.dev.ddjf.info/payment/doc.html#/%E5%AE%A2%E6%88%B7%E5%9F%9FAPI/%E6%94%AF%E4%BB%98%E4%B8%AD%E5%BF%83-%E5%AF%B9%E5%A4%96%E6%8E%A5%E5%8F%A3/getRechargeListUsingGET
9
9
  */
10
- getPackages: {
10
+ 获取充值金额列表: {
11
11
  path: '/payment/outer/payment/getRechargeList',
12
12
  translate: (data: any) => ({
13
13
  appCode: data.app,
@@ -24,7 +24,7 @@ const endpointsList: HttpEndpoints = {
24
24
  * (获取拉起微信支付用的JSON串)
25
25
  * http://ytech.dev.ddjf.info/payment/doc.html#/%E5%AE%A2%E6%88%B7%E5%9F%9FAPI/%E6%94%AF%E4%BB%98%E4%B8%AD%E5%BF%83-%E5%AF%B9%E5%A4%96%E6%8E%A5%E5%8F%A3/rechargePayUsingPOST
26
26
  */
27
- getPayParams: {
27
+ 获取微信支付参数包: {
28
28
  // {
29
29
  // "amount": 100,
30
30
  // "appCode": "crm",
@@ -54,9 +54,13 @@ const endpointsList: HttpEndpoints = {
54
54
  }
55
55
  }
56
56
  }
57
- }
57
+ } as const
58
58
 
59
- const endpoints = Object.fromEntries(
59
+ const keys = Object.keys(endpointsList as any)
60
+
61
+ type Keys = typeof keys[number]
62
+
63
+ const endpoints: Record<Keys, string> = Object.fromEntries(
60
64
  Object.entries(endpointsList).map(([name, def]) => [name, def.path])
61
65
  )
62
66
 
@@ -1,24 +1,63 @@
1
- import { useHttp } from '../../shared'
1
+ import Taro from '@tarojs/taro'
2
+ import { HttpRequestConfig, ResponseRaw, createHttp } from '../../shared'
2
3
  import { translates, transforms } from './endpoints'
3
4
  import { useAppKitOptions } from '../../Appkit'
4
5
 
5
- const makeHttp = () => {
6
- const appkitOptions = useAppKitOptions()
7
- console.log('===makeHTTP===tempToken:', appkitOptions.tempToken())
8
6
 
9
- const token = appkitOptions.tempToken() || appkitOptions.token()
10
- const header = {
11
- Token: token,
7
+ /**
8
+ * 小程序端 Http
9
+ * 使用 Taro.request 实现
10
+ */
11
+ const vendor = {
12
+ async request <T>(config: HttpRequestConfig) {
13
+ return new Promise<ResponseRaw<T>>((resolve, reject) => {
14
+ Taro.request({
15
+ url: config.url,
16
+ method: config.method,
17
+ header: config.headers,
18
+ data: config.data
19
+ }).then(({data}) => {
20
+ resolve({
21
+ status: data.code,
22
+ message: data.msg,
23
+ data: data.result as T
24
+ })
25
+ }).catch((e: any) => {
26
+ reject(e)
27
+ })
28
+ })
29
+ }
30
+ }
31
+
32
+ function useHttp () {
33
+ const appkitOptions = useAppKitOptions()
34
+ const headers = {
35
+ Token: appkitOptions.token(),
12
36
  Appcode: appkitOptions.app(),
13
37
  cookie: `tid=${appkitOptions.tenant()}`
14
38
  }
15
-
16
- const $http = useHttp({
39
+ /**
40
+ * 传入配置获取 Http instanse
41
+ */
42
+ const $http = createHttp({
43
+ vendor,
17
44
  baseUrl: appkitOptions.baseUrl(),
18
- header,
19
- onAuthError: () => {
20
- appkitOptions['401']()
21
- },
45
+ headers,
46
+ interceptors: [
47
+ raw => {
48
+ if (raw.status == 401) {
49
+ appkitOptions[401]()
50
+ return true
51
+ }
52
+ return false
53
+ },
54
+ raw => {
55
+ if (raw.status > 500) {
56
+ return true
57
+ }
58
+ return false
59
+ }
60
+ ],
22
61
  translates,
23
62
  transforms,
24
63
  })
@@ -26,7 +65,7 @@ const makeHttp = () => {
26
65
  }
27
66
 
28
67
  export {
29
- makeHttp
68
+ useHttp
30
69
  }
31
70
 
32
71
  export * from './endpoints'
@@ -28,7 +28,7 @@ import { onMounted, reactive, ref } from 'vue'
28
28
  import AmountPicker from './AmountPicker.vue'
29
29
  import UserAgreement from './UserAgreement.vue'
30
30
  import { AppDrawer } from '../../shared'
31
- import { makeHttp, endpoints } from '../api'
31
+ import { useHttp, endpoints } from '../api'
32
32
  import { requestPayment } from '../services'
33
33
  import Taro from '@tarojs/taro'
34
34
 
@@ -75,8 +75,8 @@ const onAmountSelect = (selected: number) => {
75
75
  }
76
76
 
77
77
  onMounted(() => {
78
- const $http = makeHttp()
79
- $http.get<any[]>(endpoints.getPackages, {
78
+ const $http = useHttp()
79
+ $http.get<any[]>(endpoints.获取充值金额列表, {
80
80
  app: props.app,
81
81
  // stage: 'aiApproveRecharge', // 支付场景
82
82
  tenant: props.tenant
@@ -1,12 +1,12 @@
1
1
  import { PaymentParams } from '../types'
2
2
  import { DollarApp } from '../../Appkit'
3
- import { makeHttp, endpoints } from '../../payment/api'
3
+ import { useHttp, endpoints } from '../../payment/api'
4
4
  import { requestPayment as weappRequestPayment } from '../../shared'
5
5
 
6
6
  const requestPayment = (params: PaymentParams) => {
7
7
  return new Promise<boolean>((resolve, reject) => {
8
- const $http = makeHttp()
9
- $http.post(endpoints.getPayParams, {
8
+ const $http = useHttp()
9
+ $http.post(endpoints.获取微信支付参数包, {
10
10
  ...params,
11
11
  // amount: 0.01,
12
12
  }).then(response => {
@@ -0,0 +1,34 @@
1
+ <template>
2
+ <div class="empty-view">
3
+ <img
4
+ class="empty-view-image"
5
+ src="https://cdn.ddjf.com/static/images/nutshell/empty-data.png" />
6
+ <div class="empty-view-text">暂无数据</div>
7
+ </div>
8
+ </template>
9
+
10
+ <script lang="ts" setup>
11
+ </script>
12
+
13
+ <style lang="scss">
14
+ .empty-view {
15
+ display: flex;
16
+ flex-direction: column;
17
+ justify-content: center;
18
+ align-items: center;
19
+ margin-top: 80px;
20
+ &-image {
21
+ display: block;
22
+ font-size: 0;
23
+ width: 144px;
24
+ height: 80px;
25
+ filter: grayscale(1);
26
+ }
27
+ &-text {
28
+ opacity: 0.4;
29
+ color: #353535;
30
+ font-size: 12px;
31
+ line-height: 28px;
32
+ }
33
+ }
34
+ </style>
@@ -1,15 +1,24 @@
1
1
  <template>
2
- <view :class="[
2
+ <div :class="[
3
3
  'page-header',
4
4
  `color-mode-${colorMode}`
5
- ]">
5
+ ]" :style="cssVars">
6
6
  <h1 class="page-title" v-if="title">{{ title }}</h1>
7
7
  <view class="back-button" @click="onBackButtonClick"></view>
8
8
  <slot></slot>
9
- </view>
9
+ </div>
10
10
  </template>
11
11
 
12
12
  <script lang="ts" setup>
13
+ import { useSafeArea } from '../composables'
14
+
15
+
16
+ const safeArea = useSafeArea()
17
+
18
+ const cssVars = {
19
+ '--top': `${safeArea.status}px`,
20
+ '--height': `${safeArea.nav}px`
21
+ }
13
22
 
14
23
  export type PageHeaderColorMode = 'light' | 'dark'
15
24
 
@@ -36,29 +45,28 @@ const onBackButtonClick = () => {
36
45
 
37
46
  <style lang="scss">
38
47
  .page-header {
39
- flex-shrink: 0;
48
+ display: flex;
40
49
  position: relative;
41
- padding-top: 44px;
42
- height: 88px;
43
- box-sizing: border-box;
50
+ align-items: center;
51
+ padding-top: var(--top);
52
+ min-height: var(--height);
44
53
  .page-title {
45
54
  position: absolute;
46
55
  font-size: 18px;
56
+ height: var(--height);
57
+ line-height: var(--height);
58
+ top: var(--top);
47
59
  width: 100%;
48
- height: 44px;
49
- top: 44px;
50
- left: 0;
51
- line-height: 44px;
52
60
  text-align: center;
53
61
  }
54
62
  .back-button {
55
63
  position: absolute;
56
- top: 44px;
64
+ top: var(--top);
57
65
  left: 10px;
58
- width: 44px;
59
- height: 44px;
66
+ width: var(--height);
67
+ height: var(--height);
60
68
  background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDIiIGhlaWdodD0iNDIiIHZpZXdCb3g9IjAgMCA0MiA0MiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggb3BhY2l0eT0iMC4wMSIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0wLjk5OTg3OCA0MUw0MC45OTk5IDQxTDQwLjk5OTkgMUwwLjk5OTg3OCAxTDAuOTk5ODc4IDQxWiIgZmlsbD0iI0Q4RDhEOCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMDEiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMi45OTMzIDE4Ljk0NzdDMTEuODYzMyAyMC4wMTQ1IDExLjgxMiAyMS43OTU0IDEyLjg3ODggMjIuOTI1NUwyNy45MTA1IDM3LjEzNDVDMjguNjkyNSAzNy44NzM0IDI5LjkyNTUgMzcuODM4NCAzMC42NjQ0IDM3LjA1NjRDMzEuMzY4MSAzNi4zMTE2IDMxLjM2OTkgMzUuMTU3OSAzMC42OTI5IDM0LjQxMTRMMTYuNTAxMiAyMC45OTM5TDMwLjU4NTcgNy42OTc4NUMzMS4zMzA4IDYuOTk0NDkgMzEuMjk4MiA1LjcyNzk1IDMwLjY2NDkgNC45NDQwMkMyOS45NjE2IDQuMTk4OTUgMjguODA5OCA0LjEzMTI5IDI4LjAyNTkgNC43NjQ1MkwxMi45OTMzIDE4Ljk0NzdaIiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMDEiLz4KPC9zdmc+Cg==");
61
- background-size: 22px;
69
+ background-size: 50%;
62
70
  background-repeat: no-repeat;
63
71
  background-position: center center;
64
72
  }
@@ -1,5 +1 @@
1
- export {
2
- BusSymbol,
3
- createBus,
4
- useBus,
5
- } from './bus'
1
+ export * from './useSafeArea'
@@ -0,0 +1,42 @@
1
+ import Taro from '@tarojs/taro'
2
+ /**
3
+ * 屏幕安全区域
4
+ */
5
+ export type SafeArea = {
6
+ /**
7
+ * 状态条高度
8
+ */
9
+ status: number,
10
+ /**
11
+ * 导航条区域(胶囊)
12
+ */
13
+ nav: number,
14
+ /**
15
+ * 屏幕底部范围
16
+ */
17
+ bottom: number
18
+ }
19
+
20
+ /**
21
+ * 获取屏幕安全区域
22
+ * 从系统 API 获取
23
+ * @returns
24
+ */
25
+ export function useSafeArea (): SafeArea {
26
+ const systemInfo = Taro.getSystemInfoSync(),
27
+ capsule = Taro.getMenuButtonBoundingClientRect()
28
+ /**
29
+ * 状态条高度
30
+ */
31
+ const status = systemInfo.statusBarHeight || 0,
32
+ /**
33
+ * 据说是胶囊上下间距
34
+ */
35
+ gap = capsule.top - status,
36
+ nav = capsule.height + gap * 2
37
+ return {
38
+ status,
39
+ nav,
40
+ bottom: systemInfo.safeArea?.bottom || 0
41
+ }
42
+ }