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,374 @@
1
+ <template>
2
+ <view class="oxy-month-panel">
3
+ <view v-if="showPanelTitle" class="oxy-month-panel__title">
4
+ {{ title }}
5
+ </view>
6
+ <view class="oxy-month-panel__weeks">
7
+ <view v-for="item in 7" :key="item" class="oxy-month-panel__week">{{ weekLabel(item + firstDayOfWeek) }}</view>
8
+ </view>
9
+ <scroll-view
10
+ :class="`oxy-month-panel__container ${!!timeType ? 'oxy-month-panel__container--time' : ''}`"
11
+ :style="`height: ${scrollHeight}px`"
12
+ scroll-y
13
+ @scroll="monthScroll"
14
+ :scroll-top="scrollTop"
15
+ >
16
+ <view v-for="(item, index) in months" :key="index" :id="`month${index}`">
17
+ <month
18
+ :type="type"
19
+ :date="item.date"
20
+ :value="value"
21
+ :min-date="minDate"
22
+ :max-date="maxDate"
23
+ :first-day-of-week="firstDayOfWeek"
24
+ :formatter="formatter"
25
+ :max-range="maxRange"
26
+ :range-prompt="rangePrompt"
27
+ :allow-same-day="allowSameDay"
28
+ :default-time="defaultTime"
29
+ :showTitle="index !== 0"
30
+ @change="handleDateChange"
31
+ />
32
+ </view>
33
+ </scroll-view>
34
+ <view v-if="timeType" class="oxy-month-panel__time">
35
+ <view v-if="type === 'datetimerange'" class="oxy-month-panel__time-label">
36
+ <view class="oxy-month-panel__time-text">{{ timeType === 'start' ? translate('startTime') : translate('endTime') }}</view>
37
+ </view>
38
+ <view class="oxy-month-panel__time-picker">
39
+ <oxy-picker-view
40
+ v-if="timeData.length"
41
+ v-model="timeValue"
42
+ :columns="timeData"
43
+ :columns-height="125"
44
+ :immediate-change="immediateChange"
45
+ @change="handleTimeChange"
46
+ @pickstart="handlePickStart"
47
+ @pickend="handlePickEnd"
48
+ />
49
+ </view>
50
+ </view>
51
+ </view>
52
+ </template>
53
+
54
+ <script lang="ts">
55
+ export default {
56
+ options: {
57
+ addGlobalClass: true,
58
+ virtualHost: true,
59
+ styleIsolation: 'shared'
60
+ }
61
+ }
62
+ </script>
63
+
64
+ <script lang="ts" setup>
65
+ import OxyPickerView from '../../oxy-picker-view/oxy-picker-view.vue'
66
+ import { computed, ref, watch, onMounted } from 'vue'
67
+ import { debounce, isArray, isEqual, isNumber, pause } from '../../common/util'
68
+ import { compareMonth, formatMonthTitle, getMonthEndDay, getMonths, getTimeData, getWeekLabel } from '../utils'
69
+ import Month from '../month/month.vue'
70
+ import { monthPanelProps, type MonthInfo, type MonthPanelTimeType, type MonthPanelExpose } from './types'
71
+ import { useTranslate } from '../../composables/useTranslate'
72
+ import type { CalendarItem } from '../types'
73
+
74
+ const props = defineProps(monthPanelProps)
75
+ const emit = defineEmits(['change', 'pickstart', 'pickend'])
76
+
77
+ const { translate } = useTranslate('calendar-view')
78
+
79
+ const scrollTop = ref<number>(0) // 滚动位置
80
+ const scrollIndex = ref<number>(0) // 当前显示的月份索引
81
+ const timeValue = ref<number[]>([]) // 当前选中的时分秒
82
+
83
+ const timeType = ref<MonthPanelTimeType>('') // 当前时间类型,是开始还是结束
84
+ const innerValue = ref<string | number | (number | null)[]>('') // 内部保存一个值,用于判断新老值,避免监听器触发
85
+
86
+ const handleChange = debounce((value) => {
87
+ emit('change', {
88
+ value
89
+ })
90
+ }, 50)
91
+
92
+ // 时间picker的列数据
93
+ const timeData = computed<Array<CalendarItem[]>>(() => {
94
+ let timeColumns: Array<CalendarItem[]> = []
95
+ if (props.type === 'datetime' && isNumber(props.value)) {
96
+ const date = new Date(props.value)
97
+ date.setHours(timeValue.value[0])
98
+ date.setMinutes(timeValue.value[1])
99
+ date.setSeconds(props.hideSecond ? 0 : timeValue.value[2])
100
+ const dateTime = date.getTime()
101
+ timeColumns = getTime(dateTime) || []
102
+ } else if (isArray(props.value) && props.type === 'datetimerange') {
103
+ const [start, end] = props.value!
104
+ const dataValue = timeType.value === 'start' ? start : end
105
+ const date = new Date(dataValue || '')
106
+ date.setHours(timeValue.value[0])
107
+ date.setMinutes(timeValue.value[1])
108
+ date.setSeconds(props.hideSecond ? 0 : timeValue.value[2])
109
+ const dateTime = date.getTime()
110
+ const finalValue = [start, end]
111
+ if (timeType.value === 'start') {
112
+ finalValue[0] = dateTime
113
+ } else {
114
+ finalValue[1] = dateTime
115
+ }
116
+ timeColumns = getTime(finalValue, timeType.value) || []
117
+ }
118
+ return timeColumns
119
+ })
120
+
121
+ // 标题
122
+ const title = computed(() => {
123
+ return formatMonthTitle(months.value[scrollIndex.value].date)
124
+ })
125
+
126
+ // 周标题
127
+ const weekLabel = computed(() => {
128
+ return (index: number) => {
129
+ return getWeekLabel(index - 1)
130
+ }
131
+ })
132
+
133
+ // 滚动区域的高度
134
+ const scrollHeight = computed(() => {
135
+ const scrollHeight: number = timeType.value ? props.panelHeight - 125 : props.panelHeight
136
+ return scrollHeight
137
+ })
138
+
139
+ // 月份日期和月份高度
140
+ const months = computed<MonthInfo[]>(() => {
141
+ return getMonths(props.minDate, props.maxDate).map((month, index) => {
142
+ const offset = (7 + new Date(month).getDay() - props.firstDayOfWeek) % 7
143
+ const totalDay = getMonthEndDay(new Date(month).getFullYear(), new Date(month).getMonth() + 1)
144
+ const rows = Math.ceil((offset + totalDay) / 7)
145
+ return {
146
+ height: rows * 64 + (rows - 1) * 4 + (index === 0 ? 0 : 45), // 每行64px高度,除最后一行外每行加4px margin,加上标题45px
147
+ date: month
148
+ }
149
+ })
150
+ })
151
+
152
+ watch(
153
+ () => props.type,
154
+ (val) => {
155
+ if (
156
+ (val === 'datetime' && props.value) ||
157
+ (val === 'datetimerange' && isArray(props.value) && props.value && props.value.length > 0 && props.value[0])
158
+ ) {
159
+ setTime(props.value, 'start')
160
+ }
161
+ },
162
+ {
163
+ deep: true,
164
+ immediate: true
165
+ }
166
+ )
167
+
168
+ watch(
169
+ () => props.value,
170
+ (val) => {
171
+ if (isEqual(val, innerValue.value)) return
172
+
173
+ if ((props.type === 'datetime' && val) || (props.type === 'datetimerange' && val && isArray(val) && val.length > 0 && val[0])) {
174
+ setTime(val, 'start')
175
+ }
176
+ },
177
+ {
178
+ deep: true,
179
+ immediate: true
180
+ }
181
+ )
182
+
183
+ onMounted(() => {
184
+ scrollIntoView()
185
+ })
186
+
187
+ /**
188
+ * 使当前日期或者选中日期滚动到可视区域
189
+ */
190
+ async function scrollIntoView() {
191
+ // 等待渲染完毕
192
+ await pause()
193
+ let activeDate: number | null = 0
194
+ if (isArray(props.value)) {
195
+ // 对数组按时间排序,取第一个值
196
+ const sortedValue = [...props.value].sort((a, b) => (a || 0) - (b || 0))
197
+ activeDate = sortedValue[0]
198
+ } else if (isNumber(props.value)) {
199
+ activeDate = props.value
200
+ }
201
+
202
+ if (!activeDate) {
203
+ activeDate = Date.now()
204
+ }
205
+
206
+ let top: number = 0
207
+ let activeMonthIndex = -1
208
+ for (let index = 0; index < months.value.length; index++) {
209
+ if (compareMonth(months.value[index].date, activeDate) === 0) {
210
+ activeMonthIndex = index
211
+ // 找到选中月份后,计算选中日期在月份中的位置
212
+ const date = new Date(activeDate)
213
+ const day = date.getDate()
214
+ const firstDay = new Date(date.getFullYear(), date.getMonth(), 1)
215
+ const offset = (7 + firstDay.getDay() - props.firstDayOfWeek) % 7
216
+ const row = Math.floor((offset + day - 1) / 7)
217
+ // 每行高度64px,每行加4px margin
218
+ top += row * 64 + row * 4
219
+ break
220
+ }
221
+ top += months.value[index] ? Number(months.value[index].height) : 0
222
+ }
223
+ scrollTop.value = 0
224
+ if (top > 0) {
225
+ await pause()
226
+ // 如果不是第一个月才加45
227
+ scrollTop.value = top + (activeMonthIndex > 0 ? 45 : 0)
228
+ }
229
+ }
230
+ /**
231
+ * 获取时间 picker 的数据
232
+ * @param {timestamp|array} value 当前时间
233
+ * @param {string} type 类型,是开始还是结束
234
+ */
235
+ function getTime(value: number | (number | null)[], type?: string) {
236
+ if (props.type === 'datetime') {
237
+ return getTimeData({
238
+ date: value as number,
239
+ minDate: props.minDate,
240
+ maxDate: props.maxDate,
241
+ filter: props.timeFilter,
242
+ isHideSecond: props.hideSecond
243
+ })
244
+ } else {
245
+ if (type === 'start' && isArray(props.value)) {
246
+ return getTimeData({
247
+ date: (value as Array<number>)[0],
248
+ minDate: props.minDate,
249
+ maxDate: props.value[1] ? props.value[1] : props.maxDate,
250
+ filter: props.timeFilter,
251
+ isHideSecond: props.hideSecond
252
+ })
253
+ } else {
254
+ return getTimeData({
255
+ date: (value as Array<number>)[1],
256
+ minDate: (value as Array<number>)[0],
257
+ maxDate: props.maxDate,
258
+ filter: props.timeFilter,
259
+ isHideSecond: props.hideSecond
260
+ })
261
+ }
262
+ }
263
+ }
264
+ /**
265
+ * 获取 date 的时分秒
266
+ * @param {timestamp} date 时间
267
+ * @param {string} type 类型,是开始还是结束
268
+ */
269
+ function getTimeValue(date: number | (number | null)[], type: MonthPanelTimeType) {
270
+ let dateValue: Date = new Date()
271
+ if (props.type === 'datetime') {
272
+ dateValue = new Date(date as number)
273
+ } else if (isArray(date)) {
274
+ if (type === 'start') {
275
+ dateValue = new Date(date[0] || '')
276
+ } else {
277
+ dateValue = new Date(date[1] || '')
278
+ }
279
+ }
280
+
281
+ const hour = dateValue.getHours()
282
+ const minute = dateValue.getMinutes()
283
+ const second = dateValue.getSeconds()
284
+ return props.hideSecond ? [hour, minute] : [hour, minute, second]
285
+ }
286
+
287
+ function setTime(value: number | (number | null)[], type?: MonthPanelTimeType) {
288
+ if (isArray(value) && value[0] && value[1] && type === 'start' && timeType.value === 'start') {
289
+ type = 'end'
290
+ }
291
+ timeType.value = type || ''
292
+ timeValue.value = getTimeValue(value, type || '')
293
+ }
294
+ function handleDateChange({ value, type }: { value: number | (number | null)[]; type?: MonthPanelTimeType }) {
295
+ if (!isEqual(value, props.value)) {
296
+ // 内部保存一个值,用于判断新老值,避免监听器触发
297
+ innerValue.value = value
298
+ handleChange(value)
299
+ }
300
+ // datetime 和 datetimerange 类型,需要计算 timeData 并做展示
301
+ if (props.type.indexOf('time') > -1) {
302
+ setTime(value, type)
303
+ }
304
+ }
305
+ function handleTimeChange({ value }: { value: any[] }) {
306
+ if (!props.value) {
307
+ return
308
+ }
309
+ if (props.type === 'datetime' && isNumber(props.value)) {
310
+ const date = new Date(props.value)
311
+ date.setHours(value[0])
312
+ date.setMinutes(value[1])
313
+ date.setSeconds(props.hideSecond ? 0 : value[2])
314
+ const dateTime = date.getTime()
315
+ handleChange(dateTime)
316
+ } else if (isArray(props.value) && props.type === 'datetimerange') {
317
+ const [start, end] = props.value!
318
+ const dataValue = timeType.value === 'start' ? start : end
319
+ const date = new Date(dataValue || '')
320
+ date.setHours(value[0])
321
+ date.setMinutes(value[1])
322
+ date.setSeconds(props.hideSecond ? 0 : value[2])
323
+ const dateTime = date.getTime()
324
+
325
+ if (dateTime === dataValue) return
326
+
327
+ const finalValue = [start, end]
328
+ if (timeType.value === 'start') {
329
+ finalValue[0] = dateTime
330
+ } else {
331
+ finalValue[1] = dateTime
332
+ }
333
+ innerValue.value = finalValue // 内部保存一个值,用于判断新老值,避免监听器触发
334
+ handleChange(finalValue)
335
+ }
336
+ }
337
+ function handlePickStart() {
338
+ emit('pickstart')
339
+ }
340
+ function handlePickEnd() {
341
+ emit('pickend')
342
+ }
343
+
344
+ const monthScroll = (event: { detail: { scrollTop: number } }) => {
345
+ if (months.value.length <= 1) {
346
+ return
347
+ }
348
+ const scrollTop = Math.max(0, event.detail.scrollTop)
349
+ doSetSubtitle(scrollTop)
350
+ }
351
+
352
+ /**
353
+ * 设置小标题
354
+ * scrollTop 滚动条位置
355
+ */
356
+ function doSetSubtitle(scrollTop: number) {
357
+ let height: number = 0 // 月份高度和
358
+ for (let index = 0; index < months.value.length; index++) {
359
+ height = height + months.value[index].height
360
+ if (scrollTop < height) {
361
+ scrollIndex.value = index
362
+ return
363
+ }
364
+ }
365
+ }
366
+
367
+ defineExpose<MonthPanelExpose>({
368
+ scrollIntoView
369
+ })
370
+ </script>
371
+
372
+ <style lang="scss" scoped>
373
+ @import './index.scss';
374
+ </style>
@@ -0,0 +1,48 @@
1
+ import type { ComponentPublicInstance, ExtractPropTypes, PropType } from 'vue'
2
+ import { makeBooleanProp, makeRequiredProp } from '../../common/props'
3
+ import type { CalendarFormatter, CalendarTimeFilter, CalendarType } from '../types'
4
+
5
+ /**
6
+ * 月份信息
7
+ */
8
+ export interface MonthInfo {
9
+ date: number
10
+ height: number
11
+ }
12
+
13
+ export const monthPanelProps = {
14
+ type: makeRequiredProp(String as PropType<CalendarType>),
15
+ value: makeRequiredProp([Number, Array, null] as PropType<number | (number | null)[] | null>),
16
+ minDate: makeRequiredProp(Number),
17
+ maxDate: makeRequiredProp(Number),
18
+ firstDayOfWeek: makeRequiredProp(Number),
19
+ formatter: Function as PropType<CalendarFormatter>,
20
+ maxRange: Number,
21
+ rangePrompt: String,
22
+ allowSameDay: makeBooleanProp(false),
23
+ showPanelTitle: makeBooleanProp(false),
24
+ defaultTime: {
25
+ type: [Array] as PropType<Array<number[]>>
26
+ },
27
+ panelHeight: makeRequiredProp(Number),
28
+ // type 为 'datetime' 或 'datetimerange' 时有效,用于过滤时间选择器的数据
29
+ timeFilter: Function as PropType<CalendarTimeFilter>,
30
+ hideSecond: makeBooleanProp(false),
31
+ /**
32
+ * 是否在手指松开时立即触发picker-view的 change 事件。若不开启则会在滚动动画结束后触发 change 事件,1.2.25版本起提供,仅微信小程序和支付宝小程序支持。
33
+ */
34
+ immediateChange: makeBooleanProp(false)
35
+ }
36
+
37
+ export type MonthPanelProps = ExtractPropTypes<typeof monthPanelProps>
38
+
39
+ export type MonthPanelTimeType = 'start' | 'end' | ''
40
+
41
+ export type MonthPanelExpose = {
42
+ /**
43
+ * 使当前日期或者选中日期滚动到可视区域
44
+ */
45
+ scrollIntoView: () => void
46
+ }
47
+
48
+ export type MonthPanelInstance = ComponentPublicInstance<MonthPanelProps, MonthPanelExpose>
@@ -0,0 +1,111 @@
1
+ <template>
2
+ <view :class="`oxy-calendar-view ${customClass}`">
3
+ <year-panel
4
+ v-if="type === 'month' || type === 'monthrange'"
5
+ ref="yearPanelRef"
6
+ :type="type"
7
+ :value="modelValue"
8
+ :min-date="minDate"
9
+ :max-date="maxDate"
10
+ :formatter="formatter"
11
+ :max-range="maxRange"
12
+ :range-prompt="rangePrompt"
13
+ :allow-same-day="allowSameDay"
14
+ :show-panel-title="showPanelTitle"
15
+ :default-time="formatDefauleTime"
16
+ :panel-height="panelHeight"
17
+ @change="handleChange"
18
+ />
19
+ <month-panel
20
+ v-else
21
+ ref="monthPanelRef"
22
+ :type="type"
23
+ :value="modelValue"
24
+ :min-date="minDate"
25
+ :max-date="maxDate"
26
+ :first-day-of-week="firstDayOfWeek"
27
+ :formatter="formatter"
28
+ :max-range="maxRange"
29
+ :range-prompt="rangePrompt"
30
+ :allow-same-day="allowSameDay"
31
+ :show-panel-title="showPanelTitle"
32
+ :default-time="formatDefauleTime"
33
+ :panel-height="panelHeight"
34
+ :immediate-change="immediateChange"
35
+ :time-filter="timeFilter"
36
+ :hide-second="hideSecond"
37
+ @change="handleChange"
38
+ @pickstart="handlePickStart"
39
+ @pickend="handlePickEnd"
40
+ />
41
+ </view>
42
+ </template>
43
+ <script lang="ts">
44
+ export default {
45
+ name: 'oxy-calendar-view',
46
+ options: {
47
+ addGlobalClass: true,
48
+ virtualHost: true,
49
+ styleIsolation: 'shared'
50
+ }
51
+ }
52
+ </script>
53
+
54
+ <script lang="ts" setup>
55
+ import { ref, watch } from 'vue'
56
+ import { getDefaultTime } from './utils'
57
+ import yearPanel from './yearPanel/year-panel.vue'
58
+ import MonthPanel from './monthPanel/month-panel.vue'
59
+ import { calendarViewProps, type CalendarViewExpose } from './types'
60
+
61
+ const props = defineProps(calendarViewProps)
62
+ const emit = defineEmits(['change', 'update:modelValue', 'pickstart', 'pickend'])
63
+ const formatDefauleTime = ref<number[][]>([])
64
+
65
+ const yearPanelRef = ref()
66
+ const monthPanelRef = ref()
67
+
68
+ watch(
69
+ () => props.defaultTime,
70
+ (newValue) => {
71
+ formatDefauleTime.value = getDefaultTime(newValue)
72
+ },
73
+ {
74
+ deep: true,
75
+ immediate: true
76
+ }
77
+ )
78
+
79
+ /**
80
+ * 使当前日期或者选中日期滚动到可视区域
81
+ */
82
+ function scrollIntoView() {
83
+ const panel = getPanel()
84
+ panel.scrollIntoView && panel.scrollIntoView()
85
+ }
86
+
87
+ function getPanel() {
88
+ return props.type.indexOf('month') > -1 ? yearPanelRef.value : monthPanelRef.value
89
+ }
90
+
91
+ function handleChange({ value }: { value: number | number[] | null }) {
92
+ emit('update:modelValue', value)
93
+ emit('change', {
94
+ value
95
+ })
96
+ }
97
+ function handlePickStart() {
98
+ emit('pickstart')
99
+ }
100
+ function handlePickEnd() {
101
+ emit('pickend')
102
+ }
103
+
104
+ defineExpose<CalendarViewExpose>({
105
+ scrollIntoView
106
+ })
107
+ </script>
108
+
109
+ <style lang="scss" scoped>
110
+ @import './index.scss';
111
+ </style>
@@ -0,0 +1,109 @@
1
+ import type { ComponentPublicInstance, ExtractPropTypes, PropType } from 'vue'
2
+ import { baseProps, makeBooleanProp, makeNumberProp, makeRequiredProp, makeStringProp } from '../common/props'
3
+
4
+ export type CalendarType = 'date' | 'dates' | 'datetime' | 'week' | 'month' | 'daterange' | 'datetimerange' | 'weekrange' | 'monthrange'
5
+
6
+ export const calendarViewProps = {
7
+ ...baseProps,
8
+ /**
9
+ * 选中值,为 13 位时间戳或时间戳数组
10
+ */
11
+ modelValue: makeRequiredProp([Number, Array, null] as PropType<number | number[] | null>),
12
+ /**
13
+ * 日期类型
14
+ */
15
+ type: makeStringProp<CalendarType>('date'),
16
+ /**
17
+ * 最小日期,为 13 位时间戳
18
+ */
19
+ minDate: makeNumberProp(new Date(new Date().getFullYear(), new Date().getMonth() - 6, new Date().getDate()).getTime()),
20
+ /**
21
+ * 最大日期,为 13 位时间戳
22
+ */
23
+ maxDate: makeNumberProp(new Date(new Date().getFullYear(), new Date().getMonth() + 6, new Date().getDate(), 23, 59, 59).getTime()),
24
+ /**
25
+ * 周起始天
26
+ */
27
+ firstDayOfWeek: makeNumberProp(0),
28
+ /**
29
+ * 日期格式化函数
30
+ */
31
+ formatter: Function as PropType<CalendarFormatter>,
32
+ /**
33
+ * type 为范围选择时有效,最大日期范围
34
+ */
35
+ maxRange: Number,
36
+ /**
37
+ * type 为范围选择时有效,选择超出最大日期范围时的错误提示文案
38
+ */
39
+ rangePrompt: String,
40
+ /**
41
+ * type 为范围选择时有效,是否允许选择同一天
42
+ */
43
+ allowSameDay: makeBooleanProp(false),
44
+ // 是否展示面板标题,自动计算当前滚动的日期月份
45
+ showPanelTitle: makeBooleanProp(true),
46
+ /**
47
+ * 选中日期所使用的当日内具体时刻
48
+ */
49
+ defaultTime: {
50
+ type: [String, Array] as PropType<string | string[]>,
51
+ default: '00:00:00'
52
+ },
53
+ /**
54
+ * 可滚动面板的高度
55
+ */
56
+ panelHeight: makeNumberProp(378),
57
+ /**
58
+ * type 为 'datetime' 或 'datetimerange' 时有效,用于过滤时间选择器的数据
59
+ */
60
+ timeFilter: Function as PropType<CalendarTimeFilter>,
61
+ /**
62
+ * type 为 'datetime' 或 'datetimerange' 时有效,是否不展示秒修改
63
+ */
64
+ hideSecond: makeBooleanProp(false),
65
+ /**
66
+ * 是否在手指松开时立即触发picker-view的 change 事件。若不开启则会在滚动动画结束后触发 change 事件,1.2.25版本起提供,仅微信小程序和支付宝小程序支持。
67
+ */
68
+ immediateChange: makeBooleanProp(false)
69
+ }
70
+
71
+ export type CalendarViewProps = ExtractPropTypes<typeof calendarViewProps>
72
+
73
+ export type CalendarDayType = '' | 'start' | 'middle' | 'end' | 'selected' | 'same' | 'current' | 'multiple-middle' | 'multiple-selected'
74
+
75
+ export type CalendarDayItem = {
76
+ date: number
77
+ text?: number | string
78
+ topInfo?: string
79
+ bottomInfo?: string
80
+ type?: CalendarDayType
81
+ disabled?: boolean
82
+ isLastRow?: boolean
83
+ }
84
+
85
+ export type CalendarFormatter = (day: CalendarDayItem) => CalendarDayItem
86
+
87
+ export type CalendarTimeFilterOptionType = 'hour' | 'minute' | 'second'
88
+
89
+ export type CalendarTimeFilterOption = {
90
+ type: CalendarTimeFilterOptionType
91
+ values: CalendarItem[]
92
+ }
93
+
94
+ export type CalendarTimeFilter = (option: CalendarTimeFilterOption) => CalendarItem[]
95
+
96
+ export type CalendarItem = {
97
+ label: string
98
+ value: number
99
+ disabled: boolean
100
+ }
101
+
102
+ export type CalendarViewExpose = {
103
+ /**
104
+ * 使当前日期或者选中日期滚动到可视区域
105
+ */
106
+ scrollIntoView: () => void
107
+ }
108
+
109
+ export type CalendarViewInstance = ComponentPublicInstance<CalendarViewExpose, CalendarViewProps>