oxy-uni-ui 2.1.2 → 2.1.3

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 (261) hide show
  1. package/attributes.json +1 -1
  2. package/components/common/AbortablePromise.ts +4 -0
  3. package/components/common/abstracts/variable.scss +172 -66
  4. package/components/common/base64.ts +6 -0
  5. package/components/common/clickoutside.ts +5 -0
  6. package/components/common/interceptor.ts +9 -0
  7. package/components/common/path.ts +4 -0
  8. package/components/common/props.ts +23 -0
  9. package/components/common/util.ts +18 -1
  10. package/components/composables/index.ts +2 -0
  11. package/components/composables/useCell.ts +8 -1
  12. package/components/composables/useChildren.ts +27 -1
  13. package/components/composables/useCountDown.ts +10 -1
  14. package/components/composables/useDynamicVirtualScroll.ts +9 -0
  15. package/components/composables/useGlobalLoading.ts +6 -0
  16. package/components/composables/useGlobalMessage.ts +6 -0
  17. package/components/composables/useGlobalToast.ts +6 -0
  18. package/components/composables/useLockScroll.ts +9 -0
  19. package/components/composables/useParent.ts +65 -14
  20. package/components/composables/usePopover.ts +9 -0
  21. package/components/composables/useQueue.ts +8 -0
  22. package/components/composables/useRaf.ts +10 -0
  23. package/components/composables/useSharedState.ts +284 -0
  24. package/components/composables/useTouch.ts +8 -0
  25. package/components/composables/useTranslate.ts +9 -0
  26. package/components/composables/useUpload.ts +83 -11
  27. package/components/composables/useVirtualScroll.ts +7 -0
  28. package/components/composables/useWindowResize.ts +9 -0
  29. package/components/oxy-action-sheet/index.scss +5 -5
  30. package/components/oxy-action-sheet/oxy-action-sheet.vue +11 -0
  31. package/components/oxy-backtop/index.scss +2 -2
  32. package/components/oxy-backtop/oxy-backtop.vue +2 -0
  33. package/components/oxy-badge/oxy-badge.vue +2 -0
  34. package/components/oxy-badge/types.ts +3 -0
  35. package/components/oxy-button/index.scss +13 -13
  36. package/components/oxy-button/oxy-button.vue +11 -0
  37. package/components/oxy-button/types.ts +3 -3
  38. package/components/oxy-calendar/index.scss +17 -17
  39. package/components/oxy-calendar/oxy-calendar.vue +31 -0
  40. package/components/oxy-calendar/types.ts +3 -0
  41. package/components/oxy-calendar-view/month/month.vue +2 -0
  42. package/components/oxy-calendar-view/monthPanel/month-panel.vue +3 -1
  43. package/components/oxy-calendar-view/monthPanel/types.ts +10 -7
  44. package/components/oxy-calendar-view/oxy-calendar-view.vue +2 -0
  45. package/components/oxy-calendar-view/types.ts +3 -1
  46. package/components/oxy-calendar-view/year/types.ts +33 -1
  47. package/components/oxy-calendar-view/year/year.vue +2 -0
  48. package/components/oxy-calendar-view/yearPanel/year-panel.vue +2 -0
  49. package/components/oxy-card/index.scss +1 -1
  50. package/components/oxy-card/oxy-card.vue +2 -0
  51. package/components/oxy-cell/index.scss +3 -1
  52. package/components/oxy-cell/oxy-cell.vue +6 -4
  53. package/components/oxy-cell-group/oxy-cell-group.vue +2 -0
  54. package/components/oxy-checkbox/index.scss +7 -7
  55. package/components/oxy-checkbox/oxy-checkbox.vue +22 -16
  56. package/components/oxy-checkbox/types.ts +9 -0
  57. package/components/oxy-checkbox-group/index.scss +1 -1
  58. package/components/oxy-checkbox-group/oxy-checkbox-group.vue +2 -0
  59. package/components/oxy-circle/oxy-circle.vue +2 -0
  60. package/components/oxy-col/oxy-col.vue +3 -1
  61. package/components/oxy-col-picker/index.scss +3 -3
  62. package/components/oxy-col-picker/oxy-col-picker.vue +17 -1
  63. package/components/oxy-col-picker/types.ts +3 -0
  64. package/components/oxy-collapse/index.scss +2 -2
  65. package/components/oxy-collapse/oxy-collapse.vue +9 -0
  66. package/components/oxy-collapse-item/oxy-collapse-item.vue +4 -2
  67. package/components/oxy-config-provider/oxy-config-provider.vue +18 -0
  68. package/components/oxy-config-provider/types.ts +18 -0
  69. package/components/oxy-corner/index.scss +50 -32
  70. package/components/oxy-corner/oxy-corner.vue +2 -0
  71. package/components/oxy-count-down/oxy-count-down.vue +2 -0
  72. package/components/oxy-count-to/oxy-count-to.vue +12 -1
  73. package/components/oxy-count-to/types.ts +14 -4
  74. package/components/oxy-curtain/index.scss +10 -9
  75. package/components/oxy-curtain/oxy-curtain.vue +2 -0
  76. package/components/oxy-date-strip/oxy-date-strip.vue +22 -1
  77. package/components/oxy-date-strip-item/index.scss +4 -4
  78. package/components/oxy-date-strip-item/oxy-date-strip-item.vue +2 -0
  79. package/components/oxy-datetime-picker/index.scss +3 -3
  80. package/components/oxy-datetime-picker/oxy-datetime-picker.vue +11 -1
  81. package/components/oxy-datetime-picker-view/oxy-datetime-picker-view.vue +2 -0
  82. package/components/oxy-divider/oxy-divider.vue +2 -0
  83. package/components/oxy-drop-menu/index.scss +2 -2
  84. package/components/oxy-drop-menu/oxy-drop-menu.vue +3 -0
  85. package/components/oxy-drop-menu-item/index.scss +1 -1
  86. package/components/oxy-drop-menu-item/oxy-drop-menu-item.vue +17 -9
  87. package/components/oxy-echarts/oxy-echarts.vue +2 -0
  88. package/components/oxy-fab/index.scss +1 -1
  89. package/components/oxy-fab/oxy-fab.vue +27 -0
  90. package/components/oxy-file-list/index.scss +9 -9
  91. package/components/oxy-file-list/oxy-file-list.vue +29 -17
  92. package/components/oxy-floating-panel/oxy-floating-panel.vue +34 -10
  93. package/components/oxy-footer/index.scss +7 -0
  94. package/components/oxy-footer/oxy-footer.vue +4 -2
  95. package/components/oxy-footer/types.ts +9 -6
  96. package/components/oxy-form/oxy-form.vue +13 -1
  97. package/components/oxy-form-item/oxy-form-item.vue +5 -3
  98. package/components/oxy-gap/oxy-gap.vue +2 -0
  99. package/components/oxy-global-loading/oxy-global-loading.vue +18 -5
  100. package/components/oxy-global-message/oxy-global-message.vue +30 -17
  101. package/components/oxy-global-toast/oxy-global-toast.vue +18 -5
  102. package/components/oxy-grid/oxy-grid.vue +6 -0
  103. package/components/oxy-grid-item/index.scss +1 -1
  104. package/components/oxy-grid-item/oxy-grid-item.vue +22 -20
  105. package/components/oxy-guidance/index.scss +9 -9
  106. package/components/oxy-guidance/oxy-guidance.vue +22 -16
  107. package/components/oxy-icon/oxy-icon.vue +2 -0
  108. package/components/oxy-icon/types.ts +3 -0
  109. package/components/oxy-image-preview/index.scss +75 -0
  110. package/components/oxy-image-preview/index.ts +56 -0
  111. package/components/oxy-image-preview/oxy-image-preview.vue +221 -0
  112. package/components/oxy-image-preview/types.ts +164 -0
  113. package/components/oxy-img/oxy-img.vue +2 -0
  114. package/components/oxy-img-cropper/index.scss +2 -2
  115. package/components/oxy-img-cropper/oxy-img-cropper.vue +6 -0
  116. package/components/oxy-img-lazy/oxy-img-lazy.vue +9 -0
  117. package/components/oxy-index-anchor/index.scss +1 -1
  118. package/components/oxy-index-anchor/oxy-index-anchor.vue +2 -2
  119. package/components/oxy-index-bar/index.scss +1 -1
  120. package/components/oxy-index-bar/oxy-index-bar.vue +18 -0
  121. package/components/oxy-input/index.scss +2 -1
  122. package/components/oxy-input/oxy-input.vue +18 -4
  123. package/components/oxy-input/types.ts +6 -0
  124. package/components/oxy-input-number/index.scss +3 -1
  125. package/components/oxy-input-number/oxy-input-number.vue +2 -0
  126. package/components/oxy-keyboard/index.scss +3 -3
  127. package/components/oxy-keyboard/key/index.vue +2 -0
  128. package/components/oxy-keyboard/oxy-keyboard.vue +11 -2
  129. package/components/oxy-link/index.scss +8 -4
  130. package/components/oxy-link/oxy-link.vue +9 -3
  131. package/components/oxy-link/types.ts +2 -2
  132. package/components/oxy-list/oxy-list.vue +2 -0
  133. package/components/oxy-list/types.ts +7 -0
  134. package/components/oxy-loading/oxy-loading.vue +6 -0
  135. package/components/oxy-loadmore/index.scss +1 -1
  136. package/components/oxy-loadmore/oxy-loadmore.vue +2 -0
  137. package/components/oxy-long-press-menu/index.scss +1 -1
  138. package/components/oxy-long-press-menu/oxy-long-press-menu.vue +42 -13
  139. package/components/oxy-message-box/index.scss +223 -36
  140. package/components/oxy-message-box/index.ts +49 -23
  141. package/components/oxy-message-box/oxy-message-box.vue +181 -56
  142. package/components/oxy-message-box/types.ts +60 -2
  143. package/components/oxy-navbar/index.scss +1 -1
  144. package/components/oxy-navbar/oxy-navbar.vue +9 -6
  145. package/components/oxy-navbar-capsule/oxy-navbar-capsule.vue +2 -0
  146. package/components/oxy-notice-bar/index.scss +1 -1
  147. package/components/oxy-notice-bar/oxy-notice-bar.vue +29 -0
  148. package/components/oxy-notify/index.ts +16 -12
  149. package/components/oxy-notify/oxy-notify.vue +11 -4
  150. package/components/oxy-overlay/oxy-overlay.vue +34 -2
  151. package/components/oxy-pagination/oxy-pagination.vue +2 -0
  152. package/components/oxy-password-input/oxy-password-input.vue +2 -0
  153. package/components/oxy-picker/index.scss +7 -7
  154. package/components/oxy-picker/oxy-picker.vue +11 -0
  155. package/components/oxy-picker-view/index.scss +1 -1
  156. package/components/oxy-picker-view/oxy-picker-view.vue +2 -0
  157. package/components/oxy-popover/index.scss +2 -2
  158. package/components/oxy-popover/oxy-popover.vue +4 -1
  159. package/components/oxy-popup/oxy-popup.vue +8 -0
  160. package/components/oxy-progress/index.scss +2 -2
  161. package/components/oxy-progress/oxy-progress.vue +7 -0
  162. package/components/oxy-qrcode/draw.ts +15 -1
  163. package/components/oxy-qrcode/oxy-qrcode.vue +10 -3
  164. package/components/oxy-radio/index.scss +8 -8
  165. package/components/oxy-radio/oxy-radio.vue +13 -11
  166. package/components/oxy-radio-group/index.scss +1 -1
  167. package/components/oxy-radio-group/oxy-radio-group.vue +2 -0
  168. package/components/oxy-rate/oxy-rate.vue +5 -0
  169. package/components/oxy-rate/types.ts +2 -2
  170. package/components/oxy-resize/oxy-resize.vue +12 -0
  171. package/components/oxy-rich-text/index.scss +9 -9
  172. package/components/oxy-rich-text/oxy-rich-text.vue +6 -0
  173. package/components/oxy-rich-text/types.ts +15 -0
  174. package/components/oxy-root-portal/oxy-root-portal.vue +23 -15
  175. package/components/oxy-row/oxy-row.vue +2 -0
  176. package/components/oxy-search/index.scss +3 -3
  177. package/components/oxy-search/oxy-search.vue +19 -0
  178. package/components/oxy-segmented/index.scss +4 -4
  179. package/components/oxy-segmented/oxy-segmented.vue +2 -0
  180. package/components/oxy-select/index.scss +25 -25
  181. package/components/oxy-select/oxy-select.vue +27 -0
  182. package/components/oxy-select/types.ts +3 -0
  183. package/components/oxy-select-picker/index.scss +5 -5
  184. package/components/oxy-select-picker/oxy-select-picker.vue +7 -0
  185. package/components/oxy-sidebar/oxy-sidebar.vue +2 -0
  186. package/components/oxy-sidebar-item/index.scss +3 -3
  187. package/components/oxy-sidebar-item/oxy-sidebar-item.vue +17 -31
  188. package/components/oxy-signature/oxy-signature.vue +17 -0
  189. package/components/oxy-skeleton/oxy-skeleton.vue +7 -1
  190. package/components/oxy-slide-verify/index.scss +95 -0
  191. package/components/oxy-slide-verify/oxy-slide-verify.vue +244 -0
  192. package/components/oxy-slide-verify/types.ts +98 -0
  193. package/components/oxy-slider/oxy-slider.vue +3 -0
  194. package/components/oxy-sort-button/index.scss +10 -8
  195. package/components/oxy-sort-button/oxy-sort-button.vue +6 -0
  196. package/components/oxy-splitter/index.scss +9 -0
  197. package/components/oxy-splitter/oxy-splitter.vue +23 -2
  198. package/components/oxy-splitter-panel/index.scss +7 -5
  199. package/components/oxy-splitter-panel/oxy-splitter-panel.vue +93 -89
  200. package/components/oxy-status-tip/index.scss +3 -3
  201. package/components/oxy-status-tip/oxy-status-tip.vue +2 -0
  202. package/components/oxy-step/index.scss +4 -4
  203. package/components/oxy-step/oxy-step.vue +15 -13
  204. package/components/oxy-steps/oxy-steps.vue +2 -0
  205. package/components/oxy-sticky/oxy-sticky.vue +5 -3
  206. package/components/oxy-stream-render/oxy-stream-render.vue +29 -0
  207. package/components/oxy-swipe-action/oxy-swipe-action.vue +8 -0
  208. package/components/oxy-swiper/oxy-swiper.vue +6 -0
  209. package/components/oxy-swiper-nav/index.scss +4 -4
  210. package/components/oxy-switch/index.scss +6 -3
  211. package/components/oxy-switch/oxy-switch.vue +10 -0
  212. package/components/oxy-tab/index.scss +1 -7
  213. package/components/oxy-tab/oxy-tab.vue +12 -10
  214. package/components/oxy-tabbar/oxy-tabbar.vue +5 -0
  215. package/components/oxy-tabbar-item/oxy-tabbar-item.vue +11 -9
  216. package/components/oxy-table/index.scss +1 -1
  217. package/components/oxy-table/oxy-table.vue +8 -0
  218. package/components/oxy-table/types.ts +3 -0
  219. package/components/oxy-table-col/oxy-table-col.vue +21 -19
  220. package/components/oxy-tabs/index.scss +11 -11
  221. package/components/oxy-tabs/oxy-tabs.vue +17 -0
  222. package/components/oxy-tag/index.scss +24 -5
  223. package/components/oxy-tag/oxy-tag.vue +17 -2
  224. package/components/oxy-tag/types.ts +7 -0
  225. package/components/oxy-text/oxy-text.vue +12 -1
  226. package/components/oxy-textarea/index.scss +3 -2
  227. package/components/oxy-textarea/oxy-textarea.vue +10 -4
  228. package/components/oxy-toast/index.ts +21 -20
  229. package/components/oxy-toast/oxy-toast.vue +30 -5
  230. package/components/oxy-toast/types.ts +20 -9
  231. package/components/oxy-tooltip/index.scss +1 -1
  232. package/components/oxy-tooltip/oxy-tooltip.vue +2 -0
  233. package/components/oxy-transition/index.scss +3 -1
  234. package/components/oxy-transition/oxy-transition.vue +14 -0
  235. package/components/oxy-tree/index.scss +3 -3
  236. package/components/oxy-tree/oxy-tree.vue +28 -5
  237. package/components/oxy-tree/types.ts +57 -1
  238. package/components/oxy-upload/index.scss +9 -9
  239. package/components/oxy-upload/oxy-upload.vue +5 -3
  240. package/components/oxy-verification-code/oxy-verification-code.vue +24 -0
  241. package/components/oxy-video-preview/index.scss +12 -7
  242. package/components/oxy-video-preview/index.ts +64 -0
  243. package/components/oxy-video-preview/oxy-video-preview.vue +102 -31
  244. package/components/oxy-video-preview/types.ts +54 -8
  245. package/components/oxy-virtual-scroll/index.scss +1 -1
  246. package/components/oxy-virtual-scroll/oxy-virtual-scroll.vue +2 -0
  247. package/components/oxy-voice-player/index.scss +64 -64
  248. package/components/oxy-voice-player/oxy-voice-player.vue +38 -10
  249. package/components/oxy-waterfall/oxy-waterfall.vue +13 -0
  250. package/components/oxy-waterfall/types.ts +7 -0
  251. package/components/oxy-waterfall-item/oxy-waterfall-item.vue +9 -0
  252. package/components/oxy-watermark/oxy-watermark.vue +2 -0
  253. package/global.d.ts +2 -0
  254. package/index.ts +2 -0
  255. package/locale/lang/en-US.ts +51 -2
  256. package/locale/lang/zh-CN.ts +51 -2
  257. package/package.json +2 -2
  258. package/styles/all.scss +125 -0
  259. package/tags.json +1 -1
  260. package/vite-plugins/vite-plugin-host-class.ts +166 -0
  261. package/web-types.json +1 -1
@@ -27,6 +27,23 @@
27
27
  @mixin tag-type-style($normalColor, $normalBg) {
28
28
  background: $normalBg;
29
29
 
30
+ @include when(light) {
31
+ color: $normalColor;
32
+ background: transparent;
33
+ position: relative;
34
+ z-index: $-z-index-sticky;
35
+
36
+ &::before {
37
+ content: '';
38
+ position: absolute;
39
+ inset: 0;
40
+ background: $normalBg;
41
+ opacity: $-tag-light-opacity;
42
+ border-radius: inherit;
43
+ z-index: -1;
44
+ }
45
+ }
46
+
30
47
  @include when(plain) {
31
48
  background: transparent;
32
49
  color: $normalColor;
@@ -68,10 +85,12 @@
68
85
  $roundRadius: map-get($sizeConfig, roundRadius);
69
86
  $markRadius: map-get($sizeConfig, markRadius);
70
87
 
71
- font-size: $fontSize;
72
- padding: $paddingY $paddingX;
73
- min-height: $minHeight;
74
- border-radius: $radius;
88
+ & {
89
+ font-size: $fontSize;
90
+ padding: $paddingY $paddingX;
91
+ min-height: $minHeight;
92
+ border-radius: $radius;
93
+ }
75
94
 
76
95
  &.is-round {
77
96
  padding: $paddingY $roundPaddingX;
@@ -306,7 +325,7 @@ $-tag-size-large-config: (
306
325
  display: inline-flex;
307
326
  align-items: center;
308
327
  justify-content: center;
309
- margin-left: 12rpx;
328
+ margin-left: $-spacing-12;
310
329
  margin-right: 0;
311
330
  font-size: $-tag-close-size;
312
331
  width: $-tag-close-size;
@@ -35,7 +35,9 @@ export default {
35
35
  name: 'oxy-tag',
36
36
  options: {
37
37
  addGlobalClass: true,
38
+ // #ifndef MP-TOUTIAO
38
39
  virtualHost: true,
40
+ // #endif
39
41
  styleIsolation: 'shared'
40
42
  }
41
43
  }
@@ -57,7 +59,16 @@ const dynamicValue = ref<string>('')
57
59
  const dynamicInput = ref<boolean>(false)
58
60
 
59
61
  watch(
60
- [() => props.useIconSlot, () => props.icon, () => props.plain, () => props.dynamic, () => props.round, () => props.mark, () => props.size],
62
+ [
63
+ () => props.useIconSlot,
64
+ () => props.icon,
65
+ () => props.light,
66
+ () => props.plain,
67
+ () => props.dynamic,
68
+ () => props.round,
69
+ () => props.mark,
70
+ () => props.size
71
+ ],
61
72
  () => {
62
73
  computeTagClass()
63
74
  },
@@ -118,11 +129,15 @@ const textStyle = computed(() => {
118
129
  return objToStyle(textStyle)
119
130
  })
120
131
 
132
+ /**
133
+ * 根据 tag 的 type、size、light、plain、round 等属性组合生成样式类名。
134
+ */
121
135
  function computeTagClass() {
122
- const { type, size, plain, round, mark, dynamic, icon, useIconSlot } = props
136
+ const { type, size, light, plain, round, mark, dynamic, icon, useIconSlot } = props
123
137
  let tagClassList: string[] = []
124
138
  type && tagClassList.push(`is-${type}`)
125
139
  size && tagClassList.push(`is-${size}`)
140
+ light && tagClassList.push('is-light')
126
141
  plain && tagClassList.push('is-plain')
127
142
  round && tagClassList.push('is-round')
128
143
  mark && tagClassList.push('is-mark')
@@ -44,6 +44,13 @@ export const tagProps = {
44
44
  */
45
45
  closable: makeBooleanProp(false),
46
46
 
47
+ /**
48
+ * 浅色类型
49
+ * 类型:boolean
50
+ * 默认值:false
51
+ */
52
+ light: makeBooleanProp(false),
53
+
47
54
  /**
48
55
  * 幽灵类型
49
56
  * 类型:boolean
@@ -10,7 +10,9 @@
10
10
  <slot v-if="$slots.prefix || prefix" name="prefix">{{ prefix }}</slot>
11
11
  <text>{{ props.toggleExpand && isTextOverflow && !expanded ? realText : formattedText }}</text>
12
12
  <slot v-if="$slots.suffix || suffix" name="suffix">{{ suffix }}</slot>
13
- <text v-if="props.toggleExpand && isTextOverflow" class="oxy-text__btn" @click.stop="handleToggle">{{ expanded ? '收起' : '展开' }}</text>
13
+ <text v-if="props.toggleExpand && isTextOverflow" class="oxy-text__btn" @click.stop="handleToggle">
14
+ {{ expanded ? translate('retract') : translate('expand') }}
15
+ </text>
14
16
  </text>
15
17
  </template>
16
18
 
@@ -18,7 +20,9 @@
18
20
  export default {
19
21
  name: 'oxy-text',
20
22
  options: {
23
+ // #ifndef MP-TOUTIAO
21
24
  virtualHost: true,
25
+ // #endif
22
26
  addGlobalClass: true,
23
27
  styleIsolation: 'shared'
24
28
  }
@@ -31,10 +35,12 @@ import { isDef, objToStyle, uuid, getRect } from '../common/util'
31
35
  import { textProps } from './types'
32
36
  import dayjs from '../../dayjs'
33
37
  import OxyTooltip from '../oxy-tooltip/oxy-tooltip.vue'
38
+ import { useTranslate } from '../composables/useTranslate'
34
39
 
35
40
  // 获取组件的 props 和 emit 函数
36
41
  const props = defineProps(textProps)
37
42
  const emit = defineEmits(['click'])
43
+ const { translate } = useTranslate('collapse')
38
44
 
39
45
  const { proxy } = getCurrentInstance() as any
40
46
  const textId = ref<string>(`oxy-text${uuid()}`)
@@ -147,6 +153,11 @@ const formattedText = computed(() => {
147
153
  return formatText(`${text}`, format, mode)
148
154
  })
149
155
 
156
+ /**
157
+ * 文本格式化后检测溢出。
158
+ * toggleExpand/tooltip 模式下:计算实际行数(height/lineHeight),超行则截断文本。
159
+ * 截断时考虑中英文字符宽度差异(中文=1,英文=0.5)。
160
+ */
150
161
  watch(
151
162
  formattedText,
152
163
  (value) => {
@@ -173,7 +173,7 @@
173
173
 
174
174
  @include e(suffix) {
175
175
  position: absolute;
176
- z-index: 1;
176
+ z-index: $-z-index-sticky;
177
177
  right: 0;
178
178
  top: 0;
179
179
  bottom: 0;
@@ -219,7 +219,7 @@
219
219
  position: absolute;
220
220
  top: 0;
221
221
  left: 0;
222
- z-index: 2;
222
+ z-index: $-z-index-sticky;
223
223
  width: 100%;
224
224
  height: 100%;
225
225
  }
@@ -241,6 +241,7 @@
241
241
  }
242
242
 
243
243
  @include when(disabled) {
244
+ opacity: $-opacity-disabled;
244
245
 
245
246
  .oxy-textarea__inner {
246
247
  color: $-input-disabled-color;
@@ -67,7 +67,9 @@
67
67
  export default {
68
68
  name: 'oxy-textarea',
69
69
  options: {
70
+ // #ifndef MP-TOUTIAO
70
71
  virtualHost: true,
72
+ // #endif
71
73
  addGlobalClass: true,
72
74
  styleIsolation: 'shared'
73
75
  }
@@ -156,8 +158,8 @@ const showWordCount = computed(() => {
156
158
 
157
159
  // 表单校验错误信息
158
160
  const errorMessage = computed(() => {
159
- if (form && props.prop && form.errorMessages && form.errorMessages[props.prop]) {
160
- return form.errorMessages[props.prop]
161
+ if (form.value && props.prop && form.value.errorMessages && form.value.errorMessages[props.prop]) {
162
+ return form.value.errorMessages[props.prop]
161
163
  } else {
162
164
  return ''
163
165
  }
@@ -166,8 +168,8 @@ const errorMessage = computed(() => {
166
168
  // 是否展示必填
167
169
  const isRequired = computed(() => {
168
170
  let formRequired = false
169
- if (form && form.props.rules) {
170
- const rules = form.props.rules
171
+ if (form.value && form.value.props.rules) {
172
+ const rules = form.value.props.rules
171
173
  for (const key in rules) {
172
174
  if (Object.prototype.hasOwnProperty.call(rules, key) && key === props.prop && Array.isArray(rules[key])) {
173
175
  formRequired = rules[key].some((rule: FormItemRule) => rule.required)
@@ -245,6 +247,10 @@ async function handleClear() {
245
247
  emit('update:modelValue', inputValue.value)
246
248
  emit('clear')
247
249
  }
250
+ /**
251
+ * 失焦处理:延迟 150ms 等待 clear 操作完成
252
+ * 避免清空时重复触发 blur + clear 的连锁反应
253
+ */
248
254
  async function handleBlur({ detail }: any) {
249
255
  // 等待150毫秒,clear执行完毕
250
256
  await pause(150)
@@ -1,11 +1,6 @@
1
- import { inject, provide, ref } from 'vue'
2
- import type { Toast, ToastOptions } from './types'
1
+ import type { Toast, ToastId, ToastOptions } from './types'
3
2
  import { deepMerge } from '../common/util'
4
-
5
- /**
6
- * useToast 用到的key
7
- */
8
- const toastDefaultOptionKey = '__TOAST_OPTION__'
3
+ import { createSharedState } from '../composables/useSharedState'
9
4
 
10
5
  // 默认模板
11
6
  export const defaultOptions: ToastOptions = {
@@ -13,16 +8,20 @@ export const defaultOptions: ToastOptions = {
13
8
  show: false
14
9
  }
15
10
 
16
- const None = Symbol('None')
11
+ const {
12
+ getState: getToastOptions,
13
+ initState: initToastOptions,
14
+ removeState: removeToastOptions,
15
+ resolveScopeId: resolveToastScopeId,
16
+ resolveStateKey: resolveToastStateKey
17
+ } = createSharedState<ToastOptions>(() => defaultOptions, { namespace: 'toast' })
18
+
19
+ export { getToastOptions, initToastOptions, removeToastOptions, resolveToastScopeId, resolveToastStateKey }
17
20
 
18
21
  export function useToast(selector: string = ''): Toast {
19
- const toastOptionKey = getToastOptionKey(selector)
20
- const toastOption = inject(toastOptionKey, ref<ToastOptions | typeof None>(None)) // toast选项
21
- if (toastOption.value === None) {
22
- toastOption.value = defaultOptions
23
- provide(toastOptionKey, toastOption)
24
- }
25
22
  let timer: ReturnType<typeof setTimeout> | null = null
23
+ const scopeId = resolveToastScopeId()
24
+ const id = resolveToastStateKey(selector, scopeId)
26
25
 
27
26
  const createMethod = (toastOptions: ToastOptions) => {
28
27
  return (options: ToastOptions | string) => {
@@ -30,7 +29,8 @@ export function useToast(selector: string = ''): Toast {
30
29
  }
31
30
  }
32
31
 
33
- const show = (option: ToastOptions | string) => {
32
+ const show = (option: ToastOptions | string): ToastId => {
33
+ const toastOption = initToastOptions(selector, scopeId)
34
34
  const options = deepMerge(defaultOptions, typeof option === 'string' ? { msg: option } : option) as ToastOptions
35
35
  toastOption.value = deepMerge(options, {
36
36
  show: true
@@ -43,6 +43,7 @@ export function useToast(selector: string = ''): Toast {
43
43
  close()
44
44
  }, options.duration)
45
45
  }
46
+ return resolveToastStateKey(selector, scopeId)
46
47
  }
47
48
 
48
49
  const loading = createMethod({
@@ -59,9 +60,13 @@ export function useToast(selector: string = ''): Toast {
59
60
  const info = createMethod({ iconName: 'info' })
60
61
 
61
62
  const close = () => {
62
- toastOption.value = { show: false }
63
+ const toastOption = initToastOptions(selector, scopeId)
64
+ timer && clearTimeout(timer)
65
+ timer = null
66
+ toastOption.value = { ...defaultOptions, show: false }
63
67
  }
64
68
  return {
69
+ id,
65
70
  show,
66
71
  loading,
67
72
  success,
@@ -72,10 +77,6 @@ export function useToast(selector: string = ''): Toast {
72
77
  }
73
78
  }
74
79
 
75
- export const getToastOptionKey = (selector: string) => {
76
- return selector ? `${toastDefaultOptionKey}${selector}` : toastDefaultOptionKey
77
- }
78
-
79
80
  export const toastIcon = {
80
81
  success() {
81
82
  return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="2 2 44 44" width="48" height="48"><circle cx="24" cy="26" r="22" fill="#000" opacity=".1"/><circle cx="24" cy="24" r="20" fill="#34D19D" opacity=".4"/><circle cx="24" cy="24" r="16" fill="#34D19D"/><path d="M19 24l4 4 8-8" stroke="#FFF" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg>'
@@ -44,21 +44,24 @@ export default {
44
44
  name: 'oxy-toast',
45
45
  options: {
46
46
  addGlobalClass: true,
47
+ // #ifndef MP-TOUTIAO
47
48
  virtualHost: true,
49
+ // #endif
48
50
  styleIsolation: 'shared'
49
51
  }
50
52
  }
51
53
  </script>
52
54
 
53
55
  <script lang="ts" setup>
56
+ import { onHide, onUnload } from '@dcloudio/uni-app'
54
57
  import OxyIcon from '../oxy-icon/oxy-icon.vue'
55
58
  import OxyLoading from '../oxy-loading/oxy-loading.vue'
56
59
  import OxyOverlay from '../oxy-overlay/oxy-overlay.vue'
57
60
  import OxyTransition from '../oxy-transition/oxy-transition.vue'
58
61
 
59
- import { computed, inject, onBeforeMount, ref, useSlots, watch, type CSSProperties } from 'vue'
62
+ import { computed, onBeforeMount, onUnmounted, ref, useSlots, watch, type CSSProperties } from 'vue'
60
63
  import base64 from '../common/base64'
61
- import { defaultOptions, getToastOptionKey, toastIcon } from '.'
64
+ import { initToastOptions, removeToastOptions, resolveToastScopeId, toastIcon } from '.'
62
65
  import { toastProps, type ToastDirection, type ToastLoadingType, type ToastOptions, type ToastProps } from './types'
63
66
  import { withDefaultUnit, isDef, isFunction, objToStyle } from '../common/util'
64
67
 
@@ -83,8 +86,8 @@ let opened: (() => void) | null = null
83
86
 
84
87
  let closed: (() => void) | null = null
85
88
 
86
- const toastOptionKey = getToastOptionKey(props.selector)
87
- const toastOption = inject(toastOptionKey, ref<ToastOptions>(defaultOptions)) // toast选项
89
+ const scopeId = resolveToastScopeId()
90
+ const toastOption = initToastOptions(props.selector, scopeId)
88
91
 
89
92
  // 监听options变化展示
90
93
  watch(
@@ -128,7 +131,7 @@ const transitionStyle = computed(() => {
128
131
  })
129
132
 
130
133
  const hasCustomContent = computed(() => {
131
- const slotNodes = slots.default?.()
134
+ const slotNodes = isFunction(slots.default) ? slots.default() : []
132
135
  return !!slotNodes?.length
133
136
  })
134
137
 
@@ -157,6 +160,19 @@ onBeforeMount(() => {
157
160
  buildSvg()
158
161
  })
159
162
 
163
+ onHide(() => {
164
+ clearToastState()
165
+ })
166
+
167
+ onUnload(() => {
168
+ clearToastState()
169
+ })
170
+
171
+ onUnmounted(() => {
172
+ clearToastState()
173
+ removeToastOptions(props.selector, scopeId)
174
+ })
175
+
160
176
  function handleAfterEnter() {
161
177
  if (isFunction(opened)) {
162
178
  opened()
@@ -176,6 +192,10 @@ function buildSvg() {
176
192
  svgStr.value = iconSvgStr
177
193
  }
178
194
 
195
+ function clearToastState() {
196
+ toastOption.value = { ...toastOption.value, show: false }
197
+ }
198
+
179
199
  /**
180
200
  * 重置toast选项值
181
201
  * @param option toast选项值
@@ -188,6 +208,11 @@ function reset(option: ToastOptions) {
188
208
  }
189
209
  }
190
210
 
211
+ /**
212
+ * 合并 option 和 props 配置。option 优先级高于 props,用于动态更新 toast 展示状态。
213
+ * @param option - 通过 selector 共享的 toast 运行时选项
214
+ * @param props - 组件的 props 默认值
215
+ */
191
216
  function mergeOptionsWithProps(option: ToastOptions, props: ToastProps) {
192
217
  iconName.value = isDef(option.iconName!) ? option.iconName! : props.iconName
193
218
  iconClass.value = isDef(option.iconClass!) ? option.iconClass! : props.iconClass
@@ -1,4 +1,4 @@
1
- import type { ExtractPropTypes, PropType } from 'vue'
1
+ import type { ExtractPropTypes, PropType, Ref } from 'vue'
2
2
  import { baseProps, makeStringProp } from '../common/props'
3
3
  import type { LoadingType } from '../oxy-loading/types'
4
4
 
@@ -10,6 +10,8 @@ export type ToastDirection = 'vertical' | 'horizontal' // 提示信息框的排
10
10
 
11
11
  export type ToastLoadingType = LoadingType // 提示信息加载状态类型
12
12
 
13
+ export type ToastId = string
14
+
13
15
  export type ToastOptions = {
14
16
  msg?: string
15
17
  duration?: number
@@ -46,22 +48,31 @@ export type ToastOptions = {
46
48
  }
47
49
 
48
50
  export interface Toast {
51
+ // 当前 Toast 实例 id
52
+ id: ToastId
49
53
  // 打开Toast
50
- show(toastOptions: ToastOptions | string): void
54
+ show(toastOptions: ToastOptions | string): ToastId
51
55
  // 成功提示
52
- success(toastOptions: ToastOptions | string): void
56
+ success(toastOptions: ToastOptions | string): ToastId
53
57
  // 关闭提示
54
- error(toastOptions: ToastOptions | string): void
58
+ error(toastOptions: ToastOptions | string): ToastId
55
59
  // 常规提示
56
- info(toastOptions: ToastOptions | string): void
60
+ info(toastOptions: ToastOptions | string): ToastId
57
61
  // 警告提示
58
- warning(toastOptions: ToastOptions | string): void
62
+ warning(toastOptions: ToastOptions | string): ToastId
59
63
  // 加载提示
60
- loading(toastOptions: ToastOptions | string): void
64
+ loading(toastOptions: ToastOptions | string): ToastId
61
65
  // 关闭Toast
62
66
  close(): void
63
67
  }
64
68
 
69
+ export type ToastProvide = {
70
+ /**
71
+ * toast 运行时选项,默认隐藏。
72
+ */
73
+ toastOption: Ref<ToastOptions>
74
+ }
75
+
65
76
  export const toastProps = {
66
77
  ...baseProps,
67
78
  /**
@@ -127,9 +138,9 @@ export const toastProps = {
127
138
  /**
128
139
  * 位置
129
140
  * @type {'top' | 'middle-top' | 'middle' | 'bottom'}
130
- * @default 'middle-top'
141
+ * @default 'middle'
131
142
  */
132
- position: makeStringProp<ToastPositionType>('middle-top'),
143
+ position: makeStringProp<ToastPositionType>('middle'),
133
144
  /**
134
145
  * 层级
135
146
  * @type {number}
@@ -59,7 +59,7 @@
59
59
  right: -16rpx;
60
60
  top: -20rpx;
61
61
  transform: scale(0.5);
62
- padding: 20rpx;
62
+ padding: $-spacing-20;
63
63
  }
64
64
 
65
65
  @include triangleArrow($-tooltip-arrow-size, $-tooltip-bg);
@@ -27,7 +27,9 @@ export default {
27
27
  name: 'oxy-tooltip',
28
28
  options: {
29
29
  addGlobalClass: true,
30
+ // #ifndef MP-TOUTIAO
30
31
  virtualHost: true,
32
+ // #endif
31
33
  styleIsolation: 'shared'
32
34
  }
33
35
  }
@@ -1,5 +1,7 @@
1
+ @import '../common/abstracts/variable';
2
+
1
3
  .oxy-transition {
2
- transition-timing-function: ease;
4
+ transition-timing-function: $-transition-timing-function-base;
3
5
  }
4
6
 
5
7
  .oxy-fade-enter,
@@ -19,7 +19,9 @@ export default {
19
19
  name: 'oxy-transition',
20
20
  options: {
21
21
  addGlobalClass: true,
22
+ // #ifndef MP-TOUTIAO
22
23
  virtualHost: true,
24
+ // #endif
23
25
  styleIsolation: 'shared'
24
26
  }
25
27
  }
@@ -31,6 +33,10 @@ import { isObj, isPromise, pause } from '../common/util'
31
33
  import { transitionProps, type TransitionName } from './types'
32
34
  import { AbortablePromise } from '../common/AbortablePromise'
33
35
 
36
+ /**
37
+ * 根据 name 属性生成进入/离开的 CSS 类名
38
+ * name 可以是单个字符串或数组,用于组合多个过渡效果
39
+ */
34
40
  const getClassNames = (name?: TransitionName | TransitionName[]) => {
35
41
  let enter: string = `${props.enterClass} ${props.enterActiveClass}`
36
42
  let enterTo: string = `${props.enterToClass} ${props.enterActiveClass}`
@@ -134,6 +140,10 @@ function handleAbortPromise() {
134
140
  leaveLifeCyclePromises.value = null
135
141
  }
136
142
 
143
+ /**
144
+ * 进入动画:使用 AbortablePromise 管理生命周期
145
+ * before-enter → enter → (显示元素) → enter-to(触发 CSS transition)
146
+ */
137
147
  function enter() {
138
148
  enterPromise.value = new AbortablePromise(async (resolve) => {
139
149
  try {
@@ -163,6 +173,10 @@ function enter() {
163
173
  }
164
174
  })
165
175
  }
176
+ /**
177
+ * 离开动画:等待进入动画完成后执行离开
178
+ * before-leave → leave → leave-to(触发 CSS transition)→ after-leave
179
+ */
166
180
  async function leave() {
167
181
  if (!enterPromise.value) {
168
182
  transitionEnded.value = false
@@ -29,15 +29,15 @@
29
29
  display: flex;
30
30
 
31
31
  :deep(.oxy-button) {
32
- min-width: 120rpx;
32
+ min-width: $-tree-search-btn-min-width;
33
33
  }
34
34
 
35
35
  :deep(.oxy-tree__search-input) {
36
36
  flex: 1;
37
37
  background-color: $-tree-search-input-color;
38
- padding: 16rpx 24rpx;
38
+ padding: $-spacing-4 $-spacing-24;
39
39
  border-radius: $-tree-search-input-radius;
40
- margin-bottom: 20rpx;
40
+ margin-bottom: $-tree-search-btn-margin-bottom;
41
41
  margin-right: $-spacing-24;
42
42
 
43
43
  .oxy-input__icon {
@@ -11,7 +11,7 @@
11
11
  v-model="searchValue"
12
12
  @confirm="handleFilter"
13
13
  />
14
- <oxy-button :round="false" @click="handleFilter">筛选</oxy-button>
14
+ <oxy-button :round="false" @click="handleFilter">{{ translate('filterButton') }}</oxy-button>
15
15
  </view>
16
16
  </slot>
17
17
 
@@ -39,10 +39,9 @@
39
39
 
40
40
  <!-- 兼容支付宝、微信小程序 -->
41
41
  <view class="oxy-tree-node-toggle" @tap.stop="handleClickExpand(item)">
42
- <oxy-icon
43
- :name="expandedKeySet.has(item.key) ? 'chevron-down-circle' : 'chevron-right-circle'"
44
- custom-class="oxy-tree-node-icon"
45
- ></oxy-icon>
42
+ <slot name="expand-icon" :node="item" :data="item.data" :expanded="expandedKeySet.has(item.key)">
43
+ <oxy-icon :name="expandedKeySet.has(item.key) ? expandIcon : collapseIcon" custom-class="oxy-tree-node-icon"></oxy-icon>
44
+ </slot>
46
45
  </view>
47
46
  <oxy-checkbox
48
47
  v-if="showCheckbox"
@@ -77,7 +76,9 @@
77
76
  export default {
78
77
  name: 'oxy-tree',
79
78
  options: {
79
+ // #ifndef MP-TOUTIAO
80
80
  virtualHost: true,
81
+ // #endif
81
82
  addGlobalClass: true,
82
83
  styleIsolation: 'shared'
83
84
  }
@@ -91,9 +92,11 @@ import { treeProps, type TreeExpose } from './types'
91
92
  import { isSetsEqual, useTreeMethods } from './utils'
92
93
  import { useVirtualScroll } from '../composables/useVirtualScroll'
93
94
  import { withDefaultUnit, unitConvert, unitConvertWithDefault } from '../common/util'
95
+ import { useTranslate } from '../composables/useTranslate'
94
96
 
95
97
  // 获取组件的 props 和 emit 函数
96
98
  const props = defineProps(treeProps)
99
+ const { translate } = useTranslate('tree')
97
100
  const {
98
101
  modelValue,
99
102
  data,
@@ -181,6 +184,11 @@ const {
181
184
  backToTopThreshold: backToTopThreshold
182
185
  })
183
186
 
187
+ /**
188
+ * 根据原始数据创建树结构。递归遍历构建 TreeNode,记录节点级别、是否叶子节点、展开状态等。
189
+ * @param data - 原始树数据
190
+ * @returns 含 treeNodeMap、levelTreeNodeMap、maxLevel、treeNodes 的树对象
191
+ */
184
192
  const createTree = (data: RawTreeNode[]) => {
185
193
  const treeNodeMap = new Map<string, TreeNode>()
186
194
  const levelTreeNodeMap = new Map<number, TreeNode[]>()
@@ -247,6 +255,12 @@ const toggleExpand = (node: TreeNode, flag: boolean) => {
247
255
  emit('node-collapse', node)
248
256
  }
249
257
  }
258
+ /**
259
+ * 递归切换节点勾选状态。关联模式下同步更新所有子孙节点,并向上递归更新父节点状态。
260
+ * @param node - 当前节点
261
+ * @param flag - 是否选中
262
+ * @param isClick - 是否由点击触发(控制是否 emit node-check)
263
+ */
250
264
  const toggleChecked = (node: TreeNode, flag: boolean, isClick: boolean = false) => {
251
265
  if (!showCheckbox.value || !node || node.disabled) {
252
266
  return
@@ -293,6 +307,10 @@ const updateParentNode = (node: TreeNode) => {
293
307
  updateNode(node.parent)
294
308
  updateParentNode(node.parent)
295
309
  }
310
+ /**
311
+ * 根据子节点状态更新当前节点的勾选/半选状态。
312
+ * 全选→checked,全不选→unchecked,部分选→indeterminate(半选)。
313
+ */
296
314
  const updateNode = (node: TreeNode | undefined) => {
297
315
  if (!node) return
298
316
  if (node.children?.every((item) => item.checked)) {
@@ -447,6 +465,11 @@ const filter = (query: string) => {
447
465
  }
448
466
  }
449
467
 
468
+ /**
469
+ * 执行树节点过滤。遍历所有节点,匹配的节点及其祖先展开显示,不匹配的叶子节点和非匹配分支节点隐藏。
470
+ * @param query - 搜索关键词
471
+ * @returns 应展开的节点 key 集合
472
+ */
450
473
  const doFilter = (query: string) => {
451
474
  if (typeof props.filterMethod !== 'function') {
452
475
  return