oxy-uni-ui 1.2.3 → 2.1.0

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 (246) hide show
  1. package/attributes.json +1 -1
  2. package/components/common/abstracts/variable.scss +512 -343
  3. package/components/common/util.ts +185 -32
  4. package/components/composables/index.ts +1 -0
  5. package/components/composables/usePopover.ts +24 -20
  6. package/components/composables/useVirtualScroll.ts +48 -21
  7. package/components/composables/useWindowResize.ts +35 -0
  8. package/components/oxy-action-sheet/index.scss +24 -11
  9. package/components/oxy-action-sheet/oxy-action-sheet.vue +27 -19
  10. package/components/oxy-action-sheet/types.ts +7 -0
  11. package/components/oxy-backtop/index.scss +4 -4
  12. package/components/oxy-backtop/oxy-backtop.vue +9 -6
  13. package/components/oxy-backtop/types.ts +7 -7
  14. package/components/oxy-badge/index.scss +4 -4
  15. package/components/oxy-badge/oxy-badge.vue +3 -3
  16. package/components/oxy-badge/types.ts +2 -2
  17. package/components/oxy-button/index.scss +5 -5
  18. package/components/oxy-button/oxy-button.vue +5 -1
  19. package/components/oxy-calendar/index.scss +15 -15
  20. package/components/oxy-calendar/oxy-calendar.vue +1 -0
  21. package/components/oxy-calendar/types.ts +5 -0
  22. package/components/oxy-calendar-view/month/index.scss +4 -4
  23. package/components/oxy-calendar-view/month/types.ts +36 -0
  24. package/components/oxy-calendar-view/monthPanel/index.scss +7 -8
  25. package/components/oxy-calendar-view/monthPanel/month-panel.vue +14 -8
  26. package/components/oxy-calendar-view/year/index.scss +5 -5
  27. package/components/oxy-calendar-view/yearPanel/index.scss +4 -4
  28. package/components/oxy-calendar-view/yearPanel/year-panel.vue +21 -5
  29. package/components/oxy-card/index.scss +2 -2
  30. package/components/oxy-cell/index.scss +8 -8
  31. package/components/oxy-checkbox/index.scss +12 -12
  32. package/components/oxy-checkbox-group/index.scss +2 -2
  33. package/components/oxy-circle/oxy-circle.vue +10 -7
  34. package/components/oxy-circle/types.ts +5 -5
  35. package/components/oxy-col/oxy-col.vue +2 -2
  36. package/components/oxy-col-picker/index.scss +4 -4
  37. package/components/oxy-col-picker/oxy-col-picker.vue +6 -5
  38. package/components/oxy-col-picker/types.ts +7 -2
  39. package/components/oxy-collapse/index.scss +2 -2
  40. package/components/oxy-collapse-item/oxy-collapse-item.vue +3 -3
  41. package/components/oxy-corner/index.scss +33 -33
  42. package/components/oxy-count-to/oxy-count-to.vue +3 -3
  43. package/components/oxy-curtain/index.scss +15 -15
  44. package/components/oxy-curtain/oxy-curtain.vue +4 -2
  45. package/components/oxy-curtain/types.ts +6 -1
  46. package/components/oxy-date-strip/oxy-date-strip.vue +2 -2
  47. package/components/oxy-date-strip/types.ts +1 -1
  48. package/components/oxy-date-strip-item/index.scss +3 -3
  49. package/components/oxy-datetime-picker/index.scss +11 -11
  50. package/components/oxy-datetime-picker/oxy-datetime-picker.vue +1 -0
  51. package/components/oxy-datetime-picker/types.ts +5 -0
  52. package/components/oxy-drop-menu/index.scss +5 -5
  53. package/components/oxy-drop-menu/oxy-drop-menu.vue +3 -3
  54. package/components/oxy-drop-menu-item/index.scss +3 -3
  55. package/components/oxy-drop-menu-item/oxy-drop-menu-item.vue +4 -3
  56. package/components/oxy-drop-menu-item/types.ts +5 -0
  57. package/components/oxy-echarts/types.ts +6 -0
  58. package/components/oxy-fab/index.scss +8 -8
  59. package/components/oxy-fab/oxy-fab.vue +22 -3
  60. package/components/oxy-file-list/index.scss +30 -29
  61. package/components/oxy-file-list/oxy-file-list.vue +2 -2
  62. package/components/oxy-floating-panel/oxy-floating-panel.vue +13 -9
  63. package/components/oxy-floating-panel/{type.ts → types.ts} +8 -8
  64. package/components/oxy-footer/index.scss +19 -0
  65. package/components/oxy-footer/oxy-footer.vue +78 -0
  66. package/components/oxy-footer/types.ts +17 -0
  67. package/components/oxy-form-item/types.ts +22 -1
  68. package/components/oxy-gap/oxy-gap.vue +2 -2
  69. package/components/oxy-gap/types.ts +2 -2
  70. package/components/oxy-grid/oxy-grid.vue +1 -1
  71. package/components/oxy-grid/types.ts +1 -1
  72. package/components/oxy-grid-item/index.scss +1 -1
  73. package/components/oxy-grid-item/oxy-grid-item.vue +7 -5
  74. package/components/oxy-grid-item/types.ts +1 -1
  75. package/components/oxy-guidance/index.scss +75 -0
  76. package/components/oxy-guidance/oxy-guidance.vue +201 -0
  77. package/components/oxy-guidance/types.ts +33 -0
  78. package/components/oxy-icon/oxy-icon.vue +2 -2
  79. package/components/oxy-icon/types.ts +1 -1
  80. package/components/oxy-img/oxy-img.vue +4 -4
  81. package/components/oxy-img/types.ts +3 -3
  82. package/components/oxy-img-cropper/index.scss +23 -23
  83. package/components/oxy-img-cropper/oxy-img-cropper.vue +97 -52
  84. package/components/oxy-img-cropper/types.ts +2 -2
  85. package/components/oxy-img-lazy/oxy-img-lazy.vue +3 -3
  86. package/components/oxy-img-lazy/types.ts +3 -3
  87. package/components/oxy-index-anchor/index.scss +2 -2
  88. package/components/oxy-index-anchor/oxy-index-anchor.vue +2 -2
  89. package/components/oxy-index-anchor/{type.ts → types.ts} +3 -0
  90. package/components/oxy-index-bar/index.scss +3 -3
  91. package/components/oxy-index-bar/oxy-index-bar.vue +3 -3
  92. package/components/oxy-index-bar/{type.ts → types.ts} +2 -2
  93. package/components/oxy-input/index.scss +1 -1
  94. package/components/oxy-input-number/index.scss +5 -5
  95. package/components/oxy-input-number/oxy-input-number.vue +2 -2
  96. package/components/oxy-input-number/types.ts +3 -2
  97. package/components/oxy-keyboard/index.scss +5 -5
  98. package/components/oxy-keyboard/key/index.scss +3 -3
  99. package/components/oxy-keyboard/key/index.vue +2 -2
  100. package/components/oxy-keyboard/key/types.ts +15 -0
  101. package/components/oxy-keyboard/oxy-keyboard.vue +1 -0
  102. package/components/oxy-keyboard/types.ts +5 -0
  103. package/components/oxy-link/index.scss +2 -2
  104. package/components/oxy-list/oxy-list.vue +4 -3
  105. package/components/oxy-loading/oxy-loading.vue +8 -4
  106. package/components/oxy-loading/types.ts +1 -1
  107. package/components/oxy-loadmore/index.scss +3 -3
  108. package/components/oxy-long-press-menu/index.scss +93 -0
  109. package/components/oxy-long-press-menu/oxy-long-press-menu.vue +338 -0
  110. package/components/oxy-long-press-menu/types.ts +34 -0
  111. package/components/oxy-message-box/index.scss +12 -11
  112. package/components/oxy-message-box/oxy-message-box.vue +9 -2
  113. package/components/oxy-message-box/types.ts +9 -0
  114. package/components/oxy-navbar/index.scss +2 -2
  115. package/components/oxy-navbar/oxy-navbar.vue +58 -13
  116. package/components/oxy-navbar/types.ts +8 -1
  117. package/components/oxy-navbar-capsule/types.ts +3 -0
  118. package/components/oxy-notice-bar/index.scss +3 -3
  119. package/components/oxy-notice-bar/oxy-notice-bar.vue +9 -5
  120. package/components/oxy-notice-bar/types.ts +3 -3
  121. package/components/oxy-notify/index.ts +1 -0
  122. package/components/oxy-notify/oxy-notify.vue +3 -2
  123. package/components/oxy-notify/types.ts +7 -0
  124. package/components/oxy-pagination/index.scss +6 -5
  125. package/components/oxy-password-input/oxy-password-input.vue +2 -2
  126. package/components/oxy-password-input/types.ts +1 -1
  127. package/components/oxy-picker/index.scss +45 -2
  128. package/components/oxy-picker/oxy-picker.vue +100 -14
  129. package/components/oxy-picker/types.ts +29 -1
  130. package/components/oxy-picker-view/index.scss +4 -4
  131. package/components/oxy-picker-view/oxy-picker-view.vue +4 -4
  132. package/components/oxy-popover/index.scss +13 -13
  133. package/components/oxy-popup/index.scss +4 -4
  134. package/components/oxy-popup/oxy-popup.vue +35 -2
  135. package/components/oxy-popup/types.ts +8 -1
  136. package/components/oxy-progress/index.scss +3 -3
  137. package/components/oxy-qrcode/draw.ts +398 -0
  138. package/components/oxy-qrcode/index.scss +2 -0
  139. package/components/oxy-qrcode/oxy-qrcode.vue +124 -0
  140. package/components/oxy-qrcode/qrcode.ts +936 -0
  141. package/components/oxy-qrcode/types.ts +42 -0
  142. package/components/oxy-radio/index.scss +25 -19
  143. package/components/oxy-radio-group/index.scss +2 -2
  144. package/components/oxy-rate/types.ts +4 -4
  145. package/components/oxy-resize/index.scss +2 -2
  146. package/components/oxy-resize/oxy-resize.vue +4 -4
  147. package/components/oxy-resize/types.ts +3 -0
  148. package/components/oxy-rich-text/index.scss +37 -36
  149. package/components/oxy-rich-text/mp-html/card/card.vue +3 -3
  150. package/components/oxy-rich-text/mp-html/mp-html.vue +33 -24
  151. package/components/oxy-rich-text/mp-html/node/node.vue +30 -19
  152. package/components/oxy-rich-text/oxy-rich-text.vue +31 -31
  153. package/components/oxy-rich-text/types.ts +6 -1
  154. package/components/oxy-row/oxy-row.vue +3 -3
  155. package/components/oxy-row/types.ts +1 -1
  156. package/components/oxy-search/index.scss +7 -7
  157. package/components/oxy-segmented/index.scss +19 -16
  158. package/components/oxy-segmented/oxy-segmented.vue +23 -3
  159. package/components/oxy-select/index.scss +213 -89
  160. package/components/oxy-select/oxy-select.vue +106 -58
  161. package/components/oxy-select/types.ts +13 -1
  162. package/components/oxy-select-picker/index.scss +7 -7
  163. package/components/oxy-select-picker/oxy-select-picker.vue +1 -0
  164. package/components/oxy-select-picker/types.ts +2 -0
  165. package/components/oxy-sidebar-item/index.scss +2 -2
  166. package/components/oxy-signature/oxy-signature.vue +18 -10
  167. package/components/oxy-signature/types.ts +106 -13
  168. package/components/oxy-skeleton/index.scss +1 -1
  169. package/components/oxy-skeleton/oxy-skeleton.vue +6 -6
  170. package/components/oxy-skeleton/types.ts +1 -1
  171. package/components/oxy-slider/index.scss +6 -6
  172. package/components/oxy-sort-button/index.scss +8 -8
  173. package/components/oxy-splitter/index.scss +19 -0
  174. package/components/oxy-splitter/oxy-splitter.vue +409 -0
  175. package/components/oxy-splitter/types.ts +75 -0
  176. package/components/oxy-splitter-panel/index.scss +366 -0
  177. package/components/oxy-splitter-panel/oxy-splitter-panel.vue +432 -0
  178. package/components/oxy-splitter-panel/types.ts +63 -0
  179. package/components/oxy-status-tip/index.scss +4 -4
  180. package/components/oxy-status-tip/oxy-status-tip.vue +5 -5
  181. package/components/oxy-status-tip/types.ts +3 -3
  182. package/components/oxy-step/index.scss +16 -16
  183. package/components/oxy-sticky/oxy-sticky.vue +6 -6
  184. package/components/oxy-stream-render/oxy-stream-render.vue +230 -4
  185. package/components/oxy-stream-render/types.ts +4 -1
  186. package/components/oxy-swipe-action/oxy-swipe-action.vue +27 -2
  187. package/components/oxy-swiper/oxy-swiper.vue +6 -6
  188. package/components/oxy-swiper/types.ts +5 -5
  189. package/components/oxy-swiper-nav/index.scss +3 -3
  190. package/components/oxy-switch/index.scss +10 -10
  191. package/components/oxy-switch/oxy-switch.vue +2 -2
  192. package/components/oxy-switch/types.ts +1 -1
  193. package/components/oxy-tab/index.scss +11 -1
  194. package/components/oxy-tabbar/index.scss +2 -2
  195. package/components/oxy-tabbar/oxy-tabbar.vue +39 -10
  196. package/components/oxy-table/index.scss +8 -8
  197. package/components/oxy-table/oxy-table.vue +8 -6
  198. package/components/oxy-table/types.ts +2 -2
  199. package/components/oxy-table-col/index.scss +3 -3
  200. package/components/oxy-table-col/oxy-table-col.vue +3 -3
  201. package/components/oxy-table-col/types.ts +2 -2
  202. package/components/oxy-tabs/index.scss +52 -22
  203. package/components/oxy-tabs/oxy-tabs.vue +53 -19
  204. package/components/oxy-tabs/types.ts +15 -3
  205. package/components/oxy-tag/index.scss +111 -36
  206. package/components/oxy-text/index.scss +5 -1
  207. package/components/oxy-text/oxy-text.vue +76 -7
  208. package/components/oxy-text/types.ts +12 -0
  209. package/components/oxy-textarea/index.scss +6 -6
  210. package/components/oxy-toast/oxy-toast.vue +24 -8
  211. package/components/oxy-tooltip/index.scss +9 -9
  212. package/components/oxy-tree/index.scss +51 -15
  213. package/components/oxy-tree/oxy-tree.vue +13 -9
  214. package/components/oxy-tree/types.ts +12 -9
  215. package/components/oxy-upload/index.scss +23 -23
  216. package/components/oxy-upload/types.ts +2 -2
  217. package/components/oxy-verification-code/index.scss +6 -0
  218. package/components/oxy-verification-code/oxy-verification-code.vue +187 -0
  219. package/components/oxy-verification-code/types.ts +82 -0
  220. package/components/oxy-video-preview/index.scss +4 -4
  221. package/components/oxy-virtual-scroll/index.scss +5 -5
  222. package/components/oxy-virtual-scroll/oxy-virtual-scroll.vue +11 -7
  223. package/components/oxy-virtual-scroll/types.ts +14 -14
  224. package/components/oxy-voice-player/index.scss +937 -0
  225. package/components/oxy-voice-player/oxy-voice-player.vue +821 -0
  226. package/components/oxy-voice-player/types.ts +567 -0
  227. package/components/oxy-waterfall/oxy-waterfall.vue +6 -6
  228. package/components/oxy-waterfall/types.ts +6 -6
  229. package/components/oxy-watermark/oxy-watermark.vue +35 -13
  230. package/components/oxy-watermark/types.ts +14 -14
  231. package/global.d.ts +4 -0
  232. package/locale/lang/ar-SA.ts +3 -0
  233. package/locale/lang/en-US.ts +3 -0
  234. package/locale/lang/zh-CN.ts +3 -0
  235. package/package.json +97 -1
  236. package/tags.json +1 -1
  237. package/web-types.json +1 -1
  238. package/components/oxy-number-keyboard/index.scss +0 -78
  239. package/components/oxy-number-keyboard/key/index.scss +0 -81
  240. package/components/oxy-number-keyboard/key/index.vue +0 -78
  241. package/components/oxy-number-keyboard/key/types.ts +0 -11
  242. package/components/oxy-number-keyboard/oxy-number-keyboard.vue +0 -151
  243. package/components/oxy-number-keyboard/types.ts +0 -83
  244. package/components/oxy-tree/components/tree-node-content.vue +0 -72
  245. package/components/oxy-tree/index.ts +0 -51
  246. package/oxy-uni-ui.zip +0 -0
@@ -1,31 +1,43 @@
1
1
  <template>
2
- <view :class="`oxy-select ${customClass}`" :style="rootStyle">
2
+ <view :class="rootClass" :style="rootStyle">
3
3
  <view v-if="label" class="oxy-select__label" :style="labelStyle">
4
4
  <slot name="label">{{ label }}</slot>
5
5
  </view>
6
6
  <view class="oxy-select__box">
7
- <view :class="['oxy-select__wrapper', { 'is-disabled': disabled, 'is-readonly': readonly }]">
7
+ <view :class="['oxy-select__wrapper', { 'is-disabled': disabled, 'is-readonly': readonly, 'is-focus': showSelector }]">
8
8
  <view class="oxy-select__input-box" @click="toggleSelector">
9
9
  <view class="oxy-select__tags" v-if="multiple && currentList.length > 0">
10
- <view class="oxy-select__tags-item" v-for="item in displayTags" :key="item[valueKey]">
11
- <span class="oxy-select__tags-item-text">{{ item[labelKey] }}</span>
12
- <view v-if="!disabled && !readonly" @click.stop="delItem(item)">
13
- <oxy-icon custom-class="oxy-select__icon-error" name="error-fill" />
14
- </view>
15
- </view>
16
- <view v-if="currentList.length > collapseTagsNum && collapseTags" class="oxy-select__tags-item">
17
- <span class="oxy-select__tags-item-text">+{{ currentList.length - collapseTagsNum }}</span>
18
- </view>
10
+ <oxy-tag
11
+ v-for="item in displayTags"
12
+ :key="item[valueKey]"
13
+ custom-class="oxy-select__tags-item-tag"
14
+ class="oxy-select__tags-item"
15
+ plain
16
+ round
17
+ :closable="!disabled && !readonly"
18
+ @close="delItem(item)"
19
+ >
20
+ <text class="oxy-select__tags-item-text">{{ formatItemName(item) }}</text>
21
+ </oxy-tag>
22
+ <oxy-tag
23
+ v-if="currentList.length > collapseTagsNum && collapseTags"
24
+ custom-class="oxy-select__tags-item-tag"
25
+ class="oxy-select__tags-item"
26
+ plain
27
+ round
28
+ >
29
+ <text class="oxy-select__tags-item-text">+{{ currentList.length - collapseTagsNum }}</text>
30
+ </oxy-tag>
19
31
  <input
20
- v-if="filterable && (!disabled || !readonly)"
32
+ v-if="filterable && !disabled && !readonly"
21
33
  @input="inputChange"
22
34
  class="oxy-select__input-text oxy-select__input-filter"
23
35
  type="text"
24
- placeholder="请输入"
36
+ :placeholder="currentList.length === 0 ? typePlaceholder : ''"
25
37
  v-model="filterInput"
26
38
  />
27
39
  </view>
28
- <view v-else-if="current && current.length > 0 && !showSelector" class="oxy-select__input-text">
40
+ <view v-else-if="current && current.length > 0 && (!showSelector || !filterable)" class="oxy-select__input-text">
29
41
  {{ current }}
30
42
  </view>
31
43
  <input
@@ -36,15 +48,15 @@
36
48
  :readonly="readonly"
37
49
  class="oxy-select__input-text oxy-select__input-selector"
38
50
  type="text"
39
- :placeholder="placeholderOld"
51
+ :placeholder="placeholderOld || typePlaceholder"
40
52
  v-model="filterInput"
41
53
  />
42
54
  <view v-else-if="!disabled && !readonly" class="oxy-select__input-text oxy-select__input-placeholder">{{ typePlaceholder }}</view>
43
55
  <oxy-icon
44
56
  v-if="(current.length > 0 && clear && !disabled && !readonly) || (currentArr.length > 0 && clear && !disabled && !readonly)"
45
57
  custom-class="oxy-select__icon oxy-select__icon-clear"
46
- name="error-fill"
47
- @click="clearVal"
58
+ name="close-circle-filled"
59
+ @click.stop="clearVal"
48
60
  />
49
61
  <oxy-icon
50
62
  :custom-class="`oxy-select__icon oxy-select__icon-arrow ${showSelector ? 'is-open' : ''}`"
@@ -52,24 +64,33 @@
52
64
  name="arrow-down"
53
65
  />
54
66
  </view>
55
- <oxy-transition :show="showSelector" name="fade" :duration="duration">
67
+ <oxy-transition custom-class="oxy-select__dropdown-transition" :show="showSelector" name="fade" :duration="duration" :lazy-render="false">
56
68
  <view class="oxy-select--mask" @click="toggleSelector" />
57
69
  <view class="oxy-select__selector" :class="isDown ? 'oxy-select__selector__down' : 'oxy-select__selector__upwards'">
58
70
  <view class="oxy-select__selector-arrow"></view>
59
71
  <scroll-view :scroll-y="true" class="oxy-select__selector-scroll">
60
- <view class="oxy-select__selector-empty" v-if="filterMixinDatacomResData.length === 0">
61
- <span>{{ emptyTips }}</span>
62
- </view>
63
- <view
64
- v-else
65
- :class="['oxy-select__selector-item', { 'oxy-select_selector-item_active': multiple && currentArr.includes(item[valueKey]) }]"
66
- v-for="(item, index) in filterMixinDatacomResData"
67
- :key="index"
68
- @click="change(item)"
69
- >
70
- <span :class="{ 'oxy-select__selector__disabled': item.disabled }">{{ formatItemName(item) }}</span>
71
- <oxy-icon v-if="multiple && currentArr.includes(item[valueKey])" name="check" />
72
+ <view v-if="loading" class="oxy-select__loading">
73
+ <oxy-icon name="refresh" custom-class="oxy-select__loading-icon" />
74
+ <text>{{ loadingText }}</text>
72
75
  </view>
76
+ <template v-else>
77
+ <view class="oxy-select__selector-empty" v-if="filterMixinDatacomResData.length === 0">
78
+ <span>{{ emptyTips }}</span>
79
+ </view>
80
+ <view
81
+ v-else
82
+ :class="[
83
+ 'oxy-select__selector-item',
84
+ { 'oxy-select_selector-item_active': multiple ? currentArr.includes(item[valueKey]) : modelValue === item[valueKey] }
85
+ ]"
86
+ v-for="(item, index) in filterMixinDatacomResData"
87
+ :key="index"
88
+ @click="change(item)"
89
+ >
90
+ <span :class="{ 'oxy-select__selector__disabled': item.disabled }">{{ formatItemName(item) }}</span>
91
+ <oxy-icon v-if="multiple && currentArr.includes(item[valueKey])" name="check" />
92
+ </view>
93
+ </template>
73
94
  </scroll-view>
74
95
  </view>
75
96
  </oxy-transition>
@@ -89,10 +110,12 @@ export default {
89
110
  </script>
90
111
 
91
112
  <script lang="ts" setup>
92
- import { getCurrentInstance, ref, watch, onMounted, computed } from 'vue'
113
+ import { getCurrentInstance, ref, watch, computed } from 'vue'
93
114
  import { objToStyle } from '../common/util'
115
+ import { useWindowResize, type WindowResizeResult } from '../composables/useWindowResize'
94
116
  import { selectProps, type SelectProps } from './types'
95
117
  import OxyTransition from '../oxy-transition/oxy-transition.vue'
118
+ import OxyTag from '../oxy-tag/oxy-tag.vue'
96
119
 
97
120
  type SelectOption = Record<string, any>
98
121
  type SelectModelValue = SelectProps['modelValue']
@@ -114,8 +137,23 @@ const rootStyle = ref('')
114
137
  const duration = ref<number>(200)
115
138
  let overlayTimer: ReturnType<typeof setTimeout> | null
116
139
 
117
- onMounted(() => {
118
- windowHeight.value = uni.getSystemInfoSync().windowHeight
140
+ const syncWindowHeight = (res?: WindowResizeResult) => {
141
+ const resizeHeight = Number(res?.size?.windowHeight ?? res?.windowHeight)
142
+ const systemHeight = uni.getSystemInfoSync().windowHeight
143
+ windowHeight.value = Number.isFinite(resizeHeight) && resizeHeight > 0 ? resizeHeight : systemHeight
144
+ }
145
+
146
+ const handleWindowResize = (res?: WindowResizeResult) => {
147
+ syncWindowHeight(res)
148
+ if (showSelector.value) {
149
+ void getIsDown()
150
+ }
151
+ }
152
+
153
+ useWindowResize(handleWindowResize, { immediate: true })
154
+
155
+ const rootClass = computed(() => {
156
+ return `oxy-select ${props.noBorder ? 'is-no-border' : ''} ${props.customClass}`
119
157
  })
120
158
 
121
159
  const labelStyle = computed(() => {
@@ -212,18 +250,28 @@ watch(
212
250
  )
213
251
 
214
252
  function getIsDown() {
215
- const query = uni.createSelectorQuery().in(instance)
216
- query
217
- .select('.oxy-select__box')
218
- .boundingClientRect((data) => {
219
- const rect = data as UniApp.NodeInfo
220
- if (rect && windowHeight.value - (rect.top || 0) > 200) {
221
- isDown.value = true
222
- } else {
223
- isDown.value = false
224
- }
225
- })
226
- .exec()
253
+ return new Promise((resolve) => {
254
+ const query = uni.createSelectorQuery().in(instance)
255
+ query
256
+ .select('.oxy-select__box')
257
+ .boundingClientRect((data) => {
258
+ const rect = data as UniApp.NodeInfo
259
+ if (rect) {
260
+ const bottomSpace = windowHeight.value - (rect.bottom || 0)
261
+ const topSpace = rect.top || 0
262
+ const threshold = 280 // max-height 240 + padding/arrow space
263
+
264
+ // 如果下方空间不足,且上方空间比下方空间大,则向上弹出
265
+ if (bottomSpace < threshold && topSpace > bottomSpace) {
266
+ isDown.value = false
267
+ } else {
268
+ isDown.value = true
269
+ }
270
+ }
271
+ resolve(isDown.value)
272
+ })
273
+ .exec()
274
+ })
227
275
  }
228
276
 
229
277
  function initDefVal() {
@@ -367,13 +415,16 @@ function handleEmit(val: any) {
367
415
  emit('change', _current)
368
416
  }
369
417
  }
370
- function toggleSelector() {
418
+ async function toggleSelector() {
371
419
  if (props.disabled || props.readonly) {
372
420
  return
373
421
  }
374
- getIsDown()
375
- showSelector.value = !showSelector.value
376
- isFocus.value = showSelector.value
422
+ const nextShow = !showSelector.value
423
+ if (nextShow) {
424
+ await getIsDown()
425
+ }
426
+ showSelector.value = nextShow
427
+ isFocus.value = nextShow
377
428
  if (props.filterable && current.value && showSelector.value) {
378
429
  if (!props.multiple) {
379
430
  if (typeof current.value === 'string') {
@@ -394,21 +445,18 @@ function formatItemName(item: any) {
394
445
  if (!item) {
395
446
  return ''
396
447
  }
397
- let text = item[props.labelKey]
398
- let value = item[props.valueKey]
399
- let { channel_code } = item
400
- channel_code = channel_code ? `(${channel_code})` : ''
448
+ const label = item[props.labelKey]
449
+
401
450
  if (props.format) {
402
451
  // 格式化输出
403
- let str = ''
404
- str = props.format
405
- for (let key in item) {
452
+ let str = props.format
453
+ for (const key in item) {
406
454
  str = str.replace(new RegExp(`{${key}}`, 'g'), item[key])
407
455
  }
408
456
  return str
409
- } else {
410
- return text ? text : `未命名${channel_code}`
411
457
  }
458
+
459
+ return label !== undefined && label !== null ? String(label) : ''
412
460
  }
413
461
 
414
462
  // 获取当前加载的数据
@@ -61,11 +61,23 @@ export const selectProps = {
61
61
  * 是否可清除
62
62
  */
63
63
  clear: makeBooleanProp(true),
64
+ /**
65
+ * 是否加载中
66
+ */
67
+ loading: makeBooleanProp(false),
68
+ /**
69
+ * 加载中文字
70
+ */
71
+ loadingText: makeStringProp('加载中...'),
64
72
  /**
65
73
  * 格式化输出
66
74
  */
67
75
  format: makeStringProp(''),
68
- defItem: makeNumberProp(0)
76
+ defItem: makeNumberProp(0),
77
+ /**
78
+ * 是否隐藏边框
79
+ */
80
+ noBorder: makeBooleanProp(false)
69
81
  }
70
82
 
71
83
  export type SelectProps = ExtractPropTypes<typeof selectProps>
@@ -73,19 +73,19 @@
73
73
  }
74
74
 
75
75
  @include edeep(header) {
76
- height: 72px;
77
- line-height: 72px;
76
+ height: 144rpx;
77
+ line-height: 144rpx;
78
78
  }
79
79
  @include e(wrapper) {
80
- padding: 0 10px;
80
+ padding: 0 24rpx;
81
81
  position: relative;
82
- max-height: 356px;
82
+ max-height: 712rpx;
83
83
  box-sizing: border-box;
84
84
  overflow: auto;
85
85
 
86
86
  @include when(filterable) {
87
- height: 314px;
88
- max-height: 314px;
87
+ height: 628rpx;
88
+ max-height: 628rpx;
89
89
  }
90
90
 
91
91
  @include when(loading) {
@@ -97,6 +97,6 @@
97
97
  }
98
98
 
99
99
  @include e(footer) {
100
- padding: 24px 15px;
100
+ padding: 52rpx 32rpx;
101
101
  }
102
102
  }
@@ -40,6 +40,7 @@
40
40
  :title="title || translate('title')"
41
41
  :close-on-click-modal="closeOnClickModal"
42
42
  :z-index="zIndex"
43
+ :max-width="popupMaxWidth"
43
44
  :safe-area-inset-bottom="safeAreaInsetBottom"
44
45
  :root-portal="rootPortal"
45
46
  @close="close"
@@ -72,6 +72,8 @@ export const selectPickerProps = {
72
72
  beforeConfirm: Function as PropType<SelectPickerBeforeConfirm>,
73
73
  /** 弹窗层级 */
74
74
  zIndex: makeNumberProp(15),
75
+ /** 弹层最大宽度,支持 `rpx`、`px`、`%` 等单位;`%` 在弹层打开时按屏幕宽度换算为 `rpx` */
76
+ popupMaxWidth: makeStringProp('1200rpx'),
75
77
  /** 弹出面板是否设置底部安全距离(iphone X 类型的机型) */
76
78
  safeAreaInsetBottom: makeBooleanProp(true),
77
79
  /** 可搜索(目前只支持本地搜索) */
@@ -91,7 +91,7 @@
91
91
 
92
92
  @include edeep(icon) {
93
93
  font-size: $-sidebar-icon-size;
94
- margin-right: 2px;
94
+ margin-right: 8rpx;
95
95
  }
96
96
 
97
- }
97
+ }
@@ -69,7 +69,7 @@ export default {
69
69
  </script>
70
70
  <script lang="ts" setup>
71
71
  import { computed, getCurrentInstance, onBeforeMount, onMounted, reactive, ref, watch, type CSSProperties } from 'vue'
72
- import { addUnit, getRect, isDef, objToStyle, uuid } from '../common/util'
72
+ import { getRect, isDef, objToStyle, unitConvert, unitConvertWithDefault, withDefaultUnit, uuid } from '../common/util'
73
73
  import { signatureProps, type SignatureExpose, type SignatureResult, type Point, type Line } from './types'
74
74
  import { useTranslate } from '../composables/useTranslate'
75
75
  // #ifdef MP-WEIXIN
@@ -147,11 +147,11 @@ watch(
147
147
  const canvasStyle = computed(() => {
148
148
  const style: CSSProperties = {}
149
149
  if (isDef(props.width)) {
150
- style.width = addUnit(props.width)
150
+ style.width = unitConvert(withDefaultUnit(props.width, 'rpx'), 0, { output: 'px' })
151
151
  }
152
152
 
153
153
  if (isDef(props.height)) {
154
- style.height = addUnit(props.height)
154
+ style.height = unitConvert(withDefaultUnit(props.height, 'rpx'), 0, { output: 'px' })
155
155
  }
156
156
 
157
157
  return `${objToStyle(style)}`
@@ -159,6 +159,12 @@ const canvasStyle = computed(() => {
159
159
 
160
160
  const disableScroll = computed(() => props.disableScroll)
161
161
  const enableHistory = computed(() => props.enableHistory)
162
+ const resolveStrokeWidth = (value: number | string): number => {
163
+ return unitConvertWithDefault(value, { defaultUnit: 'rpx' })
164
+ }
165
+ const lineWidthInPx = computed(() => resolveStrokeWidth(props.lineWidth))
166
+ const minWidthInPx = computed(() => resolveStrokeWidth(props.minWidth))
167
+ const maxWidthInPx = computed(() => resolveStrokeWidth(props.maxWidth))
162
168
 
163
169
  const lines = ref<Line[]>([]) // 保存所有线条
164
170
  const redoLines = ref<Line[]>([]) // 保存撤销的线条
@@ -167,22 +173,24 @@ const currentStep = ref(0) // 当前步骤
167
173
 
168
174
  // 添加计算笔画宽度的方法
169
175
  function calculateLineWidth(speed: number): number {
170
- if (!props.pressure) return props.lineWidth
176
+ if (!props.pressure) return lineWidthInPx.value
171
177
 
172
178
  const minSpeed = props.minSpeed || 1.5
179
+ const minWidth = Math.min(minWidthInPx.value, maxWidthInPx.value)
180
+ const maxWidth = Math.max(minWidthInPx.value, maxWidthInPx.value)
173
181
  const limitedSpeed = Math.min(minSpeed * 10, Math.max(minSpeed, speed))
174
- const addWidth = ((props.maxWidth - props.minWidth) * (limitedSpeed - minSpeed)) / minSpeed
175
- const lineWidth = Math.max(props.maxWidth - addWidth, props.minWidth)
176
- return Math.min(lineWidth, props.maxWidth)
182
+ const addWidth = ((maxWidth - minWidth) * (limitedSpeed - minSpeed)) / minSpeed
183
+ const lineWidth = Math.max(maxWidth - addWidth, minWidth)
184
+ return Math.min(lineWidth, maxWidth)
177
185
  }
178
186
 
179
187
  /* 获取默认笔画宽度 */
180
188
  const getDefaultLineWidth = () => {
181
189
  if (props.pressure) {
182
190
  // 在压感模式下,使用最大和最小宽度的平均值作为默认值
183
- return (props.maxWidth + props.minWidth) / 2
191
+ return (maxWidthInPx.value + minWidthInPx.value) / 2
184
192
  }
185
- return props.lineWidth
193
+ return lineWidthInPx.value
186
194
  }
187
195
 
188
196
  /* 开始画线 */
@@ -469,7 +477,7 @@ function drawSmoothLine(prePoint: Point, point: Point) {
469
477
  }
470
478
 
471
479
  // 计算线宽
472
- const lineWidth = point.lineWidth || props.lineWidth
480
+ const lineWidth = point.lineWidth || lineWidthInPx.value
473
481
 
474
482
  // 绘制贝塞尔曲线
475
483
  if (typeof prePoint.lastX1 === 'number') {
@@ -1,65 +1,122 @@
1
1
  import type { ComponentPublicInstance, ExtractPropTypes } from 'vue'
2
- import { baseProps, numericProp } from '../common/props'
2
+ import { baseProps, makeNumericProp, numericProp } from '../common/props'
3
3
 
4
4
  export const signatureProps = {
5
5
  ...baseProps,
6
+ /**
7
+ * 画笔颜色
8
+ */
6
9
  penColor: {
7
10
  type: String,
8
11
  default: '#000'
9
12
  },
10
- lineWidth: {
11
- type: Number,
12
- default: 3
13
- },
13
+ /**
14
+ * 画笔线宽,支持 number / string(如 '6rpx'、'3px'),number 与纯数字字符串按 rpx 处理
15
+ */
16
+ lineWidth: makeNumericProp(6),
17
+ /**
18
+ * 清空按钮文案
19
+ */
14
20
  clearText: String,
21
+ /**
22
+ * 撤销按钮文案
23
+ */
15
24
  revokeText: String,
25
+ /**
26
+ * 恢复按钮文案
27
+ */
16
28
  restoreText: String,
29
+ /**
30
+ * 确认按钮文案
31
+ */
17
32
  confirmText: String,
33
+ /**
34
+ * 导出图片格式
35
+ */
18
36
  fileType: {
19
37
  type: String,
20
38
  default: 'png'
21
39
  },
40
+ /**
41
+ * 导出质量
42
+ */
22
43
  quality: {
23
44
  type: Number,
24
45
  default: 1
25
46
  },
47
+ /**
48
+ * 导出缩放比例
49
+ */
26
50
  exportScale: {
27
51
  type: Number,
28
52
  default: 1
29
53
  },
54
+ /**
55
+ * 是否禁用签名操作
56
+ */
30
57
  disabled: {
31
58
  type: Boolean,
32
59
  default: false
33
60
  },
61
+ /**
62
+ * 画布高度,支持 number / string(如 '600rpx'、'300px'),number 与纯数字字符串按 rpx 处理
63
+ */
34
64
  height: numericProp,
65
+ /**
66
+ * 画布宽度,支持 number / string(如 '100%'、'700rpx'),number 与纯数字字符串按 rpx 处理
67
+ */
35
68
  width: numericProp,
69
+ /**
70
+ * 画布背景色
71
+ */
36
72
  backgroundColor: String,
73
+ /**
74
+ * 是否禁用页面滚动
75
+ */
37
76
  disableScroll: {
38
77
  type: Boolean,
39
78
  default: true
40
79
  },
80
+ /**
81
+ * 是否启用历史记录
82
+ */
41
83
  enableHistory: {
42
84
  type: Boolean,
43
85
  default: false
44
86
  },
87
+ /**
88
+ * 每次记录步进
89
+ */
45
90
  step: {
46
91
  type: Number,
47
92
  default: 1
48
93
  },
94
+ /**
95
+ * 撤销文案
96
+ */
49
97
  undoText: String,
98
+ /**
99
+ * 重做文案
100
+ */
50
101
  redoText: String,
102
+ /**
103
+ * 是否启用压感
104
+ */
51
105
  pressure: {
52
106
  type: Boolean,
53
107
  default: false
54
108
  },
55
- minWidth: {
56
- type: Number,
57
- default: 2
58
- },
59
- maxWidth: {
60
- type: Number,
61
- default: 6
62
- },
109
+ /**
110
+ * 压感最小线宽,支持 number / string(如 '4rpx'、'2px'),number 与纯数字字符串按 rpx 处理
111
+ */
112
+ minWidth: makeNumericProp(4),
113
+ /**
114
+ * 压感最大线宽,支持 number / string(如 '12rpx'、'6px'),number 与纯数字字符串按 rpx 处理
115
+ */
116
+ maxWidth: makeNumericProp(12),
117
+ /**
118
+ * 压感最小速度阈值
119
+ */
63
120
  minSpeed: {
64
121
  type: Number,
65
122
  default: 1.5
@@ -67,23 +124,59 @@ export const signatureProps = {
67
124
  }
68
125
 
69
126
  export type SignatureResult = {
127
+ /**
128
+ * 临时文件路径
129
+ */
70
130
  tempFilePath: string
131
+ /**
132
+ * 导出是否成功
133
+ */
71
134
  success: boolean
135
+ /**
136
+ * 导出宽度
137
+ */
72
138
  width: number
139
+ /**
140
+ * 导出高度
141
+ */
73
142
  height: number
74
143
  }
75
144
 
76
145
  export interface Line {
146
+ /**
147
+ * 线段点集合
148
+ */
77
149
  points: Point[]
150
+ /**
151
+ * 线段颜色
152
+ */
78
153
  color: string
154
+ /**
155
+ * 线段宽度
156
+ */
79
157
  width: number
158
+ /**
159
+ * 背景色
160
+ */
80
161
  backgroundColor?: string
162
+ /**
163
+ * 是否启用压感
164
+ */
81
165
  isPressure?: boolean
82
166
  }
83
167
 
84
168
  export interface Point {
169
+ /**
170
+ * x 坐标
171
+ */
85
172
  x: number
173
+ /**
174
+ * y 坐标
175
+ */
86
176
  y: number
177
+ /**
178
+ * 时间戳
179
+ */
87
180
  t: number
88
181
  speed?: number
89
182
  distance?: number
@@ -63,7 +63,7 @@
63
63
  content: ' ';
64
64
  position: absolute;
65
65
  animation: oxy-skeleton-gradient 1.5s linear 2s infinite;
66
- background: linear-gradient(90deg, rgba(255, 255, 255, 0), $-skeleton-animation-gradient, rgba(255, 255, 255, 0));
66
+ background: linear-gradient(90deg, transparent, $-skeleton-animation-gradient, transparent);
67
67
  inset: 0;
68
68
  }
69
69
  }
@@ -24,16 +24,16 @@ import type { CSSProperties } from 'vue'
24
24
  import { ref, computed, watch } from 'vue'
25
25
  import type { SkeletonRowCol, SkeletonRowColObj } from './types'
26
26
  import { skeletonProps } from './types'
27
- import { isNumber, addUnit } from '../common/util'
27
+ import { isNumber, withDefaultUnit } from '../common/util'
28
28
 
29
29
  const themeMap = {
30
- avatar: [{ type: 'circle', height: '64px', width: '64px' }],
31
- image: [{ type: 'rect', height: '64px', width: '64px' }],
30
+ avatar: [{ type: 'circle', height: '128rpx', width: '128rpx' }],
31
+ image: [{ type: 'rect', height: '128rpx', width: '128rpx' }],
32
32
  text: [
33
33
  1,
34
34
  [
35
- { width: '24%', height: '16px', marginRight: '16px' },
36
- { width: '76%', height: '16px' }
35
+ { width: '24%', height: '32rpx', marginRight: '32rpx' },
36
+ { width: '76%', height: '32rpx' }
37
37
  ]
38
38
  ],
39
39
  paragraph: [1, 1, 1, { width: '55%' }]
@@ -81,7 +81,7 @@ function getColItemStyle(rowCol: SkeletonRowColObj) {
81
81
 
82
82
  for (const name of styleName) {
83
83
  if (Object.prototype.hasOwnProperty.call(rowCol, name)) {
84
- const px = addUnit(rowCol[name])
84
+ const px = withDefaultUnit(rowCol[name])
85
85
 
86
86
  if (name === 'size') {
87
87
  style.width = px
@@ -36,7 +36,7 @@ export const skeletonProps = {
36
36
  * 用于设置行列数量、宽度高度、间距等。
37
37
  * @example
38
38
  * 【示例一】,`[1, 1, 2]` 表示输出三行骨架图,第一行一列,第二行一列,第三行两列。
39
- * 【示例二】,`[1, 1, { width: '100px' }]` 表示自定义第三行的宽度为 `100px`。
39
+ * 【示例二】,`[1, 1, { width: '200rpx' }]` 表示自定义第三行的宽度为 `200rpx`。
40
40
  * 【示例三】,`[1, 2, [{ width, height }, { width, height, marginLeft }]]` 表示第三行有两列,且自定义宽度、高度和间距
41
41
  */
42
42
  rowCol: makeArrayProp<SkeletonRowCol>(),