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,801 @@
1
+ <template>
2
+ <view :class="`oxy-datetime-picker ${customClass}`" :style="customStyle">
3
+ <oxy-cell
4
+ v-if="!$slots.default"
5
+ :title="label"
6
+ :required="required"
7
+ :size="size"
8
+ :title-width="labelWidth"
9
+ :prop="prop"
10
+ :rules="rules"
11
+ :clickable="!disabled && !readonly"
12
+ :value-align="alignRight ? 'right' : 'left'"
13
+ :custom-class="cellClass"
14
+ :custom-style="customStyle"
15
+ :custom-title-class="customLabelClass"
16
+ :custom-value-class="customValueClass"
17
+ :ellipsis="ellipsis"
18
+ :use-title-slot="!!$slots.label"
19
+ :marker-side="markerSide"
20
+ @click="showPopup"
21
+ >
22
+ <template v-if="$slots.label" #title>
23
+ <slot name="label"></slot>
24
+ </template>
25
+ <template #default>
26
+ <template v-if="region">
27
+ <view v-if="isArray(showValue)">
28
+ <text :class="showValue[0] ? '' : 'oxy-datetime-picker__placeholder'">
29
+ {{ showValue[0] ? showValue[0] : placeholder || translate('placeholder') }}
30
+ </text>
31
+ {{ translate('to') }}
32
+ <text :class="showValue[1] ? '' : 'oxy-datetime-picker__placeholder'">
33
+ {{ showValue[1] ? showValue[1] : placeholder || translate('placeholder') }}
34
+ </text>
35
+ </view>
36
+ <view v-else class="oxy-datetime-picker__cell-placeholder">
37
+ {{ placeholder || translate('placeholder') }}
38
+ </view>
39
+ </template>
40
+ <view v-else :class="showValue ? '' : 'oxy-datetime-picker__placeholder'">
41
+ {{ showValue ? showValue : placeholder || translate('placeholder') }}
42
+ </view>
43
+ </template>
44
+ <template #right-icon>
45
+ <oxy-icon v-if="showArrow" custom-class="oxy-datetime-picker__arrow" name="arrow-right" />
46
+ <view v-else-if="showClear" @click.stop="handleClear">
47
+ <oxy-icon custom-class="oxy-datetime-picker__clear" name="error-fill" />
48
+ </view>
49
+ </template>
50
+ </oxy-cell>
51
+ <view v-else @click="showPopup">
52
+ <slot></slot>
53
+ </view>
54
+ <!--弹出层,picker-view 在隐藏时修改值,会触发多次change事件,从而导致所有列选中第一项,因此picker在关闭时不隐藏 -->
55
+ <oxy-popup
56
+ v-model="popupShow"
57
+ position="bottom"
58
+ :hide-when-close="false"
59
+ :close-on-click-modal="closeOnClickModal"
60
+ :safe-area-inset-bottom="safeAreaInsetBottom"
61
+ :z-index="zIndex"
62
+ :root-portal="rootPortal"
63
+ @close="onCancel"
64
+ custom-class="oxy-datetime-picker__popup"
65
+ >
66
+ <view class="oxy-datetime-picker__wraper">
67
+ <!--toolBar-->
68
+ <view class="oxy-datetime-picker__toolbar" @touchmove="noop">
69
+ <!--取消按钮-->
70
+ <view class="oxy-datetime-picker__action oxy-datetime-picker__action--cancel" @click="onCancel">
71
+ {{ cancelButtonText || translate('cancel') }}
72
+ </view>
73
+ <!--标题-->
74
+ <view v-if="title" class="oxy-datetime-picker__title">{{ title }}</view>
75
+ <!--确定按钮-->
76
+ <view :class="`oxy-datetime-picker__action ${loading || isLoading ? 'is-loading' : ''}`" @click="onConfirm">
77
+ {{ confirmButtonText || translate('confirm') }}
78
+ </view>
79
+ </view>
80
+ <!-- 区域选择tab展示 -->
81
+ <view v-if="region" class="oxy-datetime-picker__region-tabs">
82
+ <view :class="`oxy-datetime-picker__region ${showStart ? 'is-active' : ''} `" @click="tabChange">
83
+ <view>{{ translate('start') }}</view>
84
+ <view class="oxy-datetime-picker__region-time">{{ showTabLabel[0] }}</view>
85
+ </view>
86
+ <view :class="`oxy-datetime-picker__region ${showStart ? '' : 'is-active'}`" @click="tabChange">
87
+ <view>{{ translate('end') }}</view>
88
+ <view class="oxy-datetime-picker__region-time">{{ showTabLabel[1] }}</view>
89
+ </view>
90
+ </view>
91
+ <!--datetimePickerView-->
92
+ <view :class="showStart ? 'oxy-datetime-picker__show' : 'oxy-datetime-picker__hidden'">
93
+ <oxy-datetime-picker-view
94
+ :custom-class="customViewClass"
95
+ ref="datetimePickerView"
96
+ :type="type"
97
+ v-model="innerValue"
98
+ :loading="loading || isLoading"
99
+ :loading-color="loadingColor"
100
+ :columns-height="columnsHeight"
101
+ :value-key="valueKey"
102
+ :label-key="labelKey"
103
+ :formatter="formatter"
104
+ :filter="filter"
105
+ :column-formatter="isArray(modelValue) ? startColumnFormatter : undefined"
106
+ :max-hour="maxHour"
107
+ :min-hour="minHour"
108
+ :max-date="maxDate"
109
+ :min-date="minDate"
110
+ :max-minute="maxMinute"
111
+ :min-minute="minMinute"
112
+ :use-second="useSecond"
113
+ :min-second="minSecond"
114
+ :max-second="maxSecond"
115
+ :immediate-change="immediateChange"
116
+ @change="onChangeStart"
117
+ @pickstart="onPickStart"
118
+ @pickend="onPickEnd"
119
+ />
120
+ </view>
121
+ <view :class="showStart ? 'oxy-datetime-picker__hidden' : 'oxy-datetime-picker__show'">
122
+ <oxy-datetime-picker-view
123
+ :custom-class="customViewClass"
124
+ ref="datetimePickerView1"
125
+ :type="type"
126
+ v-model="endInnerValue"
127
+ :loading="loading || isLoading"
128
+ :loading-color="loadingColor"
129
+ :columns-height="columnsHeight"
130
+ :value-key="valueKey"
131
+ :label-key="labelKey"
132
+ :formatter="formatter"
133
+ :filter="filter"
134
+ :column-formatter="isArray(modelValue) ? endColumnFormatter : undefined"
135
+ :max-hour="maxHour"
136
+ :min-hour="minHour"
137
+ :max-date="maxDate"
138
+ :min-date="minDate"
139
+ :max-minute="maxMinute"
140
+ :min-minute="minMinute"
141
+ :use-second="useSecond"
142
+ :min-second="minSecond"
143
+ :max-second="maxSecond"
144
+ :immediate-change="immediateChange"
145
+ @change="onChangeEnd"
146
+ @pickstart="onPickStart"
147
+ @pickend="onPickEnd"
148
+ />
149
+ </view>
150
+ </view>
151
+ </oxy-popup>
152
+ </view>
153
+ </template>
154
+
155
+ <script lang="ts">
156
+ export default {
157
+ name: 'oxy-datetime-picker',
158
+ options: {
159
+ virtualHost: true,
160
+ addGlobalClass: true,
161
+ styleIsolation: 'shared'
162
+ }
163
+ }
164
+ </script>
165
+
166
+ <script lang="ts" setup>
167
+ import OxyPopup from '../oxy-popup/oxy-popup.vue'
168
+ import OxyDatetimePickerView from '../oxy-datetime-picker-view/oxy-datetime-picker-view.vue'
169
+ import OxyCell from '../oxy-cell/oxy-cell.vue'
170
+ import OxyIcon from '../oxy-icon/oxy-icon.vue'
171
+ import { computed, getCurrentInstance, nextTick, onBeforeMount, onMounted, ref, watch } from 'vue'
172
+ import { deepClone, isArray, isDef, isEqual, isFunction, padZero } from '../common/util'
173
+ import { type DatetimePickerViewInstance, type DatetimePickerViewColumnType, type DatetimePickerViewExpose } from '../oxy-datetime-picker-view/types'
174
+ import { useTranslate } from '../composables/useTranslate'
175
+ import { datetimePickerProps, type DatetimePickerExpose } from './types'
176
+ import dayjs from '../../dayjs'
177
+ import { getPickerValue } from '../oxy-datetime-picker-view/util'
178
+
179
+ const props = defineProps(datetimePickerProps)
180
+ const emit = defineEmits(['change', 'open', 'toggle', 'cancel', 'confirm', 'clear', 'update:modelValue'])
181
+
182
+ const { translate } = useTranslate('datetime-picker')
183
+
184
+ const datetimePickerView = ref<DatetimePickerViewInstance>()
185
+ const datetimePickerView1 = ref<DatetimePickerViewInstance>()
186
+
187
+ const showValue = ref<string | Date | Array<string | Date>>('')
188
+ const popupShow = ref<boolean>(false)
189
+ const showStart = ref<boolean>(true)
190
+ const region = ref<boolean>(false)
191
+ const showTabLabel = ref<string[]>([])
192
+ const innerValue = ref<string | number>('')
193
+ const endInnerValue = ref<string | number>('')
194
+
195
+ const isPicking = ref<boolean>(false) // 判断pickview是否还在滑动中
196
+ const hasConfirmed = ref<boolean>(false) // 判断用户是否点击了确认按钮
197
+
198
+ const isLoading = ref<boolean>(false) // 加载
199
+ const { proxy } = getCurrentInstance() as any
200
+
201
+ const cellClass = computed(() => {
202
+ const classes = ['oxy-datetime-picker__cell']
203
+ if (props.disabled) classes.push('is-disabled')
204
+ if (props.readonly) classes.push('is-readonly')
205
+ if (props.error) classes.push('is-error')
206
+ return classes.join(' ')
207
+ })
208
+
209
+ watch(
210
+ () => props.modelValue,
211
+ (val, oldVal) => {
212
+ if (isEqual(val, oldVal)) return
213
+
214
+ if (isArray(val)) {
215
+ region.value = true
216
+ innerValue.value = deepClone(getDefaultInnerValue(true))
217
+ endInnerValue.value = deepClone(getDefaultInnerValue(true, true))
218
+ } else {
219
+ // 每次value更新时都需要刷新整个列表
220
+ innerValue.value = deepClone(getDefaultInnerValue())
221
+ }
222
+ nextTick(() => {
223
+ setShowValue(false, false, true)
224
+ })
225
+ },
226
+ {
227
+ deep: true,
228
+ immediate: true
229
+ }
230
+ )
231
+
232
+ watch(
233
+ () => props.displayFormat,
234
+ (fn) => {
235
+ if (fn && !isFunction(fn)) {
236
+ console.error('The type of displayFormat must be Function')
237
+ }
238
+ },
239
+ {
240
+ deep: true,
241
+ immediate: true
242
+ }
243
+ )
244
+ watch(
245
+ () => props.filter,
246
+ (fn) => {
247
+ if (fn && !isFunction(fn)) {
248
+ console.error('The type of filter must be Function')
249
+ }
250
+ },
251
+ {
252
+ deep: true,
253
+ immediate: true
254
+ }
255
+ )
256
+ watch(
257
+ () => props.formatter,
258
+ (fn) => {
259
+ if (fn && !isFunction(fn)) {
260
+ console.error('The type of formatter must be Function')
261
+ }
262
+ },
263
+ {
264
+ deep: true,
265
+ immediate: true
266
+ }
267
+ )
268
+ watch(
269
+ () => props.beforeConfirm,
270
+ (fn) => {
271
+ if (fn && !isFunction(fn)) {
272
+ console.error('The type of beforeConfirm must be Function')
273
+ }
274
+ },
275
+ {
276
+ deep: true,
277
+ immediate: true
278
+ }
279
+ )
280
+ watch(
281
+ () => props.displayFormatTabLabel,
282
+ (fn) => {
283
+ if (fn && !isFunction(fn)) {
284
+ console.error('The type of displayFormatTabLabel must be Function')
285
+ }
286
+ },
287
+ {
288
+ deep: true,
289
+ immediate: true
290
+ }
291
+ )
292
+
293
+ watch(
294
+ () => props.defaultValue,
295
+ (val) => {
296
+ if (isArray(val) || region.value) {
297
+ innerValue.value = deepClone(getDefaultInnerValue(true))
298
+ endInnerValue.value = deepClone(getDefaultInnerValue(true, true))
299
+ } else {
300
+ innerValue.value = deepClone(getDefaultInnerValue())
301
+ }
302
+ },
303
+ {
304
+ deep: true,
305
+ immediate: true
306
+ }
307
+ )
308
+
309
+ // 是否展示清除按钮
310
+ const showClear = computed(() => {
311
+ return (
312
+ props.clearable &&
313
+ !props.disabled &&
314
+ !props.readonly &&
315
+ ((!isArray(showValue.value) && showValue.value) || (isArray(showValue.value) && (showValue.value[0] || showValue.value[1])))
316
+ )
317
+ })
318
+
319
+ // 是否展示箭头
320
+ const showArrow = computed(() => {
321
+ return !props.disabled && !props.readonly && !showClear.value
322
+ })
323
+
324
+ /**
325
+ * @description 处理时间边界值判断
326
+ * @param isStart 是否是开始时间
327
+ * @param columnType 当前列类型
328
+ * @param value 当前值
329
+ * @param currentArray 当前完整选择的数组
330
+ * @param boundary 边界值数组
331
+ * @returns 是否超出边界
332
+ */
333
+ function handleBoundaryValue(
334
+ isStart: boolean,
335
+ columnType: DatetimePickerViewColumnType,
336
+ value: number,
337
+ currentArray: number[],
338
+ boundary: number[]
339
+ ): boolean {
340
+ const { type, useSecond } = props
341
+ switch (type) {
342
+ case 'datetime': {
343
+ const [year, month, date, hour, minute, second] = boundary
344
+ if (columnType === 'year') {
345
+ return isStart ? value > year : value < year
346
+ }
347
+ if (columnType === 'month' && currentArray[0] === year) {
348
+ return isStart ? value > month : value < month
349
+ }
350
+ if (columnType === 'date' && currentArray[0] === year && currentArray[1] === month) {
351
+ return isStart ? value > date : value < date
352
+ }
353
+ if (columnType === 'hour' && currentArray[0] === year && currentArray[1] === month && currentArray[2] === date) {
354
+ return isStart ? value > hour : value < hour
355
+ }
356
+ if (columnType === 'minute' && currentArray[0] === year && currentArray[1] === month && currentArray[2] === date && currentArray[3] === hour) {
357
+ return isStart ? value > minute : value < minute
358
+ }
359
+ if (
360
+ useSecond &&
361
+ columnType === 'second' &&
362
+ currentArray[0] === year &&
363
+ currentArray[1] === month &&
364
+ currentArray[2] === date &&
365
+ currentArray[3] === hour &&
366
+ currentArray[4] === minute
367
+ ) {
368
+ return isStart ? value > second : value < second
369
+ }
370
+ break
371
+ }
372
+ case 'year-month': {
373
+ const [year, month] = boundary
374
+ if (columnType === 'year') {
375
+ return isStart ? value > year : value < year
376
+ }
377
+ if (columnType === 'month' && currentArray[0] === year) {
378
+ return isStart ? value > month : value < month
379
+ }
380
+ break
381
+ }
382
+ case 'year': {
383
+ const [year] = boundary
384
+ if (columnType === 'year') {
385
+ return isStart ? value > year : value < year
386
+ }
387
+ break
388
+ }
389
+ case 'date': {
390
+ const [year, month, date] = boundary
391
+ if (columnType === 'year') {
392
+ return isStart ? value > year : value < year
393
+ }
394
+ if (columnType === 'month' && currentArray[0] === year) {
395
+ return isStart ? value > month : value < month
396
+ }
397
+ if (columnType === 'date' && currentArray[0] === year && currentArray[1] === month) {
398
+ return isStart ? value > date : value < date
399
+ }
400
+ break
401
+ }
402
+ case 'time': {
403
+ const [hour, minute, second] = boundary
404
+ if (columnType === 'hour') {
405
+ return isStart ? value > hour : value < hour
406
+ }
407
+ if (columnType === 'minute' && currentArray[0] === hour) {
408
+ return isStart ? value > minute : value < minute
409
+ }
410
+ if (useSecond && columnType === 'second' && currentArray[0] === hour && currentArray[1] === minute) {
411
+ return isStart ? value > second : value < second
412
+ }
413
+ break
414
+ }
415
+ }
416
+ return false
417
+ }
418
+
419
+ function startColumnFormatter(picker: DatetimePickerViewExpose) {
420
+ return customColumnFormatter(picker, 'start')
421
+ }
422
+
423
+ function endColumnFormatter(picker: DatetimePickerViewExpose) {
424
+ return customColumnFormatter(picker, 'end')
425
+ }
426
+
427
+ /**
428
+ * @description 自定义列项筛选规则
429
+ */
430
+ const customColumnFormatter = (picker: DatetimePickerViewExpose, pickerType: 'start' | 'end') => {
431
+ if (!picker) return []
432
+
433
+ const { type } = props
434
+ const startSymbol = pickerType === 'start'
435
+ const { formatter } = props
436
+ const start = picker.correctValue(innerValue.value)
437
+ const end = picker.correctValue(endInnerValue.value)
438
+ const currentValue = startSymbol ? getPickerValue(start, type, props.useSecond) : getPickerValue(end, type, props.useSecond)
439
+ const boundary = startSymbol ? getPickerValue(end, type, props.useSecond) : getPickerValue(start, type, props.useSecond)
440
+ const columns = picker.getOriginColumns()
441
+ return columns.map((column, _) => {
442
+ return column.values.map((value) => {
443
+ const disabled = handleBoundaryValue(startSymbol, column.type, value, currentValue, boundary)
444
+ return {
445
+ label: formatter ? formatter(column.type, padZero(value)) : padZero(value),
446
+ value,
447
+ disabled
448
+ }
449
+ })
450
+ })
451
+ }
452
+
453
+ onBeforeMount(() => {
454
+ const { modelValue: value } = props
455
+ if (isArray(value)) {
456
+ region.value = true
457
+ innerValue.value = deepClone(getDefaultInnerValue(true))
458
+ endInnerValue.value = deepClone(getDefaultInnerValue(true, true))
459
+ } else {
460
+ innerValue.value = deepClone(getDefaultInnerValue())
461
+ }
462
+ })
463
+
464
+ onMounted(() => {
465
+ setShowValue(false, false, true)
466
+ })
467
+
468
+ /**
469
+ * @description 根据传入的picker,picker组件获取当前cell展示值。
470
+ */
471
+ function getSelects(picker: 'before' | 'after') {
472
+ let value = picker === 'before' ? innerValue.value : endInnerValue.value
473
+ let selected: number[] = []
474
+ if (value) {
475
+ selected = getPickerValue(value, props.type, props.useSecond)
476
+ }
477
+
478
+ let selects = selected.map((value) => {
479
+ return {
480
+ [props.labelKey]: padZero(value),
481
+ [props.valueKey]: value
482
+ }
483
+ })
484
+ return selects
485
+ }
486
+
487
+ function noop() {}
488
+
489
+ function getDefaultInnerValue(isRegion?: boolean, isEnd?: boolean): string | number {
490
+ const { modelValue: value, defaultValue, maxDate, minDate, type } = props
491
+ if (isRegion) {
492
+ const index = isEnd ? 1 : 0
493
+ const targetValue = isArray(value) ? (value[index] as string) : ''
494
+ const targetDefault = isArray(defaultValue) ? (defaultValue[index] as string) : ''
495
+ const maxValue = type === 'time' ? dayjs(maxDate).format('HH:mm') : maxDate
496
+ const minValue = type === 'time' ? dayjs(minDate).format('HH:mm') : minDate
497
+ return targetValue || targetDefault || (isEnd ? maxValue : minValue)
498
+ } else {
499
+ return isDef(value || defaultValue) ? (value as string) || (defaultValue as string) : ''
500
+ }
501
+ }
502
+
503
+ // 对外暴露接口,打开弹框
504
+ function open() {
505
+ showPopup()
506
+ }
507
+
508
+ // 对外暴露接口,关闭弹框
509
+ function close() {
510
+ onCancel()
511
+ }
512
+
513
+ function showPopup() {
514
+ if (props.disabled || props.readonly) return
515
+
516
+ emit('open')
517
+ if (region.value) {
518
+ popupShow.value = true
519
+ showStart.value = true
520
+ innerValue.value = deepClone(getDefaultInnerValue(true, false))
521
+ endInnerValue.value = deepClone(getDefaultInnerValue(true, true))
522
+ } else {
523
+ popupShow.value = true
524
+ innerValue.value = deepClone(getDefaultInnerValue())
525
+ }
526
+ setShowValue(true, false, true)
527
+ }
528
+
529
+ /**
530
+ * @description 区域选择时tab标签切换时触发
531
+ */
532
+ function tabChange() {
533
+ showStart.value = !showStart.value
534
+ // 列项刷新多级联动挂载到datetimepickerView
535
+ const picker = showStart.value ? datetimePickerView.value : datetimePickerView1.value
536
+ picker!.setColumns(picker!.updateColumns())
537
+
538
+ emit('toggle', showStart.value ? innerValue.value : endInnerValue.value)
539
+ }
540
+
541
+ /**
542
+ * @description datetimePickerView change 事件
543
+ */
544
+ function onChangeStart({ value }: { value: number | string }) {
545
+ if (!datetimePickerView.value) return
546
+ if (region.value && !datetimePickerView1.value) return
547
+
548
+ if (region.value) {
549
+ // 区间选择才需要处理边界值
550
+ // 区间选择才需要处理边界值
551
+ const currentArray = getPickerValue(value, props.type, props.useSecond)
552
+ const boundaryArray = getPickerValue(endInnerValue.value, props.type, props.useSecond)
553
+
554
+ const columns = datetimePickerView.value.getOriginColumns()
555
+
556
+ // 检查是否有任何列超出边界
557
+ const needsAdjust = columns.some((column, index) => {
558
+ return handleBoundaryValue(true, column.type, currentArray[index], currentArray, boundaryArray)
559
+ })
560
+
561
+ innerValue.value = deepClone(needsAdjust ? endInnerValue.value : value)
562
+
563
+ nextTick(() => {
564
+ showTabLabel.value = [setTabLabel(), deepClone(showTabLabel.value[1])]
565
+ emit('change', {
566
+ value: [innerValue.value, endInnerValue.value]
567
+ })
568
+ // 更新两个picker的列
569
+ datetimePickerView.value && datetimePickerView.value.setColumns(datetimePickerView.value.updateColumns())
570
+ datetimePickerView1.value && datetimePickerView1.value.setColumns(datetimePickerView1.value.updateColumns())
571
+ })
572
+ } else {
573
+ // 非区间选择直接设置值即可
574
+ innerValue.value = deepClone(value)
575
+ emit('change', {
576
+ value: innerValue.value
577
+ })
578
+ }
579
+ }
580
+
581
+ /**
582
+ * @description 区域选择 下方 datetimePickerView change 事件
583
+ */
584
+ function onChangeEnd({ value }: { value: number | string }) {
585
+ if (!datetimePickerView.value || !datetimePickerView1.value) return
586
+
587
+ const currentArray = getPickerValue(value, props.type)
588
+ const boundaryArray = getPickerValue(innerValue.value, props.type)
589
+ const columns = datetimePickerView1.value.getOriginColumns()
590
+
591
+ // 检查是否有任何列超出边界
592
+ const needsAdjust = columns.some((column, index) => {
593
+ return handleBoundaryValue(false, column.type, currentArray[index], currentArray, boundaryArray)
594
+ })
595
+
596
+ endInnerValue.value = deepClone(needsAdjust ? innerValue.value : value)
597
+
598
+ nextTick(() => {
599
+ showTabLabel.value = [deepClone(showTabLabel.value[0]), setTabLabel(1)]
600
+ emit('change', {
601
+ value: [innerValue.value, endInnerValue.value]
602
+ })
603
+ // 更新两个picker的列
604
+ datetimePickerView.value && datetimePickerView.value.setColumns(datetimePickerView.value.updateColumns())
605
+ datetimePickerView1.value && datetimePickerView1.value.setColumns(datetimePickerView1.value.updateColumns())
606
+ })
607
+ }
608
+
609
+ /**
610
+ * @description 点击取消按钮触发。关闭popup,触发cancel事件。
611
+ */
612
+ function onCancel() {
613
+ popupShow.value = false
614
+ setTimeout(() => {
615
+ if (region.value) {
616
+ innerValue.value = deepClone(getDefaultInnerValue(true))
617
+ endInnerValue.value = deepClone(getDefaultInnerValue(true, true))
618
+ } else {
619
+ innerValue.value = deepClone(getDefaultInnerValue())
620
+ }
621
+ }, 200)
622
+
623
+ emit('cancel')
624
+ }
625
+
626
+ /** picker触发confirm事件,同步触发confirm事件 */
627
+ function onConfirm() {
628
+ if (props.loading || isLoading.value) return
629
+
630
+ // 如果当前还在滑动且未停止下来,则锁住先不确认,等滑完再自动确认,避免pickview值未更新
631
+ if (isPicking.value) {
632
+ hasConfirmed.value = true
633
+ return
634
+ }
635
+
636
+ const { beforeConfirm } = props
637
+ if (beforeConfirm) {
638
+ beforeConfirm(
639
+ region.value ? [innerValue.value, endInnerValue.value] : innerValue.value,
640
+ (isPass: boolean) => {
641
+ isPass && handleConfirm()
642
+ },
643
+ proxy.$.exposed
644
+ )
645
+ } else {
646
+ handleConfirm()
647
+ }
648
+ }
649
+
650
+ function onPickStart() {
651
+ isPicking.value = true
652
+ }
653
+
654
+ function onPickEnd() {
655
+ isPicking.value = false
656
+
657
+ // 延迟一会,因为组件层级嵌套过多,日期的计算时间也较长
658
+ setTimeout(() => {
659
+ if (hasConfirmed.value) {
660
+ hasConfirmed.value = false
661
+ onConfirm()
662
+ }
663
+ }, 50)
664
+ }
665
+
666
+ function handleConfirm() {
667
+ if (props.loading || isLoading.value || props.disabled) {
668
+ popupShow.value = false
669
+ return
670
+ }
671
+ const value = region.value ? [innerValue.value, endInnerValue.value] : innerValue.value
672
+ popupShow.value = false
673
+ emit('update:modelValue', value)
674
+ emit('confirm', {
675
+ value
676
+ })
677
+ setShowValue(false, true)
678
+ }
679
+
680
+ /**
681
+ * @description 设置区域选择 tab 标签展示值
682
+ * @param {Number} index 索引标志位,有三个有效值; 0(默认):上方picker索引; 1:下方picker索引;
683
+ * @return {String} showTabLabel
684
+ */
685
+ function setTabLabel(index: number = 0) {
686
+ if (region.value) {
687
+ let items: Record<string, any>[] = []
688
+ if (index === 0) {
689
+ items = ((datetimePickerView.value ? datetimePickerView.value!.getSelects() : undefined) ||
690
+ (innerValue.value && getSelects('before'))) as Record<string, any>[]
691
+ } else {
692
+ items = ((datetimePickerView1.value ? datetimePickerView1.value!.getSelects() : undefined) ||
693
+ (endInnerValue.value && getSelects('after'))) as Record<string, any>[]
694
+ }
695
+ return defaultDisplayFormat(items, true)
696
+ } else {
697
+ return ''
698
+ }
699
+ }
700
+
701
+ /**
702
+ * @description 设置展示值
703
+ * @param {Boolean} tab 是否修改tab展示值(尽在区域选择情况下生效)
704
+ * @param {Boolean} isConfirm 是否提交当前修改
705
+ */
706
+ function setShowValue(tab: boolean = false, isConfirm: boolean = false, beforeMount: boolean = false) {
707
+ if (region.value) {
708
+ const items = beforeMount
709
+ ? (innerValue.value && getSelects('before')) || []
710
+ : (datetimePickerView.value && datetimePickerView.value.getSelects && datetimePickerView.value.getSelects()) || []
711
+
712
+ const endItems = beforeMount
713
+ ? (endInnerValue.value && getSelects('after')) || []
714
+ : (datetimePickerView1.value && datetimePickerView1.value.getSelects && datetimePickerView1.value.getSelects()) || []
715
+
716
+ showValue.value = tab
717
+ ? showValue.value
718
+ : [
719
+ (props.modelValue as (string | number)[])[0] || isConfirm ? defaultDisplayFormat(items as Record<string, any>[]) : '',
720
+ (props.modelValue as (string | number)[])[1] || isConfirm ? defaultDisplayFormat(endItems as Record<string, any>[]) : ''
721
+ ]
722
+ showTabLabel.value = [defaultDisplayFormat(items as Record<string, any>[], true), defaultDisplayFormat(endItems as Record<string, any>[], true)]
723
+ } else {
724
+ const items = beforeMount
725
+ ? (innerValue.value && getSelects('before')) || []
726
+ : (datetimePickerView.value && datetimePickerView.value.getSelects && datetimePickerView.value.getSelects()) || []
727
+
728
+ showValue.value = deepClone(props.modelValue || isConfirm ? defaultDisplayFormat(items as Record<string, any>[]) : '')
729
+ }
730
+ }
731
+
732
+ /**
733
+ * @description 设置展示值
734
+ * @param {Object} items 获取到的选中项 包含 { value, label }
735
+ * @param {Boolean} tabLabel 当前返回的是否是展示tab上的标签
736
+ * @return {String} showValue / showTabLabel
737
+ */
738
+ function defaultDisplayFormat(items: Record<string, any>[], tabLabel: boolean = false) {
739
+ if (items.length === 0) return ''
740
+
741
+ if (tabLabel && props.displayFormatTabLabel) {
742
+ return props.displayFormatTabLabel(items)
743
+ }
744
+
745
+ if (props.displayFormat) {
746
+ return props.displayFormat(items)
747
+ }
748
+
749
+ // 如果使用了自定义的的formatter,defaultDisplayFormat无效
750
+ if (props.formatter) {
751
+ const typeMaps = {
752
+ year: ['year'],
753
+ datetime: props.useSecond ? ['year', 'month', 'date', 'hour', 'minute', 'second'] : ['year', 'month', 'date', 'hour', 'minute'],
754
+ date: ['year', 'month', 'date'],
755
+ time: props.useSecond ? ['hour', 'minute', 'second'] : ['hour', 'minute'],
756
+ 'year-month': ['year', 'month']
757
+ }
758
+
759
+ return items
760
+ .map((item, index) => {
761
+ return props.formatter!(typeMaps[props.type][index], item.value)
762
+ })
763
+ .join('')
764
+ }
765
+
766
+ switch (props.type) {
767
+ case 'year':
768
+ return items[0].label
769
+ case 'date':
770
+ return `${items[0].label}-${items[1].label}-${items[2].label}`
771
+ case 'year-month':
772
+ return `${items[0].label}-${items[1].label}`
773
+ case 'time':
774
+ return props.useSecond ? `${items[0].label}:${items[1].label}:${items[2].label}` : `${items[0].label}:${items[1].label}`
775
+ case 'datetime':
776
+ return props.useSecond
777
+ ? `${items[0].label}-${items[1].label}-${items[2].label} ${items[3].label}:${items[4].label}:${items[5].label}`
778
+ : `${items[0].label}-${items[1].label}-${items[2].label} ${items[3].label}:${items[4].label}`
779
+ }
780
+ }
781
+
782
+ function setLoading(loading: boolean) {
783
+ isLoading.value = loading
784
+ }
785
+
786
+ function handleClear() {
787
+ emit('clear')
788
+ emit('update:modelValue', '')
789
+ setShowValue(false, true)
790
+ }
791
+
792
+ defineExpose<DatetimePickerExpose>({
793
+ open,
794
+ close,
795
+ setLoading
796
+ })
797
+ </script>
798
+
799
+ <style lang="scss" scoped>
800
+ @import './index.scss';
801
+ </style>