oxy-uni-ui 1.0.1

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 (355) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +13 -0
  3. package/attributes.json +1 -0
  4. package/components/common/AbortablePromise.ts +28 -0
  5. package/components/common/abstracts/_config.scss +7 -0
  6. package/components/common/abstracts/_function.scss +89 -0
  7. package/components/common/abstracts/_mixin.scss +385 -0
  8. package/components/common/abstracts/variable.scss +974 -0
  9. package/components/common/base64.ts +29 -0
  10. package/components/common/canvasHelper.ts +49 -0
  11. package/components/common/clickoutside.ts +25 -0
  12. package/components/common/event.ts +8 -0
  13. package/components/common/interceptor.ts +43 -0
  14. package/components/common/props.ts +51 -0
  15. package/components/common/util.ts +778 -0
  16. package/components/composables/index.ts +11 -0
  17. package/components/composables/useCell.ts +13 -0
  18. package/components/composables/useChildren.ts +113 -0
  19. package/components/composables/useCountDown.ts +138 -0
  20. package/components/composables/useLockScroll.ts +37 -0
  21. package/components/composables/useParent.ts +41 -0
  22. package/components/composables/usePopover.ts +176 -0
  23. package/components/composables/useQueue.ts +52 -0
  24. package/components/composables/useRaf.ts +37 -0
  25. package/components/composables/useTouch.ts +43 -0
  26. package/components/composables/useTranslate.ts +12 -0
  27. package/components/composables/useUpload.ts +364 -0
  28. package/components/oxy-action-sheet/index.scss +204 -0
  29. package/components/oxy-action-sheet/oxy-action-sheet.vue +155 -0
  30. package/components/oxy-action-sheet/types.ts +118 -0
  31. package/components/oxy-backtop/index.scss +25 -0
  32. package/components/oxy-backtop/oxy-backtop.vue +45 -0
  33. package/components/oxy-backtop/types.ts +37 -0
  34. package/components/oxy-badge/index.scss +63 -0
  35. package/components/oxy-badge/oxy-badge.vue +61 -0
  36. package/components/oxy-badge/types.ts +41 -0
  37. package/components/oxy-button/index.scss +336 -0
  38. package/components/oxy-button/oxy-button.vue +195 -0
  39. package/components/oxy-button/types.ts +133 -0
  40. package/components/oxy-calendar/index.scss +158 -0
  41. package/components/oxy-calendar/oxy-calendar.vue +451 -0
  42. package/components/oxy-calendar/types.ts +217 -0
  43. package/components/oxy-calendar-view/index.scss +0 -0
  44. package/components/oxy-calendar-view/month/index.scss +162 -0
  45. package/components/oxy-calendar-view/month/month.vue +389 -0
  46. package/components/oxy-calendar-view/month/types.ts +20 -0
  47. package/components/oxy-calendar-view/monthPanel/index.scss +89 -0
  48. package/components/oxy-calendar-view/monthPanel/month-panel.vue +374 -0
  49. package/components/oxy-calendar-view/monthPanel/types.ts +48 -0
  50. package/components/oxy-calendar-view/oxy-calendar-view.vue +111 -0
  51. package/components/oxy-calendar-view/types.ts +109 -0
  52. package/components/oxy-calendar-view/utils.ts +429 -0
  53. package/components/oxy-calendar-view/year/index.scss +153 -0
  54. package/components/oxy-calendar-view/year/types.ts +20 -0
  55. package/components/oxy-calendar-view/year/year.vue +202 -0
  56. package/components/oxy-calendar-view/yearPanel/index.scss +24 -0
  57. package/components/oxy-calendar-view/yearPanel/types.ts +38 -0
  58. package/components/oxy-calendar-view/yearPanel/year-panel.vue +135 -0
  59. package/components/oxy-card/index.scss +71 -0
  60. package/components/oxy-card/oxy-card.vue +37 -0
  61. package/components/oxy-card/types.ts +30 -0
  62. package/components/oxy-cell/index.scss +206 -0
  63. package/components/oxy-cell/oxy-cell.vue +140 -0
  64. package/components/oxy-cell/types.ts +111 -0
  65. package/components/oxy-cell-group/index.scss +56 -0
  66. package/components/oxy-cell-group/oxy-cell-group.vue +45 -0
  67. package/components/oxy-cell-group/types.ts +32 -0
  68. package/components/oxy-checkbox/index.scss +285 -0
  69. package/components/oxy-checkbox/oxy-checkbox.vue +177 -0
  70. package/components/oxy-checkbox/types.ts +68 -0
  71. package/components/oxy-checkbox-group/index.scss +20 -0
  72. package/components/oxy-checkbox-group/oxy-checkbox-group.vue +100 -0
  73. package/components/oxy-checkbox-group/types.ts +59 -0
  74. package/components/oxy-circle/index.scss +18 -0
  75. package/components/oxy-circle/oxy-circle.vue +296 -0
  76. package/components/oxy-circle/types.ts +54 -0
  77. package/components/oxy-col/index.scss +19 -0
  78. package/components/oxy-col/oxy-col.vue +49 -0
  79. package/components/oxy-col/types.ts +15 -0
  80. package/components/oxy-col-picker/index.scss +168 -0
  81. package/components/oxy-col-picker/oxy-col-picker.vue +498 -0
  82. package/components/oxy-col-picker/types.ts +166 -0
  83. package/components/oxy-collapse/index.scss +55 -0
  84. package/components/oxy-collapse/oxy-collapse.vue +151 -0
  85. package/components/oxy-collapse/types.ts +58 -0
  86. package/components/oxy-collapse-item/index.scss +90 -0
  87. package/components/oxy-collapse-item/oxy-collapse-item.vue +171 -0
  88. package/components/oxy-collapse-item/types.ts +48 -0
  89. package/components/oxy-config-provider/oxy-config-provider.vue +73 -0
  90. package/components/oxy-config-provider/types.ts +1052 -0
  91. package/components/oxy-count-down/index.scss +15 -0
  92. package/components/oxy-count-down/oxy-count-down.vue +60 -0
  93. package/components/oxy-count-down/types.ts +41 -0
  94. package/components/oxy-count-down/utils.ts +52 -0
  95. package/components/oxy-count-to/index.scss +7 -0
  96. package/components/oxy-count-to/oxy-count-to.vue +125 -0
  97. package/components/oxy-count-to/types.ts +117 -0
  98. package/components/oxy-curtain/index.scss +85 -0
  99. package/components/oxy-curtain/oxy-curtain.vue +172 -0
  100. package/components/oxy-curtain/types.ts +73 -0
  101. package/components/oxy-datetime-picker/index.scss +164 -0
  102. package/components/oxy-datetime-picker/oxy-datetime-picker.vue +801 -0
  103. package/components/oxy-datetime-picker/types.ts +231 -0
  104. package/components/oxy-datetime-picker-view/oxy-datetime-picker-view.vue +499 -0
  105. package/components/oxy-datetime-picker-view/types.ts +120 -0
  106. package/components/oxy-datetime-picker-view/util.ts +30 -0
  107. package/components/oxy-design-uni/oxy-design-uni.vue +5 -0
  108. package/components/oxy-divider/index.scss +100 -0
  109. package/components/oxy-divider/oxy-divider.vue +52 -0
  110. package/components/oxy-divider/types.ts +35 -0
  111. package/components/oxy-drop-menu/index.scss +86 -0
  112. package/components/oxy-drop-menu/oxy-drop-menu.vue +166 -0
  113. package/components/oxy-drop-menu/types.ts +38 -0
  114. package/components/oxy-drop-menu-item/index.scss +66 -0
  115. package/components/oxy-drop-menu-item/oxy-drop-menu-item.vue +221 -0
  116. package/components/oxy-drop-menu-item/types.ts +94 -0
  117. package/components/oxy-fab/index.scss +116 -0
  118. package/components/oxy-fab/oxy-fab.vue +276 -0
  119. package/components/oxy-fab/types.ts +66 -0
  120. package/components/oxy-floating-panel/index.scss +64 -0
  121. package/components/oxy-floating-panel/oxy-floating-panel.vue +140 -0
  122. package/components/oxy-floating-panel/type.ts +32 -0
  123. package/components/oxy-form/oxy-form.vue +207 -0
  124. package/components/oxy-form/types.ts +76 -0
  125. package/components/oxy-form-item/index.scss +18 -0
  126. package/components/oxy-form-item/oxy-form-item.vue +56 -0
  127. package/components/oxy-form-item/types.ts +16 -0
  128. package/components/oxy-gap/index.scss +9 -0
  129. package/components/oxy-gap/oxy-gap.vue +36 -0
  130. package/components/oxy-gap/types.ts +17 -0
  131. package/components/oxy-grid/index.scss +9 -0
  132. package/components/oxy-grid/oxy-grid.vue +106 -0
  133. package/components/oxy-grid/types.ts +50 -0
  134. package/components/oxy-grid-item/index.scss +148 -0
  135. package/components/oxy-grid-item/oxy-grid-item.vue +176 -0
  136. package/components/oxy-grid-item/types.ts +77 -0
  137. package/components/oxy-icon/index.scss +1230 -0
  138. package/components/oxy-icon/oxy-icon.vue +53 -0
  139. package/components/oxy-icon/oxy-icons.ttf +0 -0
  140. package/components/oxy-icon/types.ts +21 -0
  141. package/components/oxy-img/index.scss +19 -0
  142. package/components/oxy-img/oxy-img.vue +81 -0
  143. package/components/oxy-img/types.ts +61 -0
  144. package/components/oxy-img-cropper/index.scss +231 -0
  145. package/components/oxy-img-cropper/oxy-img-cropper.vue +664 -0
  146. package/components/oxy-img-cropper/types.ts +76 -0
  147. package/components/oxy-index-anchor/index.scss +35 -0
  148. package/components/oxy-index-anchor/oxy-index-anchor.vue +55 -0
  149. package/components/oxy-index-anchor/type.ts +9 -0
  150. package/components/oxy-index-bar/index.scss +39 -0
  151. package/components/oxy-index-bar/oxy-index-bar.vue +156 -0
  152. package/components/oxy-index-bar/type.ts +23 -0
  153. package/components/oxy-input/index.scss +323 -0
  154. package/components/oxy-input/oxy-input.vue +300 -0
  155. package/components/oxy-input/placeholder.scss +21 -0
  156. package/components/oxy-input/types.ts +189 -0
  157. package/components/oxy-input-number/index.scss +132 -0
  158. package/components/oxy-input-number/oxy-input-number.vue +464 -0
  159. package/components/oxy-input-number/types.ts +101 -0
  160. package/components/oxy-keyboard/constants.ts +81 -0
  161. package/components/oxy-keyboard/index.scss +102 -0
  162. package/components/oxy-keyboard/key/index.scss +79 -0
  163. package/components/oxy-keyboard/key/index.vue +76 -0
  164. package/components/oxy-keyboard/key/types.ts +11 -0
  165. package/components/oxy-keyboard/oxy-keyboard.vue +206 -0
  166. package/components/oxy-keyboard/types.ts +92 -0
  167. package/components/oxy-loading/index.scss +37 -0
  168. package/components/oxy-loading/oxy-loading.vue +90 -0
  169. package/components/oxy-loading/types.ts +22 -0
  170. package/components/oxy-loadmore/index.scss +39 -0
  171. package/components/oxy-loadmore/oxy-loadmore.vue +59 -0
  172. package/components/oxy-loadmore/types.ts +30 -0
  173. package/components/oxy-message-box/index.scss +108 -0
  174. package/components/oxy-message-box/index.ts +87 -0
  175. package/components/oxy-message-box/oxy-message-box.vue +291 -0
  176. package/components/oxy-message-box/types.ts +132 -0
  177. package/components/oxy-navbar/index.scss +93 -0
  178. package/components/oxy-navbar/oxy-navbar.vue +111 -0
  179. package/components/oxy-navbar/types.ts +52 -0
  180. package/components/oxy-navbar-capsule/index.scss +66 -0
  181. package/components/oxy-navbar-capsule/oxy-navbar-capsule.vue +35 -0
  182. package/components/oxy-navbar-capsule/types.ts +8 -0
  183. package/components/oxy-notice-bar/index.scss +68 -0
  184. package/components/oxy-notice-bar/oxy-notice-bar.vue +266 -0
  185. package/components/oxy-notice-bar/types.ts +67 -0
  186. package/components/oxy-notify/index.scss +34 -0
  187. package/components/oxy-notify/index.ts +61 -0
  188. package/components/oxy-notify/oxy-notify.vue +85 -0
  189. package/components/oxy-notify/types.ts +66 -0
  190. package/components/oxy-number-keyboard/index.scss +78 -0
  191. package/components/oxy-number-keyboard/key/index.scss +81 -0
  192. package/components/oxy-number-keyboard/key/index.vue +78 -0
  193. package/components/oxy-number-keyboard/key/types.ts +11 -0
  194. package/components/oxy-number-keyboard/oxy-number-keyboard.vue +151 -0
  195. package/components/oxy-number-keyboard/types.ts +83 -0
  196. package/components/oxy-overlay/index.scss +17 -0
  197. package/components/oxy-overlay/oxy-overlay.vue +47 -0
  198. package/components/oxy-overlay/types.ts +25 -0
  199. package/components/oxy-pagination/index.scss +57 -0
  200. package/components/oxy-pagination/oxy-pagination.vue +110 -0
  201. package/components/oxy-pagination/types.ts +41 -0
  202. package/components/oxy-password-input/index.scss +124 -0
  203. package/components/oxy-password-input/oxy-password-input.vue +49 -0
  204. package/components/oxy-password-input/types.ts +33 -0
  205. package/components/oxy-picker/index.scss +110 -0
  206. package/components/oxy-picker/oxy-picker.vue +412 -0
  207. package/components/oxy-picker/types.ts +189 -0
  208. package/components/oxy-picker-view/index.scss +92 -0
  209. package/components/oxy-picker-view/oxy-picker-view.vue +369 -0
  210. package/components/oxy-picker-view/types.ts +152 -0
  211. package/components/oxy-popover/index.scss +116 -0
  212. package/components/oxy-popover/oxy-popover.vue +180 -0
  213. package/components/oxy-popover/types.ts +69 -0
  214. package/components/oxy-popup/index.scss +84 -0
  215. package/components/oxy-popup/oxy-popup.vue +169 -0
  216. package/components/oxy-popup/types.ts +95 -0
  217. package/components/oxy-progress/index.scss +68 -0
  218. package/components/oxy-progress/oxy-progress.vue +197 -0
  219. package/components/oxy-progress/types.ts +35 -0
  220. package/components/oxy-radio/index.scss +301 -0
  221. package/components/oxy-radio/oxy-radio.vue +118 -0
  222. package/components/oxy-radio/types.ts +42 -0
  223. package/components/oxy-radio-group/index.scss +23 -0
  224. package/components/oxy-radio-group/oxy-radio-group.vue +51 -0
  225. package/components/oxy-radio-group/types.ts +39 -0
  226. package/components/oxy-rate/index.scss +25 -0
  227. package/components/oxy-rate/oxy-rate.vue +178 -0
  228. package/components/oxy-rate/types.ts +103 -0
  229. package/components/oxy-resize/index.scss +27 -0
  230. package/components/oxy-resize/oxy-resize.vue +144 -0
  231. package/components/oxy-resize/types.ts +6 -0
  232. package/components/oxy-root-portal/oxy-root-portal.vue +50 -0
  233. package/components/oxy-row/index.scss +10 -0
  234. package/components/oxy-row/oxy-row.vue +42 -0
  235. package/components/oxy-row/types.ts +16 -0
  236. package/components/oxy-search/index.scss +148 -0
  237. package/components/oxy-search/oxy-search.vue +187 -0
  238. package/components/oxy-search/types.ts +93 -0
  239. package/components/oxy-segmented/index.scss +101 -0
  240. package/components/oxy-segmented/oxy-segmented.vue +143 -0
  241. package/components/oxy-segmented/types.ts +71 -0
  242. package/components/oxy-select-picker/index.scss +102 -0
  243. package/components/oxy-select-picker/oxy-select-picker.vue +432 -0
  244. package/components/oxy-select-picker/types.ts +123 -0
  245. package/components/oxy-sidebar/index.scss +25 -0
  246. package/components/oxy-sidebar/oxy-sidebar.vue +63 -0
  247. package/components/oxy-sidebar/types.ts +38 -0
  248. package/components/oxy-sidebar-item/index.scss +97 -0
  249. package/components/oxy-sidebar-item/oxy-sidebar-item.vue +116 -0
  250. package/components/oxy-sidebar-item/types.ts +31 -0
  251. package/components/oxy-signature/index.scss +31 -0
  252. package/components/oxy-signature/oxy-signature.vue +630 -0
  253. package/components/oxy-signature/types.ts +108 -0
  254. package/components/oxy-skeleton/index.scss +96 -0
  255. package/components/oxy-skeleton/index.ts +1 -0
  256. package/components/oxy-skeleton/oxy-skeleton.vue +110 -0
  257. package/components/oxy-skeleton/types.ts +69 -0
  258. package/components/oxy-slider/index.scss +98 -0
  259. package/components/oxy-slider/oxy-slider.vue +356 -0
  260. package/components/oxy-slider/types.ts +138 -0
  261. package/components/oxy-sort-button/index.scss +89 -0
  262. package/components/oxy-sort-button/oxy-sort-button.vue +69 -0
  263. package/components/oxy-sort-button/types.ts +43 -0
  264. package/components/oxy-status-tip/images/collect.png +0 -0
  265. package/components/oxy-status-tip/images/content.png +0 -0
  266. package/components/oxy-status-tip/images/network.png +0 -0
  267. package/components/oxy-status-tip/images/search.png +0 -0
  268. package/components/oxy-status-tip/index.scss +37 -0
  269. package/components/oxy-status-tip/oxy-status-tip.vue +71 -0
  270. package/components/oxy-status-tip/types.ts +50 -0
  271. package/components/oxy-step/index.scss +235 -0
  272. package/components/oxy-step/oxy-step.vue +150 -0
  273. package/components/oxy-step/types.ts +33 -0
  274. package/components/oxy-steps/index.scss +10 -0
  275. package/components/oxy-steps/oxy-steps.vue +28 -0
  276. package/components/oxy-steps/types.ts +50 -0
  277. package/components/oxy-sticky/index.scss +9 -0
  278. package/components/oxy-sticky/oxy-sticky.vue +190 -0
  279. package/components/oxy-sticky/types.ts +13 -0
  280. package/components/oxy-sticky-box/index.scss +6 -0
  281. package/components/oxy-sticky-box/oxy-sticky-box.vue +155 -0
  282. package/components/oxy-sticky-box/types.ts +11 -0
  283. package/components/oxy-swipe-action/index.scss +22 -0
  284. package/components/oxy-swipe-action/oxy-swipe-action.vue +294 -0
  285. package/components/oxy-swipe-action/types.ts +40 -0
  286. package/components/oxy-swiper/index.scss +53 -0
  287. package/components/oxy-swiper/oxy-swiper.vue +318 -0
  288. package/components/oxy-swiper/types.ts +264 -0
  289. package/components/oxy-swiper-nav/index.scss +159 -0
  290. package/components/oxy-swiper-nav/oxy-swiper-nav.vue +37 -0
  291. package/components/oxy-swiper-nav/types.ts +42 -0
  292. package/components/oxy-switch/index.scss +58 -0
  293. package/components/oxy-switch/oxy-switch.vue +83 -0
  294. package/components/oxy-switch/types.ts +58 -0
  295. package/components/oxy-tab/index.scss +16 -0
  296. package/components/oxy-tab/oxy-tab.vue +88 -0
  297. package/components/oxy-tab/types.ts +30 -0
  298. package/components/oxy-tabbar/index.scss +62 -0
  299. package/components/oxy-tabbar/oxy-tabbar.vue +91 -0
  300. package/components/oxy-tabbar/types.ts +73 -0
  301. package/components/oxy-tabbar-item/index.scss +55 -0
  302. package/components/oxy-tabbar-item/oxy-tabbar-item.vue +99 -0
  303. package/components/oxy-tabbar-item/types.ts +51 -0
  304. package/components/oxy-table/index.scss +163 -0
  305. package/components/oxy-table/oxy-table.vue +283 -0
  306. package/components/oxy-table/types.ts +58 -0
  307. package/components/oxy-table-col/index.scss +46 -0
  308. package/components/oxy-table-col/oxy-table-col.vue +149 -0
  309. package/components/oxy-table-col/types.ts +54 -0
  310. package/components/oxy-tabs/index.scss +299 -0
  311. package/components/oxy-tabs/oxy-tabs.vue +443 -0
  312. package/components/oxy-tabs/types.ts +107 -0
  313. package/components/oxy-tag/index.scss +115 -0
  314. package/components/oxy-tag/oxy-tag.vue +148 -0
  315. package/components/oxy-tag/types.ts +81 -0
  316. package/components/oxy-text/index.scss +37 -0
  317. package/components/oxy-text/oxy-text.vue +139 -0
  318. package/components/oxy-text/types.ts +98 -0
  319. package/components/oxy-textarea/index.scss +340 -0
  320. package/components/oxy-textarea/oxy-textarea.vue +296 -0
  321. package/components/oxy-textarea/placeholder.scss +20 -0
  322. package/components/oxy-textarea/types.ts +288 -0
  323. package/components/oxy-toast/index.scss +75 -0
  324. package/components/oxy-toast/index.ts +92 -0
  325. package/components/oxy-toast/oxy-toast.vue +198 -0
  326. package/components/oxy-toast/types.ts +181 -0
  327. package/components/oxy-tooltip/index.scss +66 -0
  328. package/components/oxy-tooltip/oxy-tooltip.vue +141 -0
  329. package/components/oxy-tooltip/types.ts +107 -0
  330. package/components/oxy-transition/index.scss +95 -0
  331. package/components/oxy-transition/oxy-transition.vue +232 -0
  332. package/components/oxy-transition/types.ts +98 -0
  333. package/components/oxy-upload/index.scss +175 -0
  334. package/components/oxy-upload/oxy-upload.vue +673 -0
  335. package/components/oxy-upload/types.ts +391 -0
  336. package/components/oxy-video-preview/index.scss +34 -0
  337. package/components/oxy-video-preview/oxy-video-preview.vue +72 -0
  338. package/components/oxy-video-preview/types.ts +23 -0
  339. package/components/oxy-watermark/index.scss +18 -0
  340. package/components/oxy-watermark/oxy-watermark.vue +486 -0
  341. package/components/oxy-watermark/types.ts +76 -0
  342. package/dayjs/constant.js +26 -0
  343. package/dayjs/index.d.ts +430 -0
  344. package/dayjs/index.js +542 -0
  345. package/dayjs/locale/en.js +13 -0
  346. package/dayjs/utils.js +59 -0
  347. package/global.d.ts +101 -0
  348. package/index.ts +12 -0
  349. package/locale/index.ts +32 -0
  350. package/locale/lang/ar-SA.ts +133 -0
  351. package/locale/lang/en-US.ts +133 -0
  352. package/locale/lang/zh-CN.ts +137 -0
  353. package/package.json +1 -0
  354. package/tags.json +1 -0
  355. package/web-types.json +1 -0
@@ -0,0 +1,499 @@
1
+ <template>
2
+ <oxy-picker-view
3
+ ref="datePickerview"
4
+ :custom-class="customClass"
5
+ :custom-style="customStyle"
6
+ :immediate-change="immediateChange"
7
+ v-model="pickerValue"
8
+ :columns="columns"
9
+ :columns-height="columnsHeight"
10
+ :item-height="itemHeight"
11
+ :columnChange="columnChange"
12
+ :loading="loading"
13
+ :loading-color="loadingColor"
14
+ @change="onChange"
15
+ @pickstart="onPickStart"
16
+ @pickend="onPickEnd"
17
+ ></oxy-picker-view>
18
+ </template>
19
+ <script lang="ts">
20
+ export default {
21
+ name: 'oxy-datetime-picker-view',
22
+ virtualHost: true,
23
+ addGlobalClass: true,
24
+ styleIsolation: 'shared'
25
+ }
26
+ </script>
27
+
28
+ <script lang="ts" setup>
29
+ import OxyPickerView from '../oxy-picker-view/oxy-picker-view.vue'
30
+ import { getCurrentInstance, onBeforeMount, ref, watch } from 'vue'
31
+ import { debounce, isDef, padZero, range, isArray, isString } from '../common/util'
32
+ import { datetimePickerViewProps, type DatetimePickerViewColumnType, type DatetimePickerViewOption, type DatetimePickerViewExpose } from './types'
33
+ import type { PickerViewInstance } from '../oxy-picker-view/types'
34
+ import { getPickerValue } from './util'
35
+
36
+ // 本地时间戳
37
+ /** @description 判断时间戳是否合法 */
38
+ const isValidDate = (date: string | number | Date) => isDef(date) && !Number.isNaN(date)
39
+ /**
40
+ * @description 生成n个元素,并使用iterator接口进行填充
41
+ * @param n
42
+ * @param iteratee
43
+ * @return {any[]}
44
+ */
45
+ const times = (n: number, iteratee: (index: number) => number) => {
46
+ let index: number = -1
47
+ const length = n < 0 ? 0 : n
48
+ const result: number[] = Array(length)
49
+ while (++index < n) {
50
+ result[index] = iteratee(index)
51
+ }
52
+ return result
53
+ }
54
+ /**
55
+ * @description 获取某年某月有多少天
56
+ * @param {Number} year
57
+ * @param {Number} month
58
+ * @return {Number} day
59
+ */
60
+ const getMonthEndDay = (year: number, month: number) => {
61
+ return 32 - new Date(year, month - 1, 32).getDate()
62
+ }
63
+
64
+ const props = defineProps(datetimePickerViewProps)
65
+ const emit = defineEmits(['change', 'pickstart', 'pickend', 'update:modelValue'])
66
+
67
+ // pickerview
68
+ const datePickerview = ref<PickerViewInstance>()
69
+ // 内部保持时间戳的
70
+ const innerValue = ref<null | string | number>(null)
71
+ // 传递给pickerView的columns的数据
72
+ const columns = ref<DatetimePickerViewOption[][]>([])
73
+ // 传递给pickerView的value的数据
74
+ const pickerValue = ref<string | number | boolean | string[] | number[] | boolean[]>([])
75
+ // 是否已经初始化
76
+ const created = ref<boolean>(false)
77
+
78
+ const { proxy } = getCurrentInstance() as any
79
+
80
+ /**
81
+ * @description updateValue 防抖函数的占位符
82
+ */
83
+ const updateValue = debounce(() => {
84
+ if (!created.value) return
85
+ const val = correctValue(props.modelValue)
86
+ const isEqual = val === innerValue.value
87
+ if (!isEqual) {
88
+ updateColumnValue(val)
89
+ } else {
90
+ columns.value = updateColumns()
91
+ }
92
+ }, 50)
93
+
94
+ watch(
95
+ () => props.modelValue,
96
+ (val, oldVal) => {
97
+ if (val === oldVal) return
98
+ // 外部传入值更改时 更新picker数据
99
+ const value = correctValue(val)
100
+ updateColumnValue(value)
101
+ },
102
+ { deep: true, immediate: true }
103
+ )
104
+
105
+ watch(
106
+ () => props.type,
107
+ (target) => {
108
+ const type = ['date', 'year-month', 'time', 'datetime', 'year']
109
+ if (type.indexOf(target) === -1) {
110
+ console.error(`type must be one of ${type}`)
111
+ }
112
+ },
113
+ { deep: true, immediate: true }
114
+ )
115
+
116
+ watch(
117
+ [
118
+ () => props.type,
119
+ () => props.filter,
120
+ () => props.formatter,
121
+ () => props.columnFormatter,
122
+ () => props.minDate,
123
+ () => props.maxDate,
124
+ () => props.minHour,
125
+ () => props.maxHour,
126
+ () => props.minMinute,
127
+ () => props.maxMinute,
128
+ () => props.minSecond,
129
+ () => props.maxSecond,
130
+ () => props.useSecond
131
+ ],
132
+ () => {
133
+ updateValue()
134
+ },
135
+ {
136
+ deep: true,
137
+ immediate: true
138
+ }
139
+ )
140
+
141
+ onBeforeMount(() => {
142
+ // 初始化完毕,打开observer触发render的开关
143
+ created.value = true
144
+ const innerValue = correctValue(props.modelValue)
145
+ updateColumnValue(innerValue)
146
+ })
147
+
148
+ /** pickerView触发change事件,同步修改pickerValue */
149
+ function onChange({ value }: { value: string | string[] }) {
150
+ // 更新pickerView的value
151
+ pickerValue.value = value
152
+ // pickerValue => innerValue
153
+ const result = updateInnerValue()
154
+ emit('update:modelValue', result)
155
+ // 这个地方的value返回的是picker数组,实际上在此处我们应该返回 change 的是 value date类型的值
156
+ emit('change', {
157
+ value: result,
158
+ picker: proxy.$.exposed
159
+ })
160
+ }
161
+
162
+ /**
163
+ * @description 使用formatter格式化getOriginColumns的结果
164
+ * @return {Array<Array<Number>>} 用于传入picker的columns
165
+ */
166
+ function updateColumns(): DatetimePickerViewOption[][] {
167
+ const { formatter, columnFormatter } = props
168
+ if (columnFormatter) {
169
+ return columnFormatter(proxy.$.exposed)
170
+ } else {
171
+ return getOriginColumns().map((column) => {
172
+ return column.values.map((value) => {
173
+ return {
174
+ label: formatter ? formatter(column.type, padZero(value)) : padZero(value),
175
+ value
176
+ }
177
+ })
178
+ })
179
+ }
180
+ }
181
+
182
+ /**
183
+ * 设置数据列
184
+ * @param columnList 数据列
185
+ */
186
+ function setColumns(columnList: DatetimePickerViewOption[][]) {
187
+ columns.value = columnList
188
+ }
189
+
190
+ /**
191
+ * @description 根据getRanges得到的范围计算所有的列的数据
192
+ * @return {{values: any[], type: String}[]} 年
193
+ */
194
+ function getOriginColumns() {
195
+ const { filter } = props
196
+ return getRanges().map(({ type, range }) => {
197
+ let values = times(range[1] - range[0] + 1, (index: number) => {
198
+ return range[0] + index
199
+ })
200
+
201
+ if (filter) {
202
+ values = filter(type, values)
203
+ }
204
+
205
+ return {
206
+ type,
207
+ values
208
+ }
209
+ })
210
+ }
211
+
212
+ /**
213
+ * @description 根据时间戳生成年月日时分的边界范围
214
+ * @return {Array<{type:String,range:Array<Number>}>}
215
+ */
216
+ function getRanges(): Array<{ type: DatetimePickerViewColumnType; range: number[] }> {
217
+ if (props.type === 'time') {
218
+ const result: Array<{ type: DatetimePickerViewColumnType; range: number[] }> = [
219
+ {
220
+ type: 'hour',
221
+ range: [props.minHour, props.maxHour]
222
+ },
223
+ {
224
+ type: 'minute',
225
+ range: [props.minMinute, props.maxMinute]
226
+ }
227
+ ]
228
+ if (props.useSecond) {
229
+ result.push({
230
+ type: 'second',
231
+ range: [props.minSecond, props.maxSecond]
232
+ })
233
+ }
234
+ return result
235
+ }
236
+
237
+ const { maxYear, maxDate, maxMonth, maxHour, maxMinute, maxSecond } = getBoundary('max', innerValue.value as number)
238
+ const { minYear, minDate, minMonth, minHour, minMinute, minSecond } = getBoundary('min', innerValue.value as number)
239
+
240
+ const result: Array<{ type: DatetimePickerViewColumnType; range: number[] }> = [
241
+ {
242
+ type: 'year',
243
+ range: [minYear, maxYear]
244
+ },
245
+ {
246
+ type: 'month',
247
+ range: [minMonth, maxMonth]
248
+ },
249
+ {
250
+ type: 'date',
251
+ range: [minDate, maxDate]
252
+ },
253
+ {
254
+ type: 'hour',
255
+ range: [minHour, maxHour]
256
+ },
257
+ {
258
+ type: 'minute',
259
+ range: [minMinute, maxMinute]
260
+ }
261
+ ]
262
+
263
+ if (props.type === 'datetime' && props.useSecond) {
264
+ result.push({
265
+ type: 'second',
266
+ range: [minSecond, maxSecond]
267
+ })
268
+ }
269
+
270
+ if (props.type === 'date') result.splice(3, 2)
271
+ if (props.type === 'year-month') result.splice(2, 3)
272
+ if (props.type === 'year') result.splice(1, 4)
273
+ return result
274
+ }
275
+
276
+ /**
277
+ * @description 修正时间入参,判定是否为规范时间类型
278
+ * @param {String | Number} value
279
+ * @return {String | Number} innerValue
280
+ */
281
+ function correctValue(value: string | number | Date): string | number {
282
+ const isDateType = props.type !== 'time'
283
+ if (isDateType && !isValidDate(value)) {
284
+ // 是Date类型,但入参不可用,使用最小时间戳代替
285
+ value = props.minDate
286
+ } else if (!isDateType && !value) {
287
+ // 非Date类型,无入参,使用最小小时代替
288
+ value = props.useSecond ? `${padZero(props.minHour)}:00:00` : `${padZero(props.minHour)}:00`
289
+ }
290
+
291
+ // 当type为time时
292
+ if (!isDateType) {
293
+ // 非Date类型,直接走此逻辑
294
+ let [hour, minute, second = '00'] = (isString(value) ? value : value.toString()).split(':')
295
+ hour = padZero(range(Number(hour), props.minHour, props.maxHour))
296
+ minute = padZero(range(Number(minute), props.minMinute, props.maxMinute))
297
+ if (props.useSecond) {
298
+ second = padZero(range(Number(second), props.minSecond, props.maxSecond))
299
+ return `${hour}:${minute}:${second}`
300
+ }
301
+ return `${hour}:${minute}`
302
+ }
303
+
304
+ // date type
305
+ value = Math.min(Math.max(Number(value), props.minDate), props.maxDate)
306
+
307
+ return value
308
+ }
309
+
310
+ /**
311
+ * @description 根据时间戳,计算所有选项的范围
312
+ * @param {'min'|'max'} type 类型
313
+ * @param {Number} innerValue 时间戳
314
+ */
315
+ function getBoundary(type: 'min' | 'max', innerValue: number) {
316
+ const value = new Date(innerValue)
317
+ const boundary = new Date(props[`${type}Date`])
318
+ const year = boundary.getFullYear()
319
+ let month: number = 1
320
+ let date: number = 1
321
+ let hour: number = 0
322
+ let minute: number = 0
323
+ let second: number = 0
324
+
325
+ if (type === 'max') {
326
+ month = 12
327
+ date = getMonthEndDay(value.getFullYear(), value.getMonth() + 1)
328
+ hour = 23
329
+ minute = 59
330
+ second = 59
331
+ }
332
+
333
+ if (value.getFullYear() === year) {
334
+ month = boundary.getMonth() + 1
335
+ if (value.getMonth() + 1 === month) {
336
+ date = boundary.getDate()
337
+ if (value.getDate() === date) {
338
+ hour = boundary.getHours()
339
+ if (value.getHours() === hour) {
340
+ minute = boundary.getMinutes()
341
+ if (value.getMinutes() === minute) {
342
+ second = boundary.getSeconds()
343
+ }
344
+ }
345
+ }
346
+ }
347
+ }
348
+ return {
349
+ [`${type}Year`]: year,
350
+ [`${type}Month`]: month,
351
+ [`${type}Date`]: date,
352
+ [`${type}Hour`]: hour,
353
+ [`${type}Minute`]: minute,
354
+ [`${type}Second`]: second
355
+ }
356
+ }
357
+
358
+ /**
359
+ * @description 根据传入的value以及type,初始化innerValue,期间会使用format格式化数据
360
+ * @param value
361
+ * @return {Array}
362
+ */
363
+ function updateColumnValue(value: string | number) {
364
+ const values = getPickerValue(value, props.type, props.useSecond)
365
+ // 更新pickerView的value,columns
366
+ if (props.modelValue !== value) {
367
+ emit('update:modelValue', value)
368
+ emit('change', {
369
+ value,
370
+ picker: proxy.$.exposed
371
+ })
372
+ }
373
+ innerValue.value = value
374
+ columns.value = updateColumns()
375
+ pickerValue.value = values
376
+ }
377
+
378
+ /**
379
+ * @description 根据当前的选中项 处理innerValue
380
+ * @return {date} innerValue
381
+ */
382
+ function updateInnerValue() {
383
+ const { type, useSecond } = props
384
+ let innerValue: string | number = ''
385
+ const pickerVal = datePickerview.value?.getValues() || []
386
+ const values = isArray(pickerVal) ? pickerVal : [pickerVal]
387
+
388
+ if (type === 'time') {
389
+ if (useSecond) {
390
+ innerValue = `${padZero(values[0])}:${padZero(values[1])}:${padZero(values[2])}`
391
+ } else {
392
+ innerValue = `${padZero(values[0])}:${padZero(values[1])}`
393
+ }
394
+ return innerValue
395
+ }
396
+
397
+ // 处理年份 索引位0
398
+ const year = values[0] && parseInt(values[0])
399
+
400
+ // 处理月 索引位1
401
+ const month = type === 'year' ? 1 : values[1] && parseInt(values[1])
402
+
403
+ const maxDate = getMonthEndDay(Number(year), Number(month))
404
+
405
+ // 处理 date 日期 索引位2
406
+ let date: string | number = 1
407
+ if (type !== 'year-month' && type !== 'year') {
408
+ date = (Number(values[2]) && parseInt(String(values[2]))) > maxDate ? maxDate : values[2] && parseInt(String(values[2]))
409
+ }
410
+
411
+ // 处理 时分秒 索引位3,4,5
412
+ let hour = 0
413
+ let minute = 0
414
+ let second = 0
415
+
416
+ if (type === 'datetime') {
417
+ hour = Number(values[3]) && parseInt(values[3])
418
+ minute = Number(values[4]) && parseInt(values[4])
419
+ if (useSecond) {
420
+ second = Number(values[5]) && parseInt(values[5])
421
+ }
422
+ }
423
+ const value = new Date(Number(year), Number(month) - 1, Number(date), hour, minute, second).getTime()
424
+
425
+ innerValue = correctValue(value)
426
+ return innerValue
427
+ }
428
+
429
+ /**
430
+ * @description 选中项改变,多级联动
431
+ */
432
+ function columnChange(picker: PickerViewInstance) {
433
+ // time year-mouth year 无需联动
434
+ if (props.type === 'time' || props.type === 'year-month' || props.type === 'year') {
435
+ return
436
+ }
437
+ /** 重新计算年月日时分秒,修正时间。 */
438
+ const values = picker.getValues() as string[]
439
+ const year = Number(values[0])
440
+ const month = Number(values[1])
441
+ const maxDate = getMonthEndDay(year, month)
442
+ let date = Number(values[2])
443
+ date = date > maxDate ? maxDate : date
444
+ let hour: number = 0
445
+ let minute: number = 0
446
+ let second: number = 0
447
+ if (props.type === 'datetime') {
448
+ hour = Number(values[3])
449
+ minute = Number(values[4])
450
+ if (props.useSecond) {
451
+ second = Number(values[5])
452
+ }
453
+ }
454
+ const value = new Date(year, month - 1, date, hour, minute, second).getTime()
455
+ /** 根据计算选中项的时间戳,重新计算所有的选项列表 */
456
+ // 更新选中时间戳
457
+ innerValue.value = correctValue(value)
458
+
459
+ // 根据innerValue获取最新的时间表,重新生成对应的数据源
460
+ const newColumns = updateColumns()
461
+ // 深拷贝联动之前的选中项
462
+ const selectedIndex = picker.getSelectedIndex().slice(0)
463
+ /**
464
+ * 选中年会修改对应的年份的月数,和月份对应的日期。
465
+ * 选中月,会修改月份对应的日数
466
+ */
467
+ newColumns.forEach((_columns, index) => {
468
+ const nextColumnIndex = index + 1
469
+ const nextColumnData = newColumns[nextColumnIndex]
470
+ if (nextColumnIndex > newColumns.length - 1) return
471
+ picker.setColumnData(
472
+ nextColumnIndex,
473
+ nextColumnData,
474
+ selectedIndex[nextColumnIndex] <= nextColumnData.length - 1 ? selectedIndex[nextColumnIndex] : 0
475
+ )
476
+ })
477
+ }
478
+ function onPickStart() {
479
+ emit('pickstart')
480
+ }
481
+ function onPickEnd() {
482
+ emit('pickend')
483
+ }
484
+
485
+ function getSelects() {
486
+ const pickerVal = datePickerview.value?.getSelects()
487
+ if (pickerVal == null) return undefined
488
+ if (isArray(pickerVal)) return pickerVal
489
+ return [pickerVal]
490
+ }
491
+
492
+ defineExpose<DatetimePickerViewExpose>({
493
+ updateColumns,
494
+ setColumns,
495
+ getSelects,
496
+ correctValue,
497
+ getOriginColumns
498
+ })
499
+ </script>
@@ -0,0 +1,120 @@
1
+ import type { ComponentPublicInstance, ExtractPropTypes, PropType } from 'vue'
2
+ import { baseProps, makeBooleanProp, makeNumberProp, makeRequiredProp, makeStringProp } from '../common/props'
3
+
4
+ export type DateTimeType = 'date' | 'year-month' | 'time' | 'datetime' | 'year'
5
+
6
+ export const datetimePickerViewProps = {
7
+ ...baseProps,
8
+ /**
9
+ * 选中项,当 type 为 time 时,类型为字符串,否则为 时间戳
10
+ */
11
+ modelValue: makeRequiredProp([String, Number]),
12
+ /**
13
+ * 加载中
14
+ */
15
+ loading: makeBooleanProp(false),
16
+ /**
17
+ * 加载的颜色,只能使用十六进制的色值写法,且不能使用缩写
18
+ */
19
+ loadingColor: makeStringProp('#4D80F0'),
20
+ /**
21
+ * picker内部滚筒高
22
+ */
23
+ columnsHeight: makeNumberProp(217),
24
+ /**
25
+ * picker item的高度
26
+ */
27
+ itemHeight: makeNumberProp(35),
28
+ /**
29
+ * 选项的key
30
+ */
31
+ valueKey: makeStringProp('value'),
32
+ /**
33
+ * 选项的label
34
+ */
35
+ labelKey: makeStringProp('label'),
36
+ /**
37
+ * 选择器类型,可选值:date / year-month / time
38
+ */
39
+ type: makeStringProp<DateTimeType>('datetime'),
40
+ /**
41
+ * 自定义过滤选项的函数,返回列的选项数组
42
+ */
43
+ filter: Function as PropType<DatetimePickerViewFilter>,
44
+ /**
45
+ * 自定义弹出层选项文案的格式化函数,返回一个字符串
46
+ */
47
+ formatter: Function as PropType<DatetimePickerViewFormatter>,
48
+ /**
49
+ * 自定义列的格式化函数
50
+ */
51
+ columnFormatter: Function as PropType<DatetimePickerViewColumnFormatter>,
52
+ /**
53
+ * 最小日期
54
+ */
55
+ minDate: makeNumberProp(new Date(new Date().getFullYear() - 10, 0, 1).getTime()),
56
+ /**
57
+ * 最大日期
58
+ */
59
+ maxDate: makeNumberProp(new Date(new Date().getFullYear() + 10, 11, 31).getTime()),
60
+ /**
61
+ * 最小小时,time类型时生效
62
+ */
63
+ minHour: makeNumberProp(0),
64
+ /**
65
+ * 最大小时,time类型时生效
66
+ */
67
+ maxHour: makeNumberProp(23),
68
+ /**
69
+ * 最小分钟,time类型时生效
70
+ */
71
+ minMinute: makeNumberProp(0),
72
+ /**
73
+ * 最大分钟,time类型时生效
74
+ */
75
+ maxMinute: makeNumberProp(59),
76
+ /**
77
+ * 是否显示秒选择,仅在 time 和 datetime 类型下生效
78
+ */
79
+ useSecond: makeBooleanProp(false),
80
+ /**
81
+ * 最小秒数,仅在 time 和 datetime 类型下生效
82
+ */
83
+ minSecond: makeNumberProp(0),
84
+ /**
85
+ * 最大秒数,仅在 time 和 datetime 类型下生效
86
+ */
87
+ maxSecond: makeNumberProp(59),
88
+ /**
89
+ * 是否在手指松开时立即触发picker-view的 change 事件。若不开启则会在滚动动画结束后触发 change 事件,1.2.25版本起提供,仅微信小程序和支付宝小程序支持。
90
+ */
91
+ immediateChange: makeBooleanProp(false)
92
+ }
93
+
94
+ export type DatetimePickerViewColumnType = 'year' | 'month' | 'date' | 'hour' | 'minute' | 'second'
95
+
96
+ export type DatetimePickerViewOption = {
97
+ label: string
98
+ value: number
99
+ }
100
+
101
+ export type DatetimePickerViewFilter = (type: DatetimePickerViewColumnType, values: number[]) => number[]
102
+
103
+ export type DatetimePickerViewFormatter = (type: string, value: string) => string
104
+
105
+ export type DatetimePickerViewColumnFormatter = (picker: DatetimePickerViewExpose) => DatetimePickerViewOption[][]
106
+
107
+ export type DatetimePickerViewProps = ExtractPropTypes<typeof datetimePickerViewProps>
108
+
109
+ export type DatetimePickerViewExpose = {
110
+ updateColumns: () => DatetimePickerViewOption[][]
111
+ setColumns: (columnList: DatetimePickerViewOption[][]) => void
112
+ getSelects: () => Record<string, any> | Record<string, any>[] | undefined
113
+ correctValue: (value: string | number) => string | number
114
+ getOriginColumns: () => {
115
+ type: DatetimePickerViewColumnType
116
+ values: number[]
117
+ }[]
118
+ }
119
+
120
+ export type DatetimePickerViewInstance = ComponentPublicInstance<DatetimePickerViewProps, DatetimePickerViewExpose>
@@ -0,0 +1,30 @@
1
+ import { type DateTimeType } from './types'
2
+
3
+ /**
4
+ * @description 根据传入的值和类型,获取当前的选项数组,便于传入 pickerView
5
+ * @param value
6
+ * @param type picker类型
7
+ * @param useSecond 是否使用秒,仅在 time 和 datetime 类型下生效
8
+ */
9
+ export function getPickerValue(value: string | number, type: DateTimeType, useSecond: boolean = false) {
10
+ const values: number[] = []
11
+ const date = new Date(value)
12
+ if (type === 'time') {
13
+ const pair = String(value).split(':')
14
+ values.push(parseInt(pair[0]), parseInt(pair[1]))
15
+ if (useSecond && pair[2]) {
16
+ values.push(parseInt(pair[2]))
17
+ }
18
+ } else {
19
+ values.push(date.getFullYear(), date.getMonth() + 1)
20
+ if (type === 'date') {
21
+ values.push(date.getDate())
22
+ } else if (type === 'datetime') {
23
+ values.push(date.getDate(), date.getHours(), date.getMinutes())
24
+ if (useSecond) {
25
+ values.push(date.getSeconds())
26
+ }
27
+ }
28
+ }
29
+ return values
30
+ }
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <view></view>
3
+ </template>
4
+ <script></script>
5
+ <style lang="scss" scoped></style>