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
@@ -13,34 +13,65 @@
13
13
  :root-portal="rootPortal"
14
14
  >
15
15
  <view :class="rootClass">
16
+ <oxy-icon v-if="messageState.showClose" custom-class="oxy-message-box__close" name="close" @click="toggleModal('close')" />
17
+ <slot name="header" />
18
+
16
19
  <view :class="bodyClass">
17
- <view v-if="messageState.title" class="oxy-message-box__title">
18
- {{ messageState.title }}
19
- </view>
20
- <view class="oxy-message-box__content">
21
- <block v-if="messageState.type === 'prompt'">
22
- <oxy-input
23
- v-model="messageState.inputValue"
24
- :type="messageState.inputType"
25
- :size="messageState.inputSize"
26
- :placeholder="messageState.inputPlaceholder"
27
- @input="inputValChange"
28
- />
29
- <view v-if="messageState.showErr" class="oxy-message-box__input-error">
30
- {{ messageState.inputError || translate('inputNoValidate') }}
31
- </view>
32
- </block>
33
- <slot>{{ messageState.msg }}</slot>
20
+ <slot name="image">
21
+ <image v-if="messageState.headerImage" mode="widthFix" class="oxy-message-box__img" :src="messageState.headerImage"></image>
22
+ </slot>
23
+
24
+ <slot name="title" :icon="messageState.icon" :title="messageState.title" :iconProps="messageState.iconProps">
25
+ <view v-if="messageState.iconProps?.name || messageState.title" class="oxy-message-box__title">
26
+ <oxy-icon
27
+ v-if="messageState.iconProps?.name"
28
+ :custom-class="`oxy-message-box__icon ${iconTypeClass}`"
29
+ :name="messageState.iconProps.name"
30
+ :color="messageState.iconProps.color"
31
+ :size="messageState.iconProps.size"
32
+ ></oxy-icon>
33
+ {{ messageState.title }}
34
+ </view>
35
+ </slot>
36
+
37
+ <view class="oxy-message-box__content" v-if="messageState.type === 'prompt' || !!messageState.msg || $slots.default">
38
+ <slot
39
+ :msg="messageState.msg"
40
+ :type="messageState.type"
41
+ :inputValue="messageState.inputValue"
42
+ :showErr="messageState.showErr"
43
+ :inputError="messageState.inputError"
44
+ >
45
+ <block v-if="messageState.type === 'prompt'">
46
+ <view v-if="messageState.msg" class="oxy-message-box__content-text oxy-message-box__content-text--prompt">
47
+ {{ messageState.msg }}
48
+ </view>
49
+ <oxy-input
50
+ v-model="messageState.inputValue"
51
+ :type="messageState.inputType"
52
+ :size="messageState.inputSize"
53
+ :placeholder="messageState.inputPlaceholder || translate('inputPlaceholder')"
54
+ @input="inputValChange"
55
+ />
56
+ <view v-if="messageState.showErr" class="oxy-message-box__input-error">
57
+ {{ messageState.inputError || translate('inputNoValidate') }}
58
+ </view>
59
+ </block>
60
+ <view v-else class="oxy-message-box__content-text">{{ messageState.msg }}</view>
61
+ </slot>
34
62
  </view>
35
63
  </view>
36
- <view :class="`oxy-message-box__actions ${messageState.showCancelButton ? 'oxy-message-box__flex' : 'oxy-message-box__block'}`">
37
- <oxy-button v-bind="customCancelProps" v-if="messageState.showCancelButton" @click="toggleModal('cancel')">
38
- {{ messageState.cancelButtonText || translate('cancel') }}
39
- </oxy-button>
40
- <oxy-button v-bind="customConfirmProps" @click="toggleModal('confirm')">
41
- {{ messageState.confirmButtonText || translate('confirm') }}
42
- </oxy-button>
43
- </view>
64
+
65
+ <slot name="actions" :confirm="() => toggleModal('confirm')" :cancel="() => toggleModal('cancel')" :close="() => toggleModal('close')">
66
+ <view :class="actionsClass">
67
+ <oxy-button v-bind="customCancelProps" v-if="showCancelButton" @click="toggleModal('cancel')">
68
+ {{ messageState.cancelButtonText || translate('cancel') }}
69
+ </oxy-button>
70
+ <oxy-button v-bind="customConfirmProps" v-if="showConfirmButton" @click="toggleModal('confirm')">
71
+ {{ messageState.confirmButtonText || translate('confirm') }}
72
+ </oxy-button>
73
+ </view>
74
+ </slot>
44
75
  </view>
45
76
  </oxy-popup>
46
77
  </view>
@@ -49,7 +80,9 @@
49
80
  export default {
50
81
  name: 'oxy-message-box',
51
82
  options: {
83
+ // #ifndef MP-TOUTIAO
52
84
  virtualHost: true,
85
+ // #endif
53
86
  addGlobalClass: true,
54
87
  styleIsolation: 'shared'
55
88
  }
@@ -60,10 +93,11 @@ export default {
60
93
  import OxyPopup from '../oxy-popup/oxy-popup.vue'
61
94
  import OxyButton from '../oxy-button/oxy-button.vue'
62
95
  import OxyInput from '../oxy-input/oxy-input.vue'
63
- import { computed, inject, reactive, ref, watch } from 'vue'
64
- import { messageBoxProps, type MessageOptionsWithCallBack, type MessageResult } from './types'
65
- import { defaultOptions, getMessageDefaultOptionKey } from '.'
66
- import { deepAssign, isDef, isFunction, isUndefined, omitBy, resolveSizeWithScreenWidth } from '../common/util'
96
+ import OxyIcon from '../oxy-icon/oxy-icon.vue'
97
+ import { computed, onUnmounted, reactive, ref, watch } from 'vue'
98
+ import { messageBoxProps, MESSAGE_BUILTIN_ICON_MAP, type MessageBuiltinIconType, type MessageOptionsWithCallBack, type MessageResult } from './types'
99
+ import { initMessageOptions, removeMessageOptions, resolveMessageScopeId } from '.'
100
+ import { deepAssign, isDef, isFunction, isPromise, isString, isUndefined, omitBy, resolveSizeWithScreenWidth } from '../common/util'
67
101
  import { useTranslate } from '../composables/useTranslate'
68
102
  import type { ButtonProps } from '../oxy-button/types'
69
103
 
@@ -71,20 +105,41 @@ const props = defineProps(messageBoxProps)
71
105
 
72
106
  const { translate } = useTranslate('message-box')
73
107
 
108
+ const iconType = ref<string>('')
109
+
110
+ const iconTypeClass = computed(() => {
111
+ return iconType.value ? `is-${iconType.value}` : ''
112
+ })
113
+
74
114
  const rootClass = computed(() => {
75
115
  return `oxy-message-box__container ${props.customClass}`
76
116
  })
77
117
 
78
118
  const bodyClass = computed(() => {
79
- return `oxy-message-box__body ${!messageState.title ? 'is-no-title' : ''} ${messageState.type === 'prompt' ? 'is-prompt' : ''}`
119
+ return `oxy-message-box__body ${messageState.type === 'prompt' ? 'is-prompt' : ''}`
80
120
  })
81
121
 
82
122
  const popupWidth = computed(() => {
83
123
  return resolveSizeWithScreenWidth(messageState.width || props.width, { defaultUnit: 'rpx' })
84
124
  })
85
125
 
86
- const messageOptionKey = getMessageDefaultOptionKey(props.selector)
87
- const messageOption = inject(messageOptionKey, ref<MessageOptionsWithCallBack>(defaultOptions)) // message选项
126
+ const showCancelButton = computed(() => {
127
+ return !!messageState.showCancelButton && messageState.cancelButtonProps !== null
128
+ })
129
+
130
+ const showConfirmButton = computed(() => {
131
+ return messageState.confirmButtonProps !== null
132
+ })
133
+
134
+ const actionsClass = computed(() => {
135
+ const verticalClass = messageState.actionLayout === 'vertical' ? 'oxy-message-box__actions--vertical' : ''
136
+ const layoutClass = messageState.actionLayout === 'vertical' || showCancelButton.value ? 'oxy-message-box__flex' : 'oxy-message-box__block'
137
+ const themeClass = messageState.theme === 'text' ? 'is-text' : ''
138
+ return `oxy-message-box__actions ${verticalClass} ${layoutClass} ${themeClass}`
139
+ })
140
+
141
+ const scopeId = resolveMessageScopeId()
142
+ const messageOption = initMessageOptions(props.selector, scopeId)
88
143
 
89
144
  const messageState = reactive<MessageOptionsWithCallBack>({
90
145
  msg: '', // 消息内容
@@ -95,6 +150,11 @@ const messageState = reactive<MessageOptionsWithCallBack>({
95
150
  confirmButtonText: '', // 确定按钮文案
96
151
  cancelButtonText: '', // 取消按钮文案
97
152
  type: 'alert', // 弹框类型
153
+ theme: 'button', // 按钮风格
154
+ actionLayout: 'horizontal', // 按钮布局
155
+ headerImage: '', // 头图
156
+ icon: '', // 快捷图标名
157
+ showClose: false, // 关闭按钮
98
158
  inputType: 'text', // 输入框类型
99
159
  inputValue: '', // 输入框初始值
100
160
  inputPlaceholder: '', // 输入框placeholder
@@ -113,9 +173,18 @@ const customConfirmProps = computed(() => {
113
173
  {
114
174
  block: true
115
175
  },
116
- isDef(messageState.confirmButtonProps) ? omitBy(messageState.confirmButtonProps, isUndefined) : {}
176
+ isDef(messageState.confirmButtonProps) && messageState.confirmButtonProps !== null && typeof messageState.confirmButtonProps === 'object'
177
+ ? omitBy(messageState.confirmButtonProps, isUndefined)
178
+ : {}
117
179
  )
118
- buttonProps.customClass = `${buttonProps.customClass || ''} oxy-message-box__actions-btn`
180
+
181
+ if (messageState.theme === 'text') {
182
+ buttonProps.type = 'text'
183
+ // oxy-button 在 text 且 round=true 时会清除默认 min-width,保证操作栏可等分布局
184
+ buttonProps.round = true
185
+ }
186
+
187
+ buttonProps.customClass = `${buttonProps.customClass || ''} oxy-message-box__actions-btn oxy-message-box__actions-btn--confirm`
119
188
  return buttonProps
120
189
  })
121
190
 
@@ -128,8 +197,17 @@ const customCancelProps = computed(() => {
128
197
  block: true,
129
198
  type: 'info'
130
199
  },
131
- isDef(messageState.cancelButtonProps) ? omitBy(messageState.cancelButtonProps, isUndefined) : {}
200
+ isDef(messageState.cancelButtonProps) && messageState.cancelButtonProps !== null && typeof messageState.cancelButtonProps === 'object'
201
+ ? omitBy(messageState.cancelButtonProps, isUndefined)
202
+ : {}
132
203
  )
204
+
205
+ if (messageState.theme === 'text') {
206
+ buttonProps.type = 'text'
207
+ // oxy-button 在 text 且 round=true 时会清除默认 min-width,保证操作栏可等分布局
208
+ buttonProps.round = true
209
+ }
210
+
133
211
  buttonProps.customClass = `${buttonProps.customClass || ''} oxy-message-box__actions-btn`
134
212
  return buttonProps
135
213
  })
@@ -157,45 +235,75 @@ watch(
157
235
  }
158
236
  )
159
237
 
238
+ onUnmounted(() => {
239
+ removeMessageOptions(props.selector, scopeId)
240
+ })
241
+
160
242
  /**
161
243
  * 点击操作
162
244
  * @param action
163
245
  */
164
- function toggleModal(action: 'confirm' | 'cancel' | 'modal') {
246
+ function toggleModal(action: 'confirm' | 'cancel' | 'modal' | 'close') {
165
247
  if (action === 'modal' && !messageState.closeOnClickModal) {
166
248
  return
167
249
  }
168
250
  if (messageState.type === 'prompt' && action === 'confirm' && !validate()) {
169
251
  return
170
252
  }
253
+
171
254
  switch (action) {
172
255
  case 'confirm':
173
256
  if (messageState.beforeConfirm) {
174
- messageState.beforeConfirm({
175
- resolve: (isPass) => {
176
- if (isPass) {
177
- handleConfirm({
178
- action: action,
179
- value: messageState.inputValue
180
- })
181
- }
257
+ const inputValue = messageState.inputValue || ''
258
+ let handled = false
259
+
260
+ const finishConfirm = (isPass: boolean) => {
261
+ if (handled) return
262
+ handled = true
263
+ if (isPass) {
264
+ handleConfirm({
265
+ action: 'confirm',
266
+ value: inputValue
267
+ })
182
268
  }
269
+ }
270
+
271
+ const result = messageState.beforeConfirm({
272
+ value: inputValue,
273
+ resolve: finishConfirm
183
274
  })
184
- } else {
185
- handleConfirm({
186
- action: action,
187
- value: messageState.inputValue
188
- })
275
+
276
+ if (isPromise(result)) {
277
+ result
278
+ .then((isPass) => {
279
+ finishConfirm(!!isPass)
280
+ })
281
+ .catch(() => {})
282
+ return
283
+ }
284
+
285
+ if (typeof result === 'boolean') {
286
+ finishConfirm(result)
287
+ return
288
+ }
289
+
290
+ return
189
291
  }
292
+
293
+ handleConfirm({
294
+ action: 'confirm',
295
+ value: messageState.inputValue
296
+ })
190
297
  break
191
298
  case 'cancel':
192
299
  handleCancel({
193
- action: action
300
+ action: 'cancel'
194
301
  })
195
302
  break
196
- default:
303
+ case 'modal':
304
+ case 'close':
197
305
  handleCancel({
198
- action: 'modal'
306
+ action: action
199
307
  })
200
308
  break
201
309
  }
@@ -224,7 +332,7 @@ function handleCancel(result: MessageResult) {
224
332
  }
225
333
 
226
334
  /**
227
- * 如果存在校验规则行为,则进行判断校验是否通过规则。默认不存在校验直接铜鼓。
335
+ * 如果存在校验规则行为,则进行判断校验是否通过规则。默认不存在校验直接通过。
228
336
  */
229
337
  function validate() {
230
338
  if (messageState.inputPattern && !messageState.inputPattern.test(String(messageState.inputValue))) {
@@ -251,9 +359,11 @@ function resetErr(val: boolean) {
251
359
  messageState.showErr = false
252
360
  }
253
361
  }
362
+
254
363
  function inputValChange({ value }: { value: string | number }) {
255
364
  if (value === '') {
256
365
  messageState.showErr = false
366
+ messageState.inputValue = value
257
367
  return
258
368
  }
259
369
  messageState.inputValue = value
@@ -267,15 +377,19 @@ function reset(option: MessageOptionsWithCallBack) {
267
377
  if (option) {
268
378
  messageState.title = isDef(option.title) ? option.title : ''
269
379
  messageState.showCancelButton = isDef(option.showCancelButton) ? option.showCancelButton : false
270
- messageState.show = option.show
271
- messageState.closeOnClickModal = option.closeOnClickModal
380
+ messageState.show = !!option.show
381
+ messageState.closeOnClickModal = isDef(option.closeOnClickModal) ? option.closeOnClickModal : true
272
382
  messageState.confirmButtonText = option.confirmButtonText
273
383
  messageState.cancelButtonText = option.cancelButtonText
274
384
  messageState.msg = option.msg
275
385
  messageState.type = option.type
386
+ messageState.theme = isDef(option.theme) ? option.theme : 'button'
387
+ messageState.actionLayout = isDef(option.actionLayout) ? option.actionLayout : 'horizontal'
388
+ messageState.headerImage = isDef(option.headerImage) ? option.headerImage : ''
389
+ messageState.icon = isDef(option.icon) ? option.icon : ''
276
390
  messageState.inputType = option.inputType
277
391
  messageState.inputSize = option.inputSize
278
- messageState.inputValue = option.inputValue
392
+ messageState.inputValue = isDef(option.inputValue) ? option.inputValue : ''
279
393
  messageState.inputPlaceholder = option.inputPlaceholder
280
394
  messageState.inputPattern = option.inputPattern!
281
395
  messageState.inputValidate = option.inputValidate
@@ -287,8 +401,19 @@ function reset(option: MessageOptionsWithCallBack) {
287
401
  messageState.zIndex = option.zIndex
288
402
  messageState.lazyRender = option.lazyRender
289
403
  messageState.width = isDef(option.width) ? option.width : props.width
404
+ messageState.showClose = isDef(option.showClose) ? option.showClose : false
290
405
  messageState.confirmButtonProps = option.confirmButtonProps
291
406
  messageState.cancelButtonProps = option.cancelButtonProps
407
+
408
+ const iconName = option.iconProps?.name || option.icon
409
+ if (isString(iconName) && iconName in MESSAGE_BUILTIN_ICON_MAP) {
410
+ const builtinIcon = MESSAGE_BUILTIN_ICON_MAP[iconName as MessageBuiltinIconType]
411
+ messageState.iconProps = { ...option.iconProps, name: builtinIcon }
412
+ iconType.value = iconName
413
+ } else {
414
+ messageState.iconProps = option.iconProps
415
+ iconType.value = ''
416
+ }
292
417
  }
293
418
  }
294
419
  </script>
@@ -1,13 +1,36 @@
1
1
  import { baseProps, makeStringProp, makeBooleanProp } from '../common/props'
2
2
  import type { ButtonProps } from '../oxy-button/types'
3
+ import type { IconProps } from '../oxy-icon/types'
3
4
  import { type InputSize, type InputType } from '../oxy-input/types'
4
5
 
5
6
  export type MessageType = 'alert' | 'confirm' | 'prompt'
7
+ export type MessageTheme = 'button' | 'text'
8
+ export type MessageActionLayout = 'horizontal' | 'vertical'
9
+ export type MessageBuiltinIconType = 'success' | 'info' | 'warning' | 'danger'
10
+
11
+ /**
12
+ * 内置图标类型和 oxy-icon 图标名映射
13
+ */
14
+ export const MESSAGE_BUILTIN_ICON_MAP: Record<MessageBuiltinIconType, string> = {
15
+ success: 'check-circle-filled',
16
+ info: 'info-circle-filled',
17
+ warning: 'warning',
18
+ danger: 'error-circle-filled'
19
+ }
6
20
 
7
21
  export type MessageBeforeConfirmOption = {
22
+ /**
23
+ * 弹框当前输入值(仅 prompt 时有意义)
24
+ */
25
+ value: string | number
26
+ /**
27
+ * 兼容旧版 beforeConfirm 回调方式,调用后决定是否继续确认
28
+ */
8
29
  resolve: (isPass: boolean) => void
9
30
  }
10
31
 
32
+ export type MessageBeforeConfirm = (options: MessageBeforeConfirmOption) => void | boolean | Promise<boolean>
33
+
11
34
  export type MessageOptions = {
12
35
  /**
13
36
  * 标题
@@ -37,6 +60,41 @@ export type MessageOptions = {
37
60
  * 弹框类型
38
61
  */
39
62
  type?: MessageType
63
+ /**
64
+ * 弹框操作按钮风格
65
+ * @default 'button'
66
+ */
67
+ theme?: MessageTheme
68
+ /**
69
+ * 操作按钮布局方式
70
+ * @default 'horizontal'
71
+ */
72
+ actionLayout?: MessageActionLayout
73
+ /**
74
+ * 顶部头图地址
75
+ * @default ''
76
+ */
77
+ headerImage?: string
78
+ /**
79
+ * 图标名称,支持内置类型(success / info / warning / danger)或 oxy-icon 图标名
80
+ * @default ''
81
+ */
82
+ icon?: MessageBuiltinIconType | string
83
+ /**
84
+ * 图标颜色(优先级高于内置类型颜色)
85
+ * @default ''
86
+ */
87
+ iconColor?: string
88
+ /**
89
+ * 图标组件透传属性
90
+ * @default undefined
91
+ */
92
+ iconProps?: Partial<IconProps>
93
+ /**
94
+ * 是否显示右上角关闭按钮
95
+ * @default false
96
+ */
97
+ showClose?: boolean
40
98
  /**
41
99
  * 当type为prompt时,输入框类型
42
100
  */
@@ -84,7 +142,7 @@ export type MessageOptions = {
84
142
  /**
85
143
  * 确认前钩子
86
144
  */
87
- beforeConfirm?: (options: MessageBeforeConfirmOption) => void
145
+ beforeConfirm?: MessageBeforeConfirm
88
146
  /**
89
147
  * 取消按钮Props
90
148
  */
@@ -101,7 +159,7 @@ export type MessageOptionsWithCallBack = MessageOptions & {
101
159
  fail?: (res: MessageResult) => void
102
160
  }
103
161
 
104
- export type ActionType = 'confirm' | 'cancel' | 'modal'
162
+ export type ActionType = 'confirm' | 'cancel' | 'modal' | 'close'
105
163
 
106
164
  export type InputValidate = (inputValue: string | number) => boolean
107
165
 
@@ -58,7 +58,7 @@
58
58
  font-size: $-navbar-desc-font-size;
59
59
  display: flex;
60
60
  align-items: center;
61
- padding: 0 24rpx;
61
+ padding: 0 $-spacing-24;
62
62
 
63
63
  @include when(disabled) {
64
64
  opacity: $-navbar-disabled-opacity;
@@ -1,10 +1,7 @@
1
1
  <template>
2
2
  <view :style="placeholderStyle">
3
3
  <view :class="`oxy-navbar ${customClass} ${fixed ? 'is-fixed' : ''} ${bordered ? 'is-border' : ''}`" :style="rootStyle">
4
- <view
5
- class="oxy-navbar__content"
6
- :style="{ width: fixed && avoidMenuButtonMode === 'full' ? unitConvert(navWidth, 0, { output: 'px' }) : '100%' }"
7
- >
4
+ <view class="oxy-navbar__content" :style="{ width: avoidMenuButtonMode === 'full' ? unitConvert(navWidth, 0, { output: 'px' }) : '100%' }">
8
5
  <view class="oxy-navbar__capsule" v-if="$slots.capsule">
9
6
  <slot name="capsule" />
10
7
  </view>
@@ -42,7 +39,9 @@
42
39
  export default {
43
40
  name: 'oxy-navbar',
44
41
  options: {
42
+ // #ifndef MP-TOUTIAO
45
43
  virtualHost: true,
44
+ // #endif
46
45
  addGlobalClass: true,
47
46
  styleIsolation: 'shared'
48
47
  }
@@ -93,7 +92,7 @@ const rootStyle = computed(() => {
93
92
 
94
93
  const rightStyle = computed(() => {
95
94
  const style: CSSProperties = {}
96
- if (props.fixed && props.avoidMenuButtonMode === 'right' && navWidth.value !== 'auto') {
95
+ if (props.avoidMenuButtonMode === 'right' && navWidth.value !== 'auto') {
97
96
  style['right'] = `calc(100% - ${unitConvert(navWidth.value, 0, { output: 'px' })})`
98
97
  }
99
98
  return style
@@ -104,7 +103,7 @@ onMounted(() => {
104
103
  setPlaceholderHeight()
105
104
  }
106
105
  // #ifdef MP-WEIXIN
107
- if (props.fixed && props.avoidMenuButtonMode) {
106
+ if (props.avoidMenuButtonMode) {
108
107
  const menuBtnInfo = uni.getMenuButtonBoundingClientRect()
109
108
  navWidth.value = menuBtnInfo.left
110
109
  }
@@ -125,6 +124,10 @@ function handleClickRight() {
125
124
 
126
125
  const { proxy } = getCurrentInstance() as any
127
126
 
127
+ /**
128
+ * 计算占位高度。fixed 模式下,查询 navbar 的 rect 得到实际占用高度,
129
+ * 转换为 rpx 用于占位,避免内容被 fixed 导航栏遮挡。
130
+ */
128
131
  function setPlaceholderHeight() {
129
132
  if (!props.fixed || !props.placeholder) {
130
133
  placeholderHeight.value = ''
@@ -8,7 +8,9 @@
8
8
  export default {
9
9
  name: 'oxy-navbar-capsule',
10
10
  options: {
11
+ // #ifndef MP-TOUTIAO
11
12
  virtualHost: true,
13
+ // #endif
12
14
  addGlobalClass: true,
13
15
  styleIsolation: 'shared'
14
16
  }
@@ -22,7 +22,7 @@
22
22
  color: $-notice-bar-danger-color;
23
23
  }
24
24
  @include edeep(prefix) {
25
- padding-right: 8rpx;
25
+ padding-right: $-spacing-8;
26
26
  font-size: $-notice-bar-prefix-size;
27
27
  }
28
28
 
@@ -19,7 +19,9 @@
19
19
  export default {
20
20
  name: 'oxy-notice-bar',
21
21
  options: {
22
+ // #ifndef MP-TOUTIAO
22
23
  virtualHost: true,
24
+ // #endif
23
25
  addGlobalClass: true,
24
26
  styleIsolation: 'shared'
25
27
  }
@@ -130,10 +132,17 @@ function reset() {
130
132
  startTransition()
131
133
  }
132
134
 
135
+ /**
136
+ * 启动滚动动画(横向走马灯或纵向轮播)
137
+ * 在 nextTick 后调用 scroll() 计算并设置 CSS transition
138
+ */
133
139
  function startTransition() {
134
140
  nextTick(() => scroll())
135
141
  }
136
142
 
143
+ /**
144
+ * 停止动画:清除所有 transition 属性并重置状态
145
+ */
137
146
  function stopTransition() {
138
147
  transitionState.transitionProperty = 'unset'
139
148
  transitionState.transitionDelay = 'unset'
@@ -149,6 +158,12 @@ function handleClose() {
149
158
  emit('close')
150
159
  }
151
160
 
161
+ /**
162
+ * 设置 CSS transition 属性(横向 translateX 或纵向 translateY)
163
+ * @param duration - 动画时长(秒)
164
+ * @param delay - 延迟时间(秒)
165
+ * @param translate - 位移距离(像素)
166
+ */
152
167
  function setTransition({ duration, delay, translate }: { duration: number; delay: number; translate: number }) {
153
168
  transitionState.transitionProperty = 'all'
154
169
  transitionState.transitionDelay = `${delay}s`
@@ -161,6 +176,10 @@ function queryRect() {
161
176
  return Promise.all([getRect($wrap, false, proxy), getRect($content, false, proxy)])
162
177
  }
163
178
 
179
+ /**
180
+ * 纵向滚动动画:根据当前索引计算 translateY,实现轮播滚动
181
+ * @param height - 内容区域总高度
182
+ */
164
183
  async function verticalAnimate(height: number) {
165
184
  const translate = -(height / (textArray.value.length + 1)) * (currentIndex.value + 1)
166
185
  setTransition({
@@ -170,6 +189,11 @@ async function verticalAnimate(height: number) {
170
189
  })
171
190
  }
172
191
 
192
+ /**
193
+ * 核心滚动逻辑:查询容器/内容尺寸后计算动画参数
194
+ * 横向模式:设置 translateX 动画使内容从右到左滚动
195
+ * 纵向模式(多条文本):调用 verticalAnimate 逐条轮播
196
+ */
173
197
  async function scroll() {
174
198
  const [wRect, cRect] = await queryRect()
175
199
  if (!wRect.width || !cRect.width || !cRect.height) return
@@ -201,6 +225,11 @@ function next() {
201
225
  emit('next', currentIndex.value)
202
226
  }
203
227
 
228
+ /**
229
+ * 动画结束回调:无缝循环
230
+ * 横向模式:瞬间重置到右侧,查询新宽度后继续滚动
231
+ * 纵向模式:轮播下一条文本
232
+ */
204
233
  function animationEnd() {
205
234
  if (isHorizontal.value) {
206
235
  setTransition({
@@ -1,26 +1,31 @@
1
- import { inject, provide, reactive, ref } from 'vue'
2
1
  import type { NotifyProps } from './types'
3
2
  import { deepMerge, isString } from '../common/util'
3
+ import { createSharedState } from '../composables/useSharedState'
4
4
 
5
5
  let timer: ReturnType<typeof setTimeout>
6
6
  let currentOptions = getDefaultOptions()
7
7
  const notifyDefaultOptionKey = '__NOTIFY_OPTION__'
8
- const None = Symbol('None')
8
+
9
9
  export const setNotifyDefaultOptions = (options: NotifyProps) => {
10
10
  currentOptions = deepMerge(currentOptions, options) as NotifyProps
11
11
  }
12
12
  export const resetNotifyDefaultOptions = () => {
13
13
  currentOptions = getDefaultOptions()
14
14
  }
15
- export const useNotify = (selector: string = '') => {
16
- const notifyOptionKey = getNotifyOptionKey(selector)
17
15
 
18
- const notifyOption = inject(notifyOptionKey, ref<NotifyProps | typeof None>(None))
19
- if (notifyOption.value === None) {
20
- notifyOption.value = currentOptions
21
- provide(notifyOptionKey, notifyOption)
22
- }
16
+ const {
17
+ getState: getNotifyOptions,
18
+ initState: initNotifyOptions,
19
+ removeState: removeNotifyOptions,
20
+ resolveScopeId: resolveNotifyScopeId
21
+ } = createSharedState<NotifyProps>(() => currentOptions, { namespace: 'notify' })
22
+
23
+ export { getNotifyOptions, initNotifyOptions, removeNotifyOptions, resolveNotifyScopeId }
24
+
25
+ export const useNotify = (selector: string = '') => {
26
+ const scopeId = resolveNotifyScopeId()
23
27
  const showNotify = (option: NotifyProps | string) => {
28
+ const notifyOption = initNotifyOptions(selector, scopeId)
24
29
  const options = deepMerge(currentOptions, isString(option) ? { message: option } : option) as NotifyProps
25
30
  notifyOption.value = deepMerge(options, { visible: true })
26
31
  if (notifyOption.value.duration && notifyOption.value.duration > 0) {
@@ -29,10 +34,9 @@ export const useNotify = (selector: string = '') => {
29
34
  }
30
35
  }
31
36
  const closeNotify = () => {
37
+ const notifyOption = initNotifyOptions(selector, scopeId)
32
38
  timer && clearTimeout(timer)
33
- if (notifyOption.value !== None) {
34
- notifyOption.value.visible = false
35
- }
39
+ notifyOption.value.visible = false
36
40
  }
37
41
 
38
42
  return {