From d8b41fff43a2cee6a8f714ffa807623b15803786 Mon Sep 17 00:00:00 2001 From: quanyawei <401863037@qq.com> Date: Fri, 20 Oct 2023 15:21:35 +0800 Subject: [PATCH] fix:立行立改Uniapp小程序新建项目 --- uni_modules/uview-ui/components/u-swipe-action-item/u-swipe-action-item.vue | 190 uni_modules/uview-ui/components/u-dropdown-item/props.js | 36 .hbuilderx/launch.json | 16 uni_modules/uview-ui/components/u-safe-bottom/props.js | 5 uni_modules/uview-ui/libs/mixin/touch.js | 59 utils/storage.js | 30 uni_modules/uview-ui/libs/config/props/checkboxGroup.js | 29 uni_modules/uview-ui/components/u-rate/u-rate.vue | 306 uni_modules/uview-ui/libs/config/props/upload.js | 36 main.js | 25 uni_modules/uview-ui/libs/config/props/codeInput.js | 29 uni_modules/uview-ui/libs/config/props/formItem.js | 23 uni_modules/uview-ui/components/u-empty/props.js | 59 static/logo.png | 0 uni_modules/uview-ui/libs/mixin/button.js | 13 uni_modules/uview-ui/components/u-transition/vue.ani-style.scss | 113 uni_modules/uview-ui/libs/config/props/tabbarItem.js | 20 uni.scss | 77 uni_modules/uview-ui/components/u-button/u-button.vue | 490 uni_modules/uview-ui/components/u-steps-item/props.js | 24 uni_modules/uview-ui/components/u-picker-column/u-picker-column.vue | 27 uni_modules/uview-ui/libs/config/props/numberKeyboard.js | 17 uni_modules/uview-ui/components/u-notify/props.js | 49 uni_modules/uview-ui/libs/config/props/listItem.js | 15 uni_modules/uview-ui/libs/css/nvue.scss | 0 package-lock.json | 11 uni_modules/cl-upload/components/cl-upload/cl-upload.vue | 1031 + uni_modules/uview-ui/libs/config/props/subsection.js | 23 uni_modules/uview-ui/components/u-cell/u-cell.vue | 229 uni_modules/uview-ui/LICENSE | 21 uni_modules/uview-ui/README.md | 66 uni_modules/uview-ui/components/uview-ui/uview-ui.vue | 15 uni_modules/uview-ui/components/u-tooltip/props.js | 59 uni_modules/uview-ui/libs/config/props/carKeyboard.js | 15 uni_modules/uview-ui/libs/css/common.scss | 97 uni_modules/uview-ui/components/u-loadmore/u-loadmore.vue | 150 uni_modules/uview-ui/components/u-alert/u-alert.vue | 243 uni_modules/uview-ui/components/u-count-down/utils.js | 62 .env.js | 18 uni_modules/uview-ui/components/u-row-notice/u-row-notice.vue | 330 uni_modules/uview-ui/components/u-dropdown-item/u-dropdown-item.vue | 127 uni_modules/uview-ui/components/u-picker-column/props.js | 5 uni_modules/uview-ui/components/u-swiper/props.js | 125 uni_modules/uview-ui/components/u-search/props.js | 118 uni_modules/uview-ui/components/u-row/props.js | 19 static/img/headSculpture.png | 0 uni_modules/uview-ui/components/u-loading-page/u-loading-page.vue | 115 utils/utils.js | 179 uni_modules/uview-ui/libs/config/color.js | 17 uni_modules/uview-ui/components/u-keyboard/props.js | 84 uni_modules/uview-ui/components/u-index-list/props.js | 29 uni_modules/uview-ui/components/u-code-input/props.js | 79 store/modules/index.js | 10 pages/actionChange/components/rectificationInfor.vue | 263 uni_modules/uview-ui/components/u--textarea/u--textarea.vue | 48 uni_modules/uview-ui/libs/config/props/stepsItem.js | 18 uni_modules/uview-ui/components/u-album/u-album.vue | 259 uni_modules/uview-ui/components/u-upload/utils.js | 151 uni_modules/uview-ui/components/u-grid/u-grid.vue | 97 uni_modules/uview-ui/components/u-notice-bar/u-notice-bar.vue | 101 uni_modules/uview-ui/libs/luch-request/adapters/index.js | 97 uni_modules/uview-ui/components/u-avatar-group/u-avatar-group.vue | 103 uni_modules/uview-ui/components/u-datetime-picker/props.js | 116 uni_modules/uview-ui/components/u--form/u--form.vue | 78 uni_modules/uview-ui/components/u-index-anchor/u-index-anchor.vue | 91 uni_modules/uview-ui/components/u-toolbar/u-toolbar.vue | 102 uni_modules/uview-ui/libs/config/props/empty.js | 26 uni_modules/uview-ui/libs/config/props/noticeBar.js | 27 static/img/xinjian.png | 0 uni_modules/uview-ui/libs/config/props/swiper.js | 39 uni_modules/uview-ui/libs/config/props/indexAnchor.js | 19 uni_modules/uview-ui/libs/config/props/countDown.js | 18 static/img/shouyeClick.png | 0 uni_modules/uview-ui/components/u-swipe-action/u-swipe-action.vue | 67 uni_modules/uview-ui/libs/config/props/divider.js | 23 uni_modules/uview-ui/components/u-read-more/props.js | 61 static/img/wode-.png | 0 uni_modules/uview-ui/components/u-tabbar/u-tabbar.vue | 141 uni_modules/uview-ui/components/u-tabs-item/u-tabs-item.vue | 29 uni_modules/uview-ui/components/u-slider/nvue.js | 193 uni_modules/uview-ui/libs/config/props/col.js | 19 pages/actionChange/components/basicInfor.vue | 234 uni_modules/uview-ui/components/u-swipe-action/props.js | 9 uni_modules/uview-ui/components/u-text/u-text.vue | 223 uni_modules/uview-ui/libs/config/props/code.js | 21 uni_modules/uview-ui/components/u-skeleton/u-skeleton.vue | 244 uni_modules/uview-ui/components/u-image/props.js | 84 uni_modules/uview-ui/libs/config/props/alert.js | 22 uni_modules/uview-ui/components/u-radio/props.js | 64 static/img/xinjianClick.png | 0 uni_modules/uview-ui/components/u-table/u-table.vue | 29 uni_modules/uview-ui/components/u-tag/props.js | 84 uni_modules/uview-ui/libs/config/props/noNetwork.js | 18 uni_modules/uview-ui/libs/config/props/tag.js | 29 pages/actionChange/agencyPage/index.vue | 291 uni_modules/uview-ui/components/u-swiper/u-swiper.vue | 255 uni_modules/uview-ui/components/u-index-item/u-index-item.vue | 87 uni_modules/uview-ui/libs/config/props/radioGroup.js | 30 uni_modules/uview-ui/components/u-number-box/props.js | 109 uni_modules/uview-ui/components/u-form/u-form.vue | 214 uni_modules/uview-ui/components/u-grid-item/u-grid-item.vue | 209 uni_modules/uview-ui/components/u-col/u-col.vue | 162 uni_modules/uview-ui/libs/config/props/navbar.js | 32 uni_modules/uview-ui/components/u-car-keyboard/props.js | 14 uni_modules/uview-ui/libs/config/props/readMore.js | 22 uni_modules/uview-ui/components/u-collapse-item/u-collapse-item.vue | 225 uni_modules/uview-ui/components/u-checkbox/props.js | 69 uni_modules/uview-ui/components/u-tooltip/u-tooltip.vue | 365 uni_modules/uview-ui/libs/config/props/actionSheet.js | 25 uni_modules/uview-ui/components/u-index-item/props.js | 5 uni_modules/uview-ui/components/u-sticky/props.js | 40 uni_modules/uview-ui/components/u-button/nvue.scss | 46 uni_modules/uview-ui/package.json | 84 uni_modules/uview-ui/components/u-button/props.js | 161 uni_modules/uview-ui/libs/config/props/image.js | 30 uni_modules/uview-ui/libs/config/props/form.js | 22 uni_modules/uview-ui/components/u-collapse/props.js | 19 uni_modules/uview-ui/libs/config/props/badge.js | 27 uni_modules/uview-ui/components/u-loading-page/props.js | 49 uni_modules/uview-ui/components/u-action-sheet/props.js | 54 uni_modules/uview-ui/libs/function/throttle.js | 30 uni_modules/uview-ui/components/u-datetime-picker/u-datetime-picker.vue | 360 uni_modules/uview-ui/components/u-slider/props.js | 54 uni_modules/uview-ui/components/u-back-top/props.js | 54 uni_modules/uview-ui/components/u-radio/u-radio.vue | 339 uni_modules/uview-ui/components/u-modal/u-modal.vue | 227 uni_modules/uview-ui/libs/config/props/circleProgress.js | 15 uni_modules/uview-ui/components/u-icon/icons.js | 214 .env.prod.js | 4 uni_modules/uview-ui/components/u-subsection/u-subsection.vue | 299 uni_modules/uview-ui/components/u-line/props.js | 33 uni_modules/uview-ui/libs/config/props/transition.js | 18 uni_modules/uview-ui/components/u-toolbar/props.js | 34 uni_modules/uview-ui/libs/config/props/swipterIndicator.js | 19 uni_modules/uview-ui/index.js | 79 uni_modules/uview-ui/components/u-list-item/u-list-item.vue | 116 uni_modules/uview-ui/components/u-swiper-indicator/props.js | 29 uni_modules/uview-ui/libs/config/props/search.js | 37 uni_modules/uview-ui/libs/luch-request/core/defaults.js | 29 uni_modules/uview-ui/libs/config/props/toolbar.js | 21 uni_modules/uview-ui/components/u-dropdown/u-dropdown.vue | 127 uni_modules/uview-ui/libs/function/debounce.js | 29 uni_modules/uview-ui/libs/css/color.scss | 155 uni_modules/uview-ui/libs/config/props/modal.js | 30 uni_modules/uview-ui/components/u-text/props.js | 110 uni_modules/uview-ui/components/u-number-keyboard/props.js | 19 uni_modules/uview-ui/components/u-column-notice/u-column-notice.vue | 160 uni_modules/uview-ui/components/u-album/props.js | 59 uni_modules/uview-ui/libs/css/h5.scss | 0 uni_modules/uview-ui/components/u-steps/u-steps.vue | 80 uni_modules/uview-ui/components/u-dropdown/props.js | 65 uni_modules/uview-ui/components/u-avatar/props.js | 78 uni_modules/uview-ui/libs/config/props/popup.js | 29 uni_modules/uview-ui/index.scss | 23 pages/actionChange/components/approvalnfor.vue | 230 uni_modules/uview-ui/libs/config/props/link.js | 26 uni_modules/uview-ui/components/u-icon/u-icon.vue | 234 uni_modules/uview-ui/libs/config/props/checkbox.js | 27 uni_modules/uview-ui/components/u-avatar/u-avatar.vue | 172 uni_modules/uview-ui/libs/config/props/input.js | 48 uni_modules/uview-ui/libs/util/async-validator.js | 1343 + uni_modules/uview-ui/components/u-car-keyboard/u-car-keyboard.vue | 311 uni_modules/uview-ui/libs/config/props/slider.js | 25 uni_modules/uview-ui/components/u-text/value.js | 85 uni_modules/uview-ui/components/u-subsection/props.js | 49 uni_modules/uview-ui/libs/config/props/row.js | 17 uni_modules/uview-ui/components/u-calendar/header.vue | 99 uni_modules/uview-ui/components/u-code/props.js | 34 uni_modules/uview-ui/components/u-navbar/u-navbar.vue | 186 uni_modules/uview-ui/components/u-popup/u-popup.vue | 304 uni_modules/uview-ui/components/u-tr/props.js | 5 uni_modules/uview-ui/components/u-steps/props.js | 39 uni_modules/uview-ui/components/u-td/u-td.vue | 31 uni_modules/uview-ui/libs/config/props.js | 190 static/img/shouye.png | 0 uni_modules/uview-ui/components/u-cell/props.js | 110 uni_modules/uview-ui/libs/config/config.js | 34 uni_modules/uview-ui/libs/function/test.js | 288 uni_modules/uview-ui/components/u-steps-item/u-steps-item.vue | 316 uni_modules/uview-ui/components/u-transition/nvue.ani-map.js | 68 uni_modules/uview-ui/libs/luch-request/utils/clone.js | 264 README.md | 4 uni_modules/uview-ui/components/u-calendar/props.js | 144 uni_modules/uview-ui/libs/config/props/statusBar.js | 15 uni_modules/uview-ui/components/u-modal/props.js | 84 uni_modules/uview-ui/components/u-badge/props.js | 72 uni_modules/uview-ui/components/u-collapse-item/props.js | 59 uni_modules/uview-ui/components/u-search/u-search.vue | 303 uni_modules/uview-ui/components/u-parse/node/node.vue | 499 uni_modules/uview-ui/components/u-form-item/props.js | 48 uni_modules/uview-ui/libs/config/props/picker.js | 29 uni_modules/uview-ui/libs/config/props/radio.js | 27 utils/login.js | 42 uni_modules/uview-ui/components/u-no-network/u-no-network.vue | 220 uni_modules/uview-ui/libs/config/props/textarea.js | 36 uni_modules/uview-ui/components/u--text/u--text.vue | 44 uni_modules/uview-ui/libs/config/props/grid.js | 17 uni_modules/uview-ui/libs/config/props/loadmore.js | 32 uni_modules/uview-ui/libs/config/props/datetimePicker.js | 36 uni_modules/uview-ui/components/u-circle-progress/u-circle-progress.vue | 198 uni_modules/uview-ui/libs/luch-request/core/dispatchRequest.js | 3 uni_modules/uview-ui/components/u-button/vue.scss | 80 uni_modules/uview-ui/libs/mixin/mpShare.js | 13 uni_modules/uview-ui/components/u-number-keyboard/u-number-keyboard.vue | 196 uni_modules/uview-ui/libs/config/props/steps.js | 21 uni_modules/uview-ui/libs/config/props/sticky.js | 20 uni_modules/uview-ui/components/u-index-list/u-index-list.vue | 440 uni_modules/uview-ui/components/u-overlay/props.js | 24 uni_modules/uview-ui/components/u-parse/u-parse.vue | 366 pages/actionChange/newPage/index.vue | 410 uni_modules/uview-ui/components/u-no-network/props.js | 19 uni_modules/uview-ui/components/u-transition/u-transition.vue | 92 uni_modules/cl-upload/readme.md | 253 pages/login/register/register.vue | 74 uni_modules/uview-ui/libs/config/props/numberBox.js | 35 uni_modules/uview-ui/components/u-swipe-action-item/wxs.js | 15 uni_modules/uview-ui/components/u-line/u-line.vue | 62 uni_modules/uview-ui/libs/luch-request/core/InterceptorManager.js | 50 uni_modules/uview-ui/components/u-grid/props.js | 19 store/modules/user.js | 111 uni_modules/uview-ui/libs/util/emitter.js | 51 pages/actionChange/workOrderDetails/index.vue | 106 uni_modules/uview-ui/components/u-badge/u-badge.vue | 171 uni_modules/uview-ui/components/u-count-down/props.js | 24 uni_modules/uview-ui/libs/config/props/toast.js | 30 uni_modules/uview-ui/libs/luch-request/core/settle.js | 16 uni_modules/uview-ui/components/u-slider/mpwxs.wxs | 121 uni_modules/cl-upload/components/cl-image/cl-image.vue | 60 uni_modules/uview-ui/libs/luch-request/utils.js | 131 uni_modules/uview-ui/components/u-parse/parser.js | 1075 + uni_modules/uview-ui/components/u--input/u--input.vue | 73 uni_modules/uview-ui/components/u-list-item/props.js | 9 uni_modules/uview-ui/components/u-row/u-row.vue | 93 uni_modules/uview-ui/components/u-keyboard/u-keyboard.vue | 164 uni_modules/uview-ui/libs/config/props/countTo.js | 25 uni_modules/uview-ui/libs/config/props/rowNotice.js | 21 uni_modules/uview-ui/components/u-divider/u-divider.vue | 116 uni_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue | 278 uni_modules/uview-ui/components/u-td/props.js | 5 uni_modules/uview-ui/components/u-parse/props.js | 45 uni_modules/uview-ui/components/u-link/u-link.vue | 83 uni_modules/uview-ui/components/u-checkbox-group/u-checkbox-group.vue | 103 uni_modules/uview-ui/libs/config/props/tabs.js | 32 uni_modules/uview-ui/libs/css/vue.scss | 27 uni_modules/uview-ui/components/u-form-item/u-form-item.vue | 235 uni_modules/uview-ui/libs/config/props/text.js | 38 uni_modules/uview-ui/libs/config/props/scrollList.js | 20 uni_modules/uview-ui/libs/luch-request/helpers/isAbsoluteURL.js | 14 uni_modules/uview-ui/components/u-textarea/u-textarea.vue | 239 uni_modules/uview-ui/components/u-count-to/props.js | 59 uni_modules/uview-ui/components/u-back-top/u-back-top.vue | 129 uni_modules/uview-ui/components/u-code/u-code.vue | 129 uni_modules/uview-ui/components/u-tabs/u-tabs.vue | 354 uni_modules/uview-ui/libs/css/components.scss | 15 uni_modules/uview-ui/components/u-slider/nvue - 副本.js | 180 uni_modules/uview-ui/components/u-upload/mixin.js | 21 uni_modules/uview-ui/libs/config/props/columnNotice.js | 24 pages/index/index.vue | 5 uni_modules/uview-ui/components/u-radio-group/u-radio-group.vue | 108 uni_modules/uview-ui/libs/config/props/overlay.js | 18 uni_modules/cl-upload/package.json | 82 uni_modules/uview-ui/libs/css/flex.scss | 257 uni_modules/uview-ui/libs/util/dayjs.js | 308 uni_modules/uview-ui/components/u-link/props.js | 39 uni_modules/uview-ui/libs/config/props/list.js | 28 utils/request.js | 74 uni_modules/uview-ui/libs/config/props/tabbar.js | 22 uni_modules/uview-ui/components/u-image/u-image.vue | 232 uni_modules/uview-ui/components/u-loading-icon/u-loading-icon.vue | 343 uni_modules/uview-ui/components/u-notify/u-notify.vue | 211 uni_modules/uview-ui/libs/config/props/collapseItem.js | 25 uni_modules/uview-ui/components/u-textarea/props.js | 119 uni_modules/uview-ui/components/u-checkbox/u-checkbox.vue | 344 uni_modules/uview-ui/libs/config/props/button.js | 42 uni_modules/uview-ui/libs/luch-request/helpers/combineURLs.js | 14 uni_modules/uview-ui/libs/config/props/switch.js | 24 uni_modules/uview-ui/components/u-picker/u-picker.vue | 283 uni_modules/uview-ui/libs/mixin/mpMixin.js | 8 index.html | 20 uni_modules/uview-ui/components/u-count-to/u-count-to.vue | 184 uni_modules/uview-ui/components/u-tag/u-tag.vue | 358 uni_modules/uview-ui/components/u-swipe-action-item/index.wxs | 225 uni_modules/uview-ui/components/u-column-notice/props.js | 55 uni_modules/uview-ui/components/u-radio-group/props.js | 85 uni_modules/uview-ui/libs/util/route.js | 124 uni_modules/uview-ui/components/u-input/u-input.vue | 354 uni_modules/uview-ui/libs/config/props/swipeActionItem.js | 21 uni_modules/uview-ui/libs/config/props/avatarGroup.js | 23 uni_modules/uview-ui/components/u-calendar/month.vue | 579 uni_modules/uview-ui/theme.scss | 44 uni_modules/uview-ui/components/u-upload/u-upload.vue | 558 uni_modules/uview-ui/components/u-scroll-list/u-scroll-list.vue | 224 uni_modules/uview-ui/components/u--image/u--image.vue | 47 .gitignore | 2 uni_modules/uview-ui/libs/config/props/cell.js | 35 uni_modules/uview-ui/libs/config/props/gridItem.js | 16 uni_modules/uview-ui/components/u-divider/props.js | 44 uni_modules/uview-ui/libs/luch-request/index.d.ts | 116 uni_modules/uview-ui/libs/config/props/calendar.js | 42 uni_modules/uview-ui/components/u-col/props.js | 29 uni_modules/uview-ui/libs/config/props/avatar.js | 28 uni_modules/uview-ui/libs/config/props/swipeAction.js | 15 uni_modules/uview-ui/libs/config/props/tooltip.js | 25 uni_modules/uview-ui/libs/luch-request/helpers/buildURL.js | 69 uni_modules/uview-ui/components/u-cell-group/u-cell-group.vue | 61 uni_modules/uview-ui/components/u-upload/props.js | 124 uni_modules/uview-ui/components/u-status-bar/props.js | 8 uni_modules/uview-ui/components/u-gap/u-gap.vue | 38 uni_modules/uview-ui/components/u-picker/props.js | 79 uni_modules/uview-ui/components/u-slider/mpwxs.js | 42 manifest.json | 75 uni_modules/uview-ui/components/u-grid-item/props.js | 14 uni_modules/uview-ui/components/u-loadmore/props.js | 94 uni_modules/uview-ui/libs/function/colorGradient.js | 134 uni_modules/uview-ui/changelog.md | 362 uni_modules/uview-ui/libs/css/mp.scss | 0 uni_modules/uview-ui/components/u-row-notice/props.js | 39 uni_modules/uview-ui/libs/config/props/skeleton.js | 25 uni_modules/uview-ui/libs/function/index.js | 731 + uni_modules/cl-upload/changelog.md | 77 uni_modules/uview-ui/components/u-avatar-group/props.js | 52 uni_modules/uview-ui/components/u-form/props.js | 45 uni_modules/uview-ui/components/u-index-anchor/props.js | 29 uni_modules/uview-ui/libs/config/props/line.js | 20 uni_modules/uview-ui/libs/config/props/icon.js | 36 uni_modules/uview-ui/libs/config/props/loadingPage.js | 23 uni_modules/uview-ui/libs/luch-request/index.js | 3 uni_modules/uview-ui/libs/config/props/parse.js | 22 uni_modules/uview-ui/components/u-loading-icon/props.js | 59 uni_modules/uview-ui/components/u-calendar/u-calendar.vue | 384 uni_modules/uview-ui/libs/config/props/collapse.js | 17 uni_modules/uview-ui/components/u-swiper-indicator/u-swiper-indicator.vue | 110 uni_modules/uview-ui/components/u-table/props.js | 5 uni_modules/uview-ui/libs/luch-request/core/mergeConfig.js | 103 uni_modules/uview-ui/components/u-status-bar/u-status-bar.vue | 46 uni_modules/uview-ui/libs/css/mixin.scss | 8 uni_modules/uview-ui/components/u-tabs/props.js | 64 uni_modules/uview-ui/components/u-scroll-list/other.js | 0 uni_modules/uview-ui/components/u-tooltip/clipboard.min.js | 58 uni_modules/uview-ui/libs/config/props/keyboard.js | 30 store/index.js | 7 uni_modules/uview-ui/libs/function/digit.js | 167 uni_modules/uview-ui/components/u-transition/props.js | 24 uni_modules/uview-ui/components/u-skeleton/props.js | 59 pages/actionChange/myInfor/index.vue | 91 uni_modules/uview-ui/components/u-tabbar/props.js | 44 utils/http.js | 28 uni_modules/uview-ui/components/u-toast/u-toast.vue | 291 uni_modules/uview-ui/components/u-collapse/u-collapse.vue | 90 uni_modules/uview-ui/components/u-rate/props.js | 69 uni_modules/uview-ui/components/u-line-progress/u-line-progress.vue | 144 uni_modules/uview-ui/components/u-scroll-list/nvue.js | 28 uni_modules/uview-ui/libs/config/props/loadingIcon.js | 30 uni_modules/uview-ui/components/u-circle-progress/props.js | 8 uni_modules/uview-ui/components/u-scroll-list/scrollWxs.wxs | 50 uni_modules/uview-ui/components/u-checkbox-group/props.js | 82 uni_modules/uview-ui/components/u-notice-bar/props.js | 70 uni_modules/uview-ui/components/u-switch/props.js | 54 unpackage/.gitkeep | 0 uni_modules/uview-ui/components/u-list/props.js | 76 uni_modules/uview-ui/components/u-popup/props.js | 79 uni_modules/uview-ui/libs/config/props/indexList.js | 19 uni_modules/uview-ui/components/u-overlay/u-overlay.vue | 68 uni_modules/uview-ui/components/u-line-progress/props.js | 28 uni_modules/uview-ui/components/u-sticky/u-sticky.vue | 212 uni_modules/uview-ui/components/u-alert/props.js | 44 uni_modules/uview-ui/components/u-tr/u-tr.vue | 31 uni_modules/uview-ui/libs/config/props/gap.js | 19 uni_modules/uview-ui/libs/mixin/style.js | 228 uni_modules/uview-ui/components/u-slider/u-slider.vue | 55 uni_modules/uview-ui/components/u-switch/u-switch.vue | 177 .env.dev.js | 6 uni_modules/uview-ui/components/u-list/u-list.vue | 157 uni_modules/uview-ui/components/u-transition/transition.js | 157 uni_modules/uview-ui/components/u-swipe-action-item/nvue.js | 174 pages.json | 70 uni_modules/uview-ui/libs/luch-request/core/buildFullPath.js | 20 uni_modules/uview-ui/components/u-swipe-action-item/props.js | 41 uni_modules/uview-ui/libs/config/props/rate.js | 26 uni_modules/uview-ui/components/u-input/props.js | 187 uni_modules/uview-ui/libs/luch-request/core/Request.js | 198 uni_modules/uview-ui/components/u-slider/mpother.js | 113 uni_modules/uview-ui/components/u-swipe-action-item/index - backup.wxs | 256 uni_modules/uview-ui/components/u-code-input/u-code-input.vue | 252 uni_modules/uview-ui/libs/function/platform.js | 75 uni_modules/uview-ui/components/u-cell-group/props.js | 14 uni_modules/uview-ui/components/u-tabs-item/props.js | 5 static/img/wodeClick.png | 0 uni_modules/uview-ui/components/u-swipe-action-item/nvue - backup.js | 270 uni_modules/uview-ui/components/u-empty/u-empty.vue | 128 uni_modules/uview-ui/libs/util/calendar.js | 546 App.vue | 93 pages/actionChange/components/fileUpload.vue | 87 uni_modules/uview-ui/components/u-read-more/u-read-more.vue | 157 uni_modules/uview-ui/components/u-scroll-list/props.js | 34 uni_modules/uview-ui/components/u-tabbar-item/props.js | 35 uni.promisify.adaptor.js | 10 uni_modules/uview-ui/libs/config/props/cellGroup.js | 17 uni_modules/uview-ui/libs/mixin/openType.js | 25 uni_modules/uview-ui/components/u-number-box/u-number-box.vue | 416 uni_modules/uview-ui/libs/config/props/notify.js | 22 uni_modules/uview-ui/components/u-tabbar-item/u-tabbar-item.vue | 142 pages/login/login.vue | 173 uni_modules/uview-ui/libs/config/props/backtop.js | 27 uni_modules/uview-ui/libs/config/props/section.js | 24 uni_modules/uview-ui/components/u-calendar/util.js | 85 uni_modules/uview-ui/components/u-gap/props.js | 24 uni_modules/uview-ui/components/u-count-down/u-count-down.vue | 163 uni_modules/uview-ui/libs/config/props/album.js | 25 uni_modules/uview-ui/libs/config/props/lineProgress.js | 19 uni_modules/uview-ui/libs/config/zIndex.js | 20 uni_modules/uview-ui/libs/mixin/mixin.js | 160 uni_modules/uview-ui/components/u-icon/props.js | 89 uni_modules/uview-ui/components/u-navbar/props.js | 84 uni_modules/uview-ui/components/u-safe-bottom/u-safe-bottom.vue | 56 415 files changed, 42,875 insertions(+), 0 deletions(-) diff --git a/.env.dev.js b/.env.dev.js new file mode 100644 index 0000000..ed166ca --- /dev/null +++ b/.env.dev.js @@ -0,0 +1,6 @@ +const config = { + baseUrl: "http://120.26.43.34:8081/api", //������ + // baseUrl: "http://47.99.64.149:8081/api", //������ + // baseUrl: "http://192.168.0.9:8081/api", //������ +}; +module.exports = config; \ No newline at end of file diff --git a/.env.js b/.env.js new file mode 100644 index 0000000..5a2a2fd --- /dev/null +++ b/.env.js @@ -0,0 +1,18 @@ +let ENV_CONFIG = {}; +if (process.env.NODE_ENV === "development") { + //������������ + ENV_CONFIG = require(".env.dev.js"); + console.log("���������������"); +} else { + //������������ + ENV_CONFIG = require(".env.prod.js"); + console.log("���������������"); +} + +//���������������process.uniEnv������ +if (ENV_CONFIG) { + process.uniEnv = {}; + for (let key in ENV_CONFIG) { + process.uniEnv[key] = ENV_CONFIG[key]; + } +} diff --git a/.env.prod.js b/.env.prod.js new file mode 100644 index 0000000..a574ccd --- /dev/null +++ b/.env.prod.js @@ -0,0 +1,4 @@ +const config = { + baseUrl: "http://47.99.64.149:8081/api/", +}; +module.exports = config; diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..685f9fe --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/unpackage/dist +/node_modules \ No newline at end of file diff --git a/.hbuilderx/launch.json b/.hbuilderx/launch.json new file mode 100644 index 0000000..81f13f4 --- /dev/null +++ b/.hbuilderx/launch.json @@ -0,0 +1,16 @@ +{ // launch.json ���������������������������������������configurations��������������������� app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/ + // launchtype������������������local���remote, local���������������������������������remote������������������������������ + "version": "0.0", + "configurations": [{ + "default" : + { + "launchtype" : "local" + }, + "mp-weixin" : + { + "launchtype" : "local" + }, + "type" : "uniCloud" + } + ] +} diff --git a/App.vue b/App.vue new file mode 100644 index 0000000..dd2c821 --- /dev/null +++ b/App.vue @@ -0,0 +1,93 @@ +<script> + import Vue from 'vue' + import { + getUserInfor, + getDic + } from '@/utils/login.js' // ������������ + import { + httpPost, + httpGet + } from '@/utils/http.js' + export default { + onLaunch: function() { + // ������������������ + this.getUserInfo() + }, + methods: { + /** + * ������������ + * ��������������������������������������������������������������������� + * + */ + getUserInfo() { + uni.login({ + provider: 'weixin', + success(res) { + if (res.code) { + // ������������������������code������������������������ + httpGet('/AppUser/wx/login', { + 'code': res.code + }).then(result => { + if (result.data.code === 0) { + // ������������ + uni.clearStorageSync() + uni.setStorageSync('token', result.data.token) + // setTimeout(() => { + // uni.reLaunch({ + // url: '/pages/actionChange/agencyPage/index', + // }) + // }, 3000) + getUserInfor(result.data.token) + getDic() + } else { + // ��������������� + uni.setStorageSync('openId', result.data.openId) + uni.showModal({ + title: '���������', + content: '������������������������������������������', + showCancel: false, + confirmText: '������', + success: res => { + if (res.confirm) { + uni.reLaunch({ + url: '/pages/login/login', + }) + } + }, + }) + } + }) + } else { + console.log(res.errMsg) + } + } + }) + }, + }, + } +</script> +<style lang="scss"> + /* ������������������������������������style������������lang="scss"������ */ + @import "@/uni_modules/uview-ui/index.scss"; + + html { + height: 100%; + } + + .formItemContent { + ::v-deep.u-form-item { + padding: 8px 0; + border-bottom: 1px dashed #bbb; + } + + ::v-deep.u-form-item__body, + /deep/.u-textarea { + padding: 0 !important; + } + + ::v-deep.u-form-item__body__left__content__label, + /deep/.u-radio__text { + font-size: 13px !important; + } + } +</style> \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..b8af7aa --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +## moral_applet_allocation + +��������������������� + diff --git a/index.html b/index.html new file mode 100644 index 0000000..c3ff205 --- /dev/null +++ b/index.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8" /> + <script> + var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || + CSS.supports('top: constant(a)')) + document.write( + '<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + + (coverSupport ? ', viewport-fit=cover' : '') + '" />') + </script> + <title></title> + <!--preload-links--> + <!--app-context--> + </head> + <body> + <div id="app"><!--app-html--></div> + <script type="module" src="/main.js"></script> + </body> +</html> diff --git a/main.js b/main.js new file mode 100644 index 0000000..3892abb --- /dev/null +++ b/main.js @@ -0,0 +1,25 @@ +import Vue from "vue"; +import App from "./App"; +import * as http from "./utils/http"; // http������������ +import * as login from "./utils/login"; // ������ +import * as utils from "./utils/utils"; // ������������ +// import * as common from './utils/common' // ������������ +import store from "./store"; +import storage from "./utils/storage"; // ������������ +import ".env.js"; +// ������������ +Vue.prototype.$store = store; +Vue.prototype.$storage = storage; +Vue.prototype.$http = http; +Vue.prototype.$login = login; +Vue.prototype.$utils = utils; +// Vue.prototype.$common = common + +App.mpType = "app"; +const app = new Vue({ + store, + ...App, +}); +app.$mount(); +import uView from "@/uni_modules/uview-ui"; +Vue.use(uView); diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..5bf1825 --- /dev/null +++ b/manifest.json @@ -0,0 +1,75 @@ +{ + "name" : "test", + "appid" : "__UNI__93C3197", + "description" : "", + "versionName" : "1.0.0", + "versionCode" : "100", + "transformPx" : false, + /* 5+App������������ */ + "app-plus" : { + "usingComponents" : true, + "nvueStyleCompiler" : "uni-app", + "compilerVersion" : 3, + "splashscreen" : { + "alwaysShowBeforeRender" : true, + "waiting" : true, + "autoclose" : true, + "delay" : 0 + }, + /* ������������ */ + "modules" : {}, + /* ������������������ */ + "distribute" : { + /* android������������ */ + "android" : { + "permissions" : [ + "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>", + "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>", + "<uses-permission android:name=\"android.permission.VIBRATE\"/>", + "<uses-permission android:name=\"android.permission.READ_LOGS\"/>", + "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>", + "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>", + "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>", + "<uses-permission android:name=\"android.permission.CAMERA\"/>", + "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>", + "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>", + "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>", + "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>", + "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>", + "<uses-feature android:name=\"android.hardware.camera\"/>", + "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>" + ] + }, + /* ios������������ */ + "ios" : {}, + /* SDK������ */ + "sdkConfigs" : {} + } + }, + /* ��������������������� */ + "quickapp" : {}, + /* ��������������������� */ + "mp-weixin" : { + "appid" : "wx41f4c3c007545088", + "setting" : { + "urlCheck" : false, + "es6" : true, + "postcss" : true, + "minified" : true + }, + "usingComponents" : true + }, + "mp-alipay" : { + "usingComponents" : true + }, + "mp-baidu" : { + "usingComponents" : true + }, + "mp-toutiao" : { + "usingComponents" : true + }, + "uniStatistics" : { + "enable" : false + }, + "vueVersion" : "2" +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..d901b5d --- /dev/null +++ b/package-lock.json @@ -0,0 +1,11 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + } + } +} diff --git a/pages.json b/pages.json new file mode 100644 index 0000000..f0efe61 --- /dev/null +++ b/pages.json @@ -0,0 +1,70 @@ +{ + "pages": [ + //pages���������������������������������������������������https://uniapp.dcloud.io/collocation/pages + + { + "path": "pages/actionChange/agencyPage/index", + "style": { + "navigationBarTitleText": "������", + "enablePullDownRefresh": false + } + }, + { + "path": "pages/login/login" + }, + { + "path": "pages/login/register/register", + "style": { + "navigationBarTitleText": "������", + "enablePullDownRefresh": false + } + }, + { + "path": "pages/actionChange/newPage/index", //��������������������������� + "style": { + "navigationBarTitleText": "���������������", + "enablePullDownRefresh": false, + "navigationBarHidden":true + } + }, + { + "path": "pages/actionChange/workOrderDetails/index", //��������������������������� + "style": { + "navigationBarTitleText": "���������������", + "enablePullDownRefresh": false + } + }, + { + "path": "pages/actionChange/myInfor/index", + "style": { + "navigationBarTitleText": "������", + "enablePullDownRefresh": false + } + } + ], + "tabBar": { + "color": "#515151", + "selectedColor": "#3875C5", + "list": [ + { + "text": "������", + "pagePath": "pages/actionChange/agencyPage/index", + "iconPath": "static/img/shouye.png", + "selectedIconPath": "static/img/shouyeClick.png" + }, + { + "text": "���������������", + "pagePath": "pages/actionChange/newPage/index", + "iconPath": "static/img/xinjian.png", + "selectedIconPath": "static/img/xinjianClick.png" + }, + + { + "text": "������", + "iconPath": "static/img/wode-.png", + "selectedIconPath": "static/img/wodeClick.png", + "pagePath": "pages/actionChange/myInfor/index" + } + ] + } +} diff --git a/pages/actionChange/agencyPage/index.vue b/pages/actionChange/agencyPage/index.vue new file mode 100644 index 0000000..5c535ca --- /dev/null +++ b/pages/actionChange/agencyPage/index.vue @@ -0,0 +1,291 @@ +<template> + <view> + <view class="hearderInfor"> + <view> + <p class="unit"> + <text>���������������{{ userInfor.userName ||''}}</text> + </p> + </view> + <view class="headSculpture"> + <image alt="" src="/static/img/headSculpture.png" /> + <text>������������{{ userInfor.userName || ''}}</text> + </view> + </view> + <view> + <u-tabs :list="list" :scrollable="scrollable" @change="changeTap" /> + </view> + <view class="" v-if="userInfor.userName"> + <view :key="index" v-for="(item, index) in workOderList" class="workOrderDetail" + @tap="handleClick(item, 'edit')"> + <view class="mainContent"> + <p class="rowTip" style="justify-content: space-between"> + <text class=""> ������������: {{ item.allocationNum }} + </text> + <text class="rowTipContenet_right"> + <text catchtap class="butsName" @tap.stop="handleClick(item, 'view')"> ������ </text> + <text catchtap class="butsName" @tap.stop="handleClick(item, 'edit')"> + {{ item.stateName }} + </text> + </text> + </p> + </view> + <u-line color="#bbb" /> + <view class="mainContent"> + <p class="rowTip"> + <view class="rowTipContenet"> + <view class="wholeLine"> + <text class="rowTipContenetLabel">������������:</text> + <text class="rowTipContenetAll"> + {{ unitList.find( + (a) => item && parseInt(a.unitId) === item.unitId + ).unitName + }} + </text> + </view> + </view> + <view class="rowTipContenet"> + <view class="wholeLine"> + <text class="rowTipContenetLabel">������������:</text> + <text class="rowTipContenetAll"> + {{ polluteList.find( + (a) => item && parseInt(a.dataKey) === item.polluteType + ).dataValue + }} + </text> + </view> + </view> + </p> + </view> + <view class="mainContent"> + <p class="rowTip"> + <view class="rowTipContenet"> + <view class="wholeLine"> + <text class="rowTipContenetLabel">������������:</text> + <text class="rowTipContenetAll"> + {{ dictObj.changeEnum[item.changeType] }} + </text> + </view> + </view> + <view class="rowTipContenet"> + <view class="wholeLine"> + <text class="rowTipContenetLabel">������������:</text> + <text class="rowTipContenetAll"> + {{ stateFormatter(item.state) }} + </text> + </view> + </view> + </p> + </view> + <view class="mainContent"> + <p class="rowTip"> + <view class="rowTipContenet"> + <view class="wholeLine"> + <text class="rowTipContenetLabel">������������:</text> + <text class="rowTipContenetAll"> + {{ item.escalationTime }} + </text> + </view> + </view> + <view class="rowTipContenet"> + <view class="wholeLine"> + <text class="rowTipContenetLabel">������������:</text> + <text class="rowTipContenetAll"> + {{ unitList.find( + (a) => + item && parseInt(a.unitId) === item.escalationUnitId + ).unitName + }} + </text> + </view> + </view> + </p> + </view> + <view class="mainContent"> + <p class="rowTip"> + <view class="wholeLine"> + <text class="rowTipContenetLabel">������������:</text> + <text class="rowTipContenetAll">{{ item.pollutePosition }}</text> + </view> + </p> + </view> + </view> + </view> + </view> +</template> +<script> + import { + httpPost, + httpGet + } from '@/utils/http.js' + export default { + data() { + return { + scrollable: false, + userInfor: {}, + dictObj: [], + list: [{ + name: '������', + value: 0, + }, { + name: '���������', + value: 1, + }, { + name: '���������', + value: 2, + }, { + name: '���������', + value: 3, + }, ], + current: 0, + workOderList: [], + unitList: [], + polluteList: [], + } + }, + mounted() { + console.log('mounted this.userInfo', this.userInfo) + }, + created() { + console.log('created this.userInfo', this.userInfo) + this.getContaminateList() + this.getUnitList() + this.getWorkOrder() + }, + onShow() { + uni.showTabBar() + }, + methods: { + changeTap(data) { + this.current = data.value + this.getWorkOrder() + }, + // ������������������list + getUnitList() { + this.$http.httpGet('/allocation/unit').then(res => { + this.unitList = res.data + this.userInfor = this.$storage.getJson('userInfo') + this.dictObj = this.$storage.getJson('dictObj') + this.$storage.setJson('unitList', this.unitList) + }) + }, + getContaminateList() { + this.$http.httpGet('/allocation/contaminate').then(res => { + this.polluteList = res.data + this.$storage.setJson('polluteList', this.polluteList) + }) + }, + stateFormatter(val) { + return this.dictObj.allocationApproveEnum[val] + }, + getWorkOrder() { + httpGet('/allocationApp/select', { + state: this.current, + startTime: '', + endTime: '', + }).then(res => { + this.workOderList = res.data + }) + }, + handleClick(e, pageState) { + this.$http.httpGet('/allocation/detail', { + id: e.allocationId + }).then(res => { + let data = res.data + data.pageState = pageState + let myData = JSON.stringify(data) + uni.navigateTo({ + url: '/pages/actionChange/workOrderDetails/index?infor=' + myData, + }) + }) + }, + }, + // onShow() {}, + } +</script> +<style scoped lang="scss"> + /deep/.uni-page-head { + display: none; + } + + .hearderInfor { + font-size: 26.92rpx; + height: 223.08rpx; + background-color: #3875c5; + color: #f2f2f2; + + .unit { + text-align: right; + padding-right: 19.23rpx; + padding-top: 19.23rpx; + } + + .headSculpture { + display: flex; + align-items: center; + + image { + height: 117.31rpx; + width: 117.31rpx; + margin: 0rpx 46.15rpx; + } + } + } + + .textContent { + text-align: left; + width: 100%; + font-size: 28.85rpx; + } + + .workOrderDetail { + border: 1px solid #bbb; + border-radius: 5px; + min-height: 288.46rpx; + margin: 19.23rpx; + padding: 19.23rpx; + color: #101010; + font-weight: 700; + font-size: 26.92rpx; + + /deep/.u-line { + margin: 19.23rpx 0px !important; + } + + .mainContent { + margin-bottom: 10px; + + .rowTip { + display: flex; + + .wholeLine { + display: flex; + + .rowTipContenetLabel { + min-width: 125rpx; + } + } + + .rowTipContenetAll { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .rowTipContenet { + width: 50%; + text-align: left; + } + } + + .butsName { + display: inline-block; + margin-left: 19.23rpx; + color: #1990ff; + } + + .rowTipContenet_right { + text-align: right !important; + } + } + } +</style> \ No newline at end of file diff --git a/pages/actionChange/components/approvalnfor.vue b/pages/actionChange/components/approvalnfor.vue new file mode 100644 index 0000000..98bc05c --- /dev/null +++ b/pages/actionChange/components/approvalnfor.vue @@ -0,0 +1,230 @@ +<template> + <view class=""> + <!-- ������������ --> + <view class="workOrderDetail"> + <view class="headerCont"> + <p class="title">������������</p> + </view> + <u-line color="#bbb" /> + <view> + <view class="mainContent"> + + <u--form labelPosition="left" label-width="70" :model="form" :border-bottom="false" :rules="rules" + ref="uForm"> + <view class="formItemContent"> + <u-form-item border-bottom label="������������:" prop="checkScore" required :border-bottom="false"> + <view class="" v-if="basicInfor.pageState==='view'"> + {{ basicInfor.checkScore ||''}} + </view> + <u-input v-else v-model="form.checkScore" border="none" placeholder="���������" type="text" /> + </u-form-item> + </view> + <view class="formItemContent"> + <u-form-item border-bottom label="������:" prop="checkDescribe" required :border-bottom="false"> + <view class="" v-if="basicInfor.pageState==='view'"> + {{ basicInfor.checkDescribe ||''}} + </view> + <u--textarea v-else v-model="form.checkDescribe" border="none" placeholder="���������������" /> + </u-form-item> + </view> + <view class="formItemContent"> + <u-form-item border-bottom label="������������" :border-bottom="false"> + <view class="fileBox" v-if="basicInfor.pageState==='view'"> + <cl-upload v-model="fileList" :add="false" :action="`''`" cloud-type="other" + :remove="false" /> + </view> + <view class="fileBox" v-else> + <fileUpload class="rowTipContenetAll" :sys-code="sysCode" @handleFile="handleFile" /> + </view> + </u-form-item> + </view> + </u--form> + </view> + </view> + </view> + </view> +</template> +<script> + import fileUpload from '../components/fileUpload.vue' + export default { + components: { + fileUpload + }, + props: { + basicInfor: { + type: Object, + default: () => {} + }, + }, + computed: { + pageState() { + return this.basicInfor.pageState + } + }, + data() { + return { + sysCode: '1010203', + form: { + checkScore: 0, + checkDescribe: '', + }, + dictObj: this.$storage.getJson('dictObj'), + fileList: [], + fileBaseList: [], + baseUrl: this.$storage.get('baseUrl'), + rules: { + 'checkScore': { + required: true, + message: '���������', + trigger: ['blur', 'change'] + }, + 'checkDescribe': { + required: true, + message: '���������', + trigger: ['blur', 'change'] + }, + } + } + }, + onLoad: function(option) { + //option���object������������������������������������������������ + console.log(option) //��������������������������������������� + }, + onReady() { + //onReady ���uni-app��������������������������� + this.$refs.uForm.setRules(this.rules) + }, + mounted() { + console.log('this.basicInfor', this.basicInfor) + if (this.basicInfor.fileApproveList && this.basicInfor.fileApproveList.length > 0) { + this.basicInfor.fileApproveList.forEach(item => { + let name = item.fileType === 1 ? 'name.png' : 'name.mp4' + this.fileList.push(`${this.baseUrl}/file/preview/${item.fileId}?${name}`) // ������ + }) + console.log('this.fileList', this.basicInfor.fileBaseList) + console.log('this.fileList', this.fileList) + } + + }, + methods: { + handleFile(data) { + this.fileBaseList = data + this.form.fileChangeList = this.fileBaseList + }, + formVali() { + return new Promise((resolve, reject) => { + if(this.basicInfor.pageState!=='view'){ + this.$refs.uForm.validate().then(res => { + resolve(true) + }) + .catch(errors => { + reject(false) + uni.$u.toast('������������') + }) + } else{ + resolve(true) + } + + }); + + } + + }, + } +</script> + +<style scoped lang="scss"> + /deep/.u-line { + margin: 19.23rpx 0px !important; + } + + .workOrderDetail { + border: 1px solid #bbb; + border-radius: 5px; + min-height: 288.46rpx; + margin: 19.23rpx; + padding: 19.23rpx; + color: #101010; + font-weight: 700; + font-size: 26.92rpx; + + .headerCont { + display: flex; + justify-content: space-between; + font-size: 15px; + } + + .mainContent { + margin-bottom: 10px; + font-weight: 500; + + .rowTip { + // display: flex; + padding: 8px 0; + border-bottom: 1px dashed #bbb; + + .wholeLine { + display: flex; + align-items: center; + + .rowTipContenetLabel { + min-width: 125rpx; + } + } + + .rowTipContenetAll { + width: calc(100% - 125rpx; ); + } + + .rowTipContenet { + width: 50%; + text-align: left; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + + .butsName { + display: inline-block; + margin-left: 19.23rpx; + color: #1990ff; + } + } + } + + .rowTipContenet_right { + text-align: right !important; + } + } + } + + /deep/.u-form-item { + padding: 8px 0; + border-bottom: 1px dashed #bbb; + } + + /deep/.u-form-item__body, + /deep/.u-textarea { + padding: 0 !important; + } + + /deep/.u-form-item__body__left__content__label, + /deep/.u-radio__text { + font-size: 13px !important; + } + + .fileBox { + display: -webkit-box; + display: -webkit-flex; + display: flex; + position: relative; + width: 100%; + height: 100%; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -webkit-justify-content: center; + justify-content: center; + } +</style> \ No newline at end of file diff --git a/pages/actionChange/components/basicInfor.vue b/pages/actionChange/components/basicInfor.vue new file mode 100644 index 0000000..f7e26bb --- /dev/null +++ b/pages/actionChange/components/basicInfor.vue @@ -0,0 +1,234 @@ +<template> + <view class=""> + <!-- ������������ --> + <view class="workOrderDetail"> + <view class="headerCont"> + <p class="title">������������</p> + <p>���������{{ basicInfor.allocationNum }}</p> + </view> + <u-line color="#bbb" /> + <view> + <view class="mainContent"> + <p class="rowTip"> + <view class="rowTipContenet"> + <view class="wholeLine"> + <text class="rowTipContenetLabel">������������:</text> + <text class="rowTipContenetAll"> + {{ unitName }} + </text> + </view> + </view> + <view class="rowTipContenet"> + <view class="wholeLine"> + <text class="rowTipContenetLabel">������������:</text> + <text class="rowTipContenetAll"> + {{ polluteType }} + </text> + </view> + </view> + </p> + <p class="rowTip"> + <view class="rowTipContenet"> + <view class="wholeLine"> + <text class="rowTipContenetLabel">������������:</text> + <!-- this.dictObj.investigationEnum[val.investigationType] --> + <text class="rowTipContenetAll"> + {{ dictObj.investigationEnum[basicInfor.investigationType] ||'' }} + </text> + </view> + </view> + <view class="rowTipContenet"> + <view class="wholeLine"> + <text class="rowTipContenetLabel">������������:</text> + <text class="rowTipContenetAll"> + {{ dictObj.changeEnum[basicInfor.changeType] ||'' }} + </text> + </view> + </view> + </p> + <p class="rowTip"> + <view class="rowTipContenet"> + <view class="wholeLine"> + <text class="rowTipContenetLabel">������������:</text> + <text class="rowTipContenetAll"> + {{ escalationUnitName }} + </text> + </view> + </view> + <view class="rowTipContenet"> + <view class="wholeLine"> + <text class="rowTipContenetLabel">���������:</text> + <text class="rowTipContenetAll">{{ basicInfor.escalationName ||'' }}</text> + </view> + </view> + </p> + <p class="rowTip"> + <view class="wholeLine"> + <text class="rowTipContenetLabel">������������:</text> + <text class="rowTipContenetAll">{{ basicInfor.escalationTime ||'' }}</text> + </view> + </p> + <p class="rowTip"> + <view class="wholeLine"> + <text class="rowTipContenetLabel">������������:</text> + <text class="rowTipContenetAll">{{ basicInfor.pollutePosition ||'' }}</text> + </view> + </p> + <p class="rowTip"> + <view class="wholeLine"> + <text class="rowTipContenetLabel">������������:</text> + <text v-if="fileList.length>0" class="rowTipContenetAll"> + <cl-upload + v-model="fileList" + :action="`''`" + :add="false" + cloud-type="other" + :remove="false" + /> + </text> + </view> + </p> + </view> + </view> + </view> + </view> +</template> +<script> +export default { + props: { + basicInfor: { + type: Object, + default: ()=> {} + }, + }, + data() { + return { + polluteList: this.$storage.getJson('polluteList'), + unitList: this.$storage.getJson('unitList'), + dictObj: this.$storage.getJson('dictObj'), + fileList: [], + baseUrl: this.$storage.get('baseUrl'), + } + }, + computed: { + unitName(){ + let data ={} + if(this.basicInfor.unitId){ + data=this.unitList&& this.unitList.find( + (a)=> parseInt(a.unitId) === this.basicInfor.unitId + ) + console.log('nnnnnn', this.unitList) + console.log('nnnnnn', this.basicInfor.unitId) + + } + return data.unitName || '' + }, + escalationUnitName(){ + let data ={} + if(this.basicInfor.unitId){ + data=this.unitList&& this.unitList.find( + (a)=> parseInt(a.unitId) === this.basicInfor.escalationUnitId + ) + console.log('nnnnnn', this.unitList) + console.log('nnnnnn', this.basicInfor.unitId) + + } + return data.unitName || '' + + }, + polluteType(){ + let data ={} + if(this.basicInfor.polluteType){ + data=this.polluteList.find( + (a)=> parseInt(a.dataKey) === this.basicInfor.polluteType + ) + } + return data.dataValue ||'' + } + }, + watch: { + basicInfor: { + handler: function(newValue, oldValue) { + // ������������������ + this.basicInfor=newValue + }, + deep: true + } + }, + onLoad: function (option) { + //option���object������������������������������������������������ + console.log(option) //��������������������������������������� + }, + mounted() { + if(this.basicInfor.fileBaseList&&this.basicInfor.fileBaseList.length>0){ + this.basicInfor.fileBaseList.forEach(item=> { + this.baseUrl='http://120.26.43.34:8081/api/' + let name = item.fileType === 1 ? 'name.png' : '' + this.fileList.push(`${this.baseUrl}/file/preview/${item.fileId}?${name}`) // ������ + this.fileList.push('http://120.26.43.34:8081/api//file/preview/145?name.png') // ������ + }) + console.log('this.fileList', this.basicInfor.fileBaseList) + console.log('this.fileList', this.fileList) + } + + }, + methods: {}, +} +</script> + +<style scoped lang="scss"> +/deep/.u-line { + margin: 19.23rpx 0px !important; +} +.workOrderDetail { + border: 1px solid #bbb; + border-radius: 5px; + min-height: 288.46rpx; + margin: 19.23rpx; + padding: 19.23rpx; + color: #101010; + font-weight: 700; + font-size: 26.92rpx; + .headerCont { + display: flex; + justify-content: space-between; + font-size: 15px; + } + .mainContent { + margin-bottom: 10px; + font-weight: 500; + .rowTip { + display: flex; + padding: 8px 0; + border-bottom: 1px dashed #bbb; + .wholeLine { + display: flex; + width: 100%; + align-items: center; + .rowTipContenetLabel { + min-width: 125rpx; + } + .rowTipContenetAll{ + width: calc(100% - 125rpx); + } + } + + .rowTipContenet { + width: 50%; + text-align: left; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + .butsName { + display: inline-block; + margin-left: 19.23rpx; + color: #1990ff; + } + } + } + .rowTipContenet_right { + text-align: right !important; + } + } +} +</style> diff --git a/pages/actionChange/components/fileUpload.vue b/pages/actionChange/components/fileUpload.vue new file mode 100644 index 0000000..c9d6d82 --- /dev/null +++ b/pages/actionChange/components/fileUpload.vue @@ -0,0 +1,87 @@ +<template> + <view class=""> + <cl-upload + v-model="fileList" + :action="uploadTermExcelUrl" + cloud-type="other" + :data="{ sysCode }" + :headers="hearder" + :image-form-data="{ + compress: true, + }" + :list-style="{ + columns: 3, + columnGap: '10rpx', + rowGap: '10rpx', + padding: '10rpx', + radius: '20rpx' + }" + use-before-delete + @beforeDelete="beforeDelete" + @onSuccess="onSuccess" + /> + </cl-upload> + </view> +</template> + +<script> +export default { + props: { + sysCode: { + type: String, + }, + }, + data() { + return { + fileList: [], + upLoadList: [], + beforFileList: [], + baseUrl: this.$storage.get('baseUrl'), + token: this.$storage.get('token'), + } + }, + computed: { + uploadTermExcelUrl() { + return `${this.baseUrl}/file/upload` || '' + }, + hearder() { + let obj = { token: this.token, Authorization: this.token } + return obj + }, + }, + methods: { + onSuccess(res) { + console.log(res.data.fileId) + let fileId = res.data.fileId + let name = res.data.fileType === 1 ? 'name.png' : '' + this.fileList.push(`${this.baseUrl}/file/preview/${fileId}?${name}`) // ������ + this.upLoadList.push(res.data) + console.log(this.fileList) + this.$emit('handleFile', this.upLoadList) + }, + /** + * ��������������� + * @param {Object} item ��������������������������������������� + * @param {Number} index ������������������������������������ + * @param {Function} next ��������������������������������������������� + * */ + beforeDelete(item, index, next) { + + uni.showModal({ + title: '������������', + content: '���������������������������������', + success: res=> { + if (res.confirm) { + this.fileList.splice(index, 1) + this.upLoadList.splice(index, 1) + console.log('this.fileList', this.upLoadList) + this.$emit('handleFile', this.upLoadList) + } + } + }) + }, + }, +} +</script> + +<style></style> diff --git a/pages/actionChange/components/rectificationInfor.vue b/pages/actionChange/components/rectificationInfor.vue new file mode 100644 index 0000000..8f532aa --- /dev/null +++ b/pages/actionChange/components/rectificationInfor.vue @@ -0,0 +1,263 @@ +<template> + <view class=""> + <!-- ������������ --> + <view class="workOrderDetail"> + <view class="headerCont"> + <p class="title">������������</p> + </view> + <u-line color="#bbb" /> + <view> + <view class="mainContent"> + <u--form labelPosition="left" label-width="70" :model="form" :border-bottom="false" :rules="rules" + ref="uForm"> + <view class="formItemContent"> + <u-form-item label="������������:" required :border-bottom="false"> + <view class="" v-if="pageState"> + {{ dictObj.yesOrNo[basicInfor.isChange] ||''}} + </view> + <u-radio-group v-else v-model="form.isChange" @change="radioGroupChange"> + <u-radio :key="index" v-for="(item, index) in list" + :custom-style="{marginRight: '8px'}" :label="item.name" :name="item.value" /> + </u-radio-group> + </u-form-item> + </view> + <view class="formItemContent"> + <u-form-item label="���������:" prop="changeName" :border-bottom="false" required> + <view class="" v-if="pageState"> + {{ basicInfor.changeName ||''}} + </view> + <u-input v-else v-model="form.changeName" border="none" placeholder="���������" type="text" /> + </u-form-item> + </view> + <view class="formItemContent"> + <u-form-item label="������������" prop="changeDescribe" :border-bottom="false" required> + <view class="" v-if="pageState"> + {{ basicInfor.changeDescribe ||''}} + </view> + <u--textarea v-else v-model="form.changeDescribe" border="none" placeholder="���������������" /> + </u-form-item> + </view> + + <view class="formItemContent"> + <u-form-item label="������������" :border-bottom="false"> + <view class="fileBox" v-if="pageState"> + <cl-upload v-model="fileList" :add="false" :action="`''`" cloud-type="other" + :remove="false" /> + </view> + <view class="fileBox" v-else> + <fileUpload class="rowTipContenetAll" :sys-code="sysCode" + @handleFile="handleFile" /> + </view> + </u-form-item> + </view> + </u--form> + </view> + </view> + </view> + </view> +</template> +<script> + import fileUpload from '../components/fileUpload.vue' + export default { + components: { + fileUpload + }, + props: { + basicInfor: { + type: Object, + default: () => {} + }, + }, + watch: { + basicInfor: { + handler: function(newValue, oldValue) { + // ������������������ + this.basicInfor = newValue + }, + deep: true + } + }, + computed: { + pageState() { + return this.basicInfor.pageState === 'view' || this.basicInfor.state >= 30 + } + }, + data() { + return { + sysCode: '1010202', + list: [{ + name: '���', + value: 0, + }, + { + name: '���', + value: 1, + }, + ], + form: { + isChange: 0, + changeName: '', + changeDescribe: '', + }, + dictObj: this.$storage.getJson('dictObj'), + fileList: [], + fileBaseList: [], + baseUrl: this.$storage.get('baseUrl'), + rules: { + 'changeName': { + required: true, + message: '���������', + trigger: ['blur', 'change'] + }, + 'changeDescribe': { + required: true, + message: '���������', + trigger: ['blur', 'change'] + }, + } + } + }, + onLoad: function(option) { + //option���object������������������������������������������������ + console.log(option) //��������������������������������������� + }, + onReady() { + //onReady ���uni-app��������������������������� + this.$refs.uForm.setRules(this.rules) + }, + mounted() { + if (this.basicInfor.fileChangeList && this.basicInfor.fileChangeList.length > 0) { + this.basicInfor.fileChangeList.forEach(item => { + let name = item.fileType === 1 ? 'name.png' : 'name.mp4' + this.fileList.push(`${this.baseUrl}/file/preview/${item.fileId}?${name}`) // ������ + }) + console.log('this.fileList', this.basicInfor.fileBaseList) + console.log('this.fileList', this.fileList) + } + }, + methods: { + radioGroupChange(e) { + console.log('radioGroupe���e', e) + }, + handleFile(data) { + this.fileBaseList = data + this.form.fileChangeList = this.fileBaseList + }, + formVali() { + return new Promise((resolve, reject) => { + if (!this.pageState) { + this.$refs.uForm.validate().then(res => { + resolve(true) + }) + .catch(errors => { + reject(false) + uni.$u.toast('������������') + }) + } else { + resolve(true) + } + + }); + + } + }, + } +</script> + +<style scoped lang="scss"> + /deep/.u-line { + margin: 19.23rpx 0px !important; + } + + .workOrderDetail { + border: 1px solid #bbb; + border-radius: 5px; + min-height: 288.46rpx; + margin: 19.23rpx; + padding: 19.23rpx; + color: #101010; + font-weight: 700; + font-size: 26.92rpx; + + .headerCont { + display: flex; + justify-content: space-between; + font-size: 15px; + } + + .mainContent { + margin-bottom: 10px; + font-weight: 500; + + .rowTip { + padding: 8px 0; + border-bottom: 1px dashed #bbb; + + .wholeLine { + display: flex; + width: 100%; + align-items: center; + + .rowTipContenetLabel { + min-width: 125rpx; + } + } + + .rowTipContenetAll { + width: calc(100% - 125rpx; ); + } + + .rowTipContenet { + width: 50%; + text-align: left; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + + .butsName { + display: inline-block; + margin-left: 19.23rpx; + color: #1990ff; + } + } + } + + .rowTipContenet_right { + text-align: right !important; + } + } + } + + .formItemContent { + /deep/.u-form-item { + padding: 8px 0; + border-bottom: 1px dashed #bbb; + } + + /deep/.u-form-item__body, + /deep/.u-textarea { + padding: 0 !important; + } + + /deep/.u-form-item__body__left__content__label, + /deep/.u-radio__text { + font-size: 13px !important; + } + } + + .fileBox { + display: -webkit-box; + display: -webkit-flex; + display: flex; + position: relative; + width: 100%; + height: 100%; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -webkit-justify-content: center; + justify-content: center; + } +</style> \ No newline at end of file diff --git a/pages/actionChange/myInfor/index.vue b/pages/actionChange/myInfor/index.vue new file mode 100644 index 0000000..b63dc6c --- /dev/null +++ b/pages/actionChange/myInfor/index.vue @@ -0,0 +1,91 @@ +<template> + <view class="mainContent"> + <view class="headerAvatar"> + <view class=""> + <u-avatar :text="firstFont" fontSize="40" randomBgColor size='100'></u-avatar> + </view> + </view> + <view class="inforBox"> + <u-cell-group> + <u-cell icon="server-man" title="������" :value="userInfor.userName"></u-cell> + <u-cell icon="account-fill" title="������" :value="userInfor.account"></u-cell> + <u-cell icon="integral-fill" title="������������" :value="unitName"></u-cell> + <u-cell icon="phone-fill" title="���������" :value="userInfor.mobile"></u-cell> + </u-cell-group> + </view> + <view class="bunts"> + <u-button type="error" text="������" @click="goOut"></u-button> + </view> + </view> +</template> +<script> + import { + created + } from '../../../uni_modules/uview-ui/libs/mixin/mixin' + export default { + data() { + return { + loading: false, + userInfor: {}, + unitList: [] + } + }, + computed: { + unitName() { + let data = '' + if (this.unitList.length > 0) { + data = this.unitList.find(a => parseInt(a.unitId) === this.userInfor.unitId).unitName + } + return data || '' + }, + firstFont() { + return this.userInfor.userName[0] || '���' + } + }, + created() { + this.$http.httpGet('/allocation/unit').then(res => { + this.unitList = res.data + }) + this.userInfor = this.$storage.getJson('userInfo') + console.log('userInfor', this.userInfor.userName[0]) + }, + methods: { + goOut() { + uni.showModal({ + title: '������', + content: '������������������', + success: res => { + if (res.confirm) { + this.$http.httpGet('/AppUser/wx/exit', { + userId: this.userInfor.userId + }).then(res => { + uni.clearStorageSync() + uni.reLaunch({ + url: '/pages/login/login', + }) + }).catch(uni.$u.toast('������������')) + } + } + }) + } + } + } +</script> +<style lang="scss" scoped> + .mainContent { + padding: 20px; + } + + .headerAvatar { + display: flex; + justify-content: center; + } + + .inforBox { + margin-top: 57.69rpx; + } + + .bunts { + margin-top: 57.69rpx; + } +</style> \ No newline at end of file diff --git a/pages/actionChange/newPage/index.vue b/pages/actionChange/newPage/index.vue new file mode 100644 index 0000000..e33c5bf --- /dev/null +++ b/pages/actionChange/newPage/index.vue @@ -0,0 +1,410 @@ +<template> + <view class="mianContent"> + <p class="title">������������</p> + <u-form + ref="uForm" + label-width="65" + :model="form" + :rules="rules" + > + <u-form-item + border-bottom + label="������������:" + prop="unitId" + required + @click=" + showCheckBox = true; + hideKeyboard('unitList', 'unitId'); + " + > + <u--input + v-model="form.unitId" + border="none" + disabled + disabled-color="#ffffff" + placeholder="���������" + /> + <u-icon slot="right" name="arrow-right" /> + </u-form-item> + + <u-form-item + border-bottom + label="������������:" + prop="polluteType" + required + @click=" + showCheckBox = true; + hideKeyboard('polluteList', 'polluteType'); + " + > + <u-input + v-model="form.polluteType" + border="none" + disabled + disabled-color="#ffffff" + placeholder="���������" + type="select" + /> + <u-icon slot="right" name="arrow-right" /> + </u-form-item> + <u-form-item + border="none" + border-bottom + label="������������:" + prop="changeType" + required + @click=" + showCheckBox = true; + hideKeyboard('changeEnum', 'changeType'); + " + > + <u-input + v-model="form.changeType" + border="none" + disabled + disabled-color="#ffffff" + placeholder="���������" + type="select" + /> + <u-icon slot="right" name="arrow-right" /> + </u-form-item> + <u-form-item + border-bottom + label="������������:" + placeholder="���������" + required + > + <u-input v-model="form.changeDay" border="none" type="number" /> + </u-form-item> + <u-form-item + border-bottom + label="������������:" + prop="escalationUnitId" + required + @click=" + showCheckBox = true; + hideKeyboard('unitList', 'escalationUnitId'); + " + > + <u-input + v-model="form.escalationUnitId" + border="none" + disabled + disabled-color="#ffffff" + placeholder="���������" + type="select" + /> + <u-icon slot="right" name="arrow-right" /> + </u-form-item> + <u-form-item + border-bottom + label="���������:" + prop="escalationName" + required + > + <u-input + v-model="form.escalationName" + border="none" + placeholder="���������" + type="text" + /> + </u-form-item> + <u-form-item + border-bottom + label="������������:" + prop="investigationType" + required + > + <u-radio-group v-model="form.investigationType" style="font-size: 13px;"> + <u-radio + :key="index" + v-for="(item, index) in Dic.investigationEnum" + :custom-style="{marginRight: '8px'}" + :label="item.name" + :name="item.value" + /> + </u-radio-group> + </u-form-item> + <u-form-item + border-bottom + label="������������:" + prop="escalationTime" + required + @click="showeEscalationTime = true" + > + <u-input + v-model="form.escalationTime" + border="none" + disabled + disabled-color="#ffffff" + placeholder="���������" + type="select" + /> + <u-icon slot="right" name="arrow-right" /> + <u-datetime-picker + ref="datetimePicker" + v-model="timeFormet" + mode="date" + :show="showeEscalationTime" + @confirm="checkTime" + /> + </u-form-item> + <u-form-item + border-bottom + label="������������:" + prop="pollutePosition" + required + > + <u-input + v-model="form.pollutePosition" + border="none" + placeholder="���������" + type="text" + /> + </u-form-item> + <u-form-item + border-bottom + label="������������:" + prop="problemDescribe" + required + > + <u--textarea v-model="form.problemDescribe" border="none" placeholder="���������������" /> + </u-form-item> + <u-form-item border-bottom label="������������:"> + <view class="fileBox"> + <fileUpload :sys-code="sysCode" @handleFile="handleFile" /> + </view> + </u-form-item> + </u-form> + <u-action-sheet + v-if="actionOptionList.length > 0" + :actions="actionOptionList" + :show="showCheckBox" + title="���������" + @close="showCheckBox = false" + @select="selectBack" + /> + <view class="bunts"> + <u-button shape="square" @click="close">������</u-button> + <u-button shape="square" type="primary" @click="submit">������</u-button> + </view> + </view> +</template> + +<script> +import fileUpload from '../components/fileUpload.vue' +export default { + components: { + fileUpload + }, + data() { + return { + sysCode: '1010201', // + showCheckBox: false, + showeEscalationTime: false, + actionOptionList: [], + rules: { + 'unitId': { + required: true, + message: '���������', + trigger: ['blur', 'change'] + }, + 'polluteType': { + required: true, + message: '���������', + trigger: ['blur', 'change'] + }, + 'changeType': { + required: true, + message: '���������', + trigger: ['blur', 'change'] + }, + 'changeDay': { + required: true, + message: '���������', + trigger: ['blur', 'change'] + }, + 'escalationName': { + required: true, + message: '���������', + trigger: ['blur'] + }, + 'escalationUnitId': { + required: true, + message: '���������', + trigger: ['blur', 'change'] + }, + 'escalationTime': { + required: true, + message: '���������', + trigger: ['blur'] + }, 'problemDescribe': { + required: true, + message: '���������', + trigger: ['blur'] + }, 'pollutePosition': { + required: true, + message: '���������', + trigger: ['blur'] + }, + }, + currentKey: '', + Dic: this.$storage.getJson('dict'), + changeEnum: [], + timeFormet: Number(new Date()), + form: { + unitId: '', + polluteType: '', + changeType: '', + changeDay: '', + escalationName: '', + escalationUnitId: '', + escalationTime: '', + problemDescribe: '', + pollutePosition: '', + }, + sumbitForm: { + unitId: '', + polluteType: '', + changeType: '', + changeDay: '', + escalationName: '', + escalationUnitId: '', + escalationTime: '', + problemDescribe: '', + pollutePosition: '', + }, + unitList: [], + polluteList: [], + fileBaseList: [], + } + }, + onReady() { + //onReady ���uni-app��������������������������� + this.$refs.uForm.setRules(this.rules) + }, + onShow(){ + uni.hideTabBar() + }, + created() { + this.changeEnum = this.Dic.changeEnum + this.getUnitList() + this.getContaminateList() + }, + methods: { + handleFile(data){ + this.fileBaseList=data + }, + close(){ + uni.reLaunch({ + url: '/pages/actionChange/agencyPage/index', + }) + }, + hideKeyboard(data, key) { + this.actionOptionList = [] + let list = this[data] + + this.currentKey = key + list.forEach((item)=> { + item.name = item.dataValue || item.name || item.unitName + item.value = item.dataKey || item.value|| item.unitId + }) + + this.actionOptionList = list + }, + selectBack(e) { + this.form[this.currentKey] = e.name + this.sumbitForm[this.currentKey] = e.value + + }, + checkTime(e) { + this.showeEscalationTime = false + let data = this.$utils.dateFormatter(e.value) + this.form.escalationTime = data + this.sumbitForm.escalationTime = data + }, + submit() { + this.$refs.uForm.validate().then(res=> { + this.sumbitForm.problemDescribe=this.form.problemDescribe + this.sumbitForm.pollutePosition=this.form.pollutePosition + this.sumbitForm.changeDay=this.form.changeDay + this.sumbitForm.escalationName=this.form.escalationName + this.sumbitForm.fileBaseList=this.fileBaseList + this.sumbitForm.state='10' + console.log('this.sumbitForm', this.sumbitForm) + this.$http.httpPost('/allocation/insert', {...this.sumbitForm}).then((res)=> { + uni.$u.toast('������������') + this.close() + }) + }).catch(errors=> { + uni.$u.toast('������������') + }) + }, + // ������������������list + getUnitList() { + this.$http.httpGet('/allocation/unit').then((res)=> { + this.unitList = res.data + }) + }, + getContaminateList() { + this.$http.httpGet('/allocation/contaminate').then((res)=> { + this.polluteList = res.data + }) + }, + }, +} +</script> + +<style scoped lang="scss"> + uni-page-body { + padding-top: 10px; + } + + .mianContent { + margin: 19.23rpx; + border-radius: 5px; + .title { + padding: 9.62rpx; + font-size: 16px; + font-weight: 700; + color: #101010; + border-bottom: 1px solid #bbb; + } + + /deep/.u-form-item { + padding-left: 10px; + } + + /deep/.u-form-item__body { + padding: 5px 0px !important; + font-size: 13px!important; + } + /deep/.u-form-item__body__left__content__label,/deep/.u-input__content__field-wrapper__field,/deep/.u-radio__text{ + font-size: 13px!important; + } + } + .bunts { + display: flex; + margin-top: 20px; + margin-bottom: 96.15rpx; + padding-bottom: 20px; + .u-button { + width: 288.46rpx; + } + } + .fileBox{ + display: -webkit-box; + display: -webkit-flex; + display: flex; + position: relative; + width: 100%; + height: 100%; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -webkit-justify-content: center; + justify-content: center; + } +</style> \ No newline at end of file diff --git a/pages/actionChange/workOrderDetails/index.vue b/pages/actionChange/workOrderDetails/index.vue new file mode 100644 index 0000000..1e79165 --- /dev/null +++ b/pages/actionChange/workOrderDetails/index.vue @@ -0,0 +1,106 @@ +<template> + <view class="mainContent"> + <basicInfor :basic-infor="basicInfor" /> + <rectificationInfor ref="rectificationInfor" :basic-infor="basicInfor" /> + <approvalnfor ref="approvalnfor" v-if="basicInfor.state >= 30" :basic-infor="basicInfor" /> + <view class="bunts"> + <u-button shape="square" @click="close">������</u-button> + <u-button + v-if="pageState==='edit'" + shape="square" + type="primary" + @click="submit" + > + ������ + </u-button> + </view> + </view> +</template> +<script> +import basicInfor from '../components/basicInfor.vue' +import rectificationInfor from '../components/rectificationInfor.vue' +import approvalnfor from '../components/approvalnfor.vue' +export default { + components: { + basicInfor, + rectificationInfor, + approvalnfor, + }, + data() { + return { + basicInfor: {} + } + }, + computed: { + pageState() { + return this.basicInfor.pageState + } + }, + onLoad: function(option) { + console.log('option', option) + //option���object������������������������������������������������ + this.basicInfor = JSON.parse(option.infor) + + }, + onBackPress(e) { + uni.navigateTo({ + url: '/pages/actionChange/agencyPage/index', + }) + return false + }, + methods: { + radioGroupChange(e) { + console.log('radioGroupe���e', this.workForme.isChange) + }, + close() { + let pages = getCurrentPages() // ������������ + let beforePage = pages[pages.length - 3] // ������������ + //beforePage.$vm.reFresh = Math.random()//������������������������ + uni.navigateBack({ + delta: 1, //������������������������������������������2 + success: function() { + // beforePage.$vm.reFresh() + } + }) + }, + submit() { + Promise.all([this.$refs.rectificationInfor && this.$refs.rectificationInfor.formVali(), this.$refs + .approvalnfor && this.$refs.approvalnfor.formVali() + ]) // + .then(()=> { + let api = this.basicInfor.state >= 30 ? '/allocation/check' : '/allocation/change' //������ + let form = this.basicInfor.state >=30 ? this.$refs.approvalnfor.form : this.$refs.rectificationInfor.form + let data = { + allocationId: this.basicInfor.allocationId, + ...form, + state: this.basicInfor.state, + } + this.$http.httpPost(api, data).then((res)=> { + this.close() + }) + }) + .catch(err=> { + console.log('���������������������', err) + }) + + } + }, +} +</script> + +<style scoped lang="scss"> + .mainContent { + padding-bottom: 38.46rpx; + } + + .bunts { + display: flex; + margin-top: 20px; + margin-bottom: 96.15rpx; + padding: 0 20px; + + .u-button { + width: 288.46rpx; + } + } +</style> \ No newline at end of file diff --git a/pages/index/index.vue b/pages/index/index.vue new file mode 100644 index 0000000..6445b39 --- /dev/null +++ b/pages/index/index.vue @@ -0,0 +1,5 @@ +<template /> + +<script></script> + +<style></style> diff --git a/pages/login/login.vue b/pages/login/login.vue new file mode 100644 index 0000000..147529c --- /dev/null +++ b/pages/login/login.vue @@ -0,0 +1,173 @@ +<template> + <view class="page"> + <view class="tit"> + <view class="imageContent"> + <image src="/static/logo.png" style="width: 67.31rpx; height: 100rpx" /> + </view> + <view class=""> + <text>������������������������</text> + </view> + </view> + <view class="formConten"> + <view> + <u-form ref="uForm" label-position="left" :model="form" :labelStyle="labelStyle"> + <u-form-item label="������:" prop="account"> + <u-input v-model="form.account" color='#fff' placeholder="���������������" /> + </u-form-item> + <u-form-item label="������:" prop="password"> + <u-input v-model="form.password" :password-icon="passwordIcon" color='#fff' placeholder="���������������" + type="password" /> + </u-form-item> + </u-form> + </view> + <view class="loginContent"> + <p> + <navigator style="display: inline-block;" url="/pages/login/register/register"> + <text style="text-decoration: underline">������������</text> + </navigator> + </p> + <u-button @click="submit">������</u-button> + </view> + </view> + </view> +</template> +<script> + import { + login, + getUserInfor, + getDic + } from '@/utils/login.js' // ������������ + import { + httpPost, + httpGet + } from '@/utils/http.js' + export default { + data() { + return { + labelStyle: { + color: '#fff' + }, + passwordIcon: false, + form: { + account: '', + password: '', + }, + rules: { + account: [{ + required: true, + message: '���������������', + // ��������������������������������������������������� + trigger: ['change', 'blur'], + }, ], + password: [{ + required: true, + message: '���������������', + trigger: ['change', 'blur'], + }, ], + }, + } + }, + onReady() { + //onReady ���uni-app��������������������������� + this.$refs.uForm.setRules(this.rules) + }, + methods: { + submit() { + this.$refs.uForm.validate().then(res => { + this.getlogin() + }).catch(errors => { + uni.$u.toast('������������') + }) + }, + //������ + getlogin() { + let openId = this.$storage.get('openId') + login({ + ...this.form, + openId + }).then(response => { + this.$storage.set('token', response.data.token) + getDic() + getUserInfor(response.data.token) + uni.hideLoading() + uni.switchTab({ + url: '/pages/actionChange/agencyPage/index', + }) + // this.$storage.setJson("accountInFor", this.form); + // console.log('this.$store', this.$store) + // this.$store.commit('token', token) + }).catch(errors => { + uni.showToast({ + title: errors, + icon: 'none', + }) + }) + }, + }, + } +</script> +<style scoped lang="scss"> + uni-page-body { + height: 100%; + } + + .page { + color: #ffffff; + background: #3875c5; + height: 100%; + } + + .tit { + padding-top: 307.69rpx; + display: flex; + justify-content: center; + align-items: center; + font-size: 53.85rpx; + } + + .formConten { + padding: 0 76.92rpx; + color: #ffffff; + } + + .u-form-item { + color: #ffffff; + font-size: 28.85rpx; + font-weight: 700; + } + + // /deep/.uni-input-wrapper { + // background: #fff; + // border-radius: 5px; + // } + // /deep/.uni-input-placeholder { + // padding-left: 10px; + // } + /deep/.u-form-item__body__left__content__label { + color: #fff; + } + + // /deep/.uni-input-input { + // padding-left: 10px; + // } + .loginContent { + margin-top: 38.46rpx; + + p { + text-align: right; + margin-bottom: 20px; + + a { + color: #fff; + } + } + + .u-btn--default { + width: 80%; + } + } + + uni-navigator { + display: inline-block; + } +</style> \ No newline at end of file diff --git a/pages/login/register/register.vue b/pages/login/register/register.vue new file mode 100644 index 0000000..a3482e3 --- /dev/null +++ b/pages/login/register/register.vue @@ -0,0 +1,74 @@ +<template> + <view> + <view class="imageContent"> + <image + src="/static/logo.png" + style="width: 267.31rpx; height: 403.85rpx" + /> + </view> + <view class="formContent"> + <u-form ref="uForm" label-width="70" :model="form"> + <u-form-item label="������"> + <u-input v-model="form.name" placeholder="���������������������" /> + </u-form-item> + <u-form-item label="������"> + <u-input v-model="form.intro" placeholder="���������������" /> + </u-form-item> + <u-form-item label="������������"> + <u-input v-model="form.intro" placeholder="���������������������" /> + </u-form-item> + </u-form> + <p class="tips"> + <text>���������������������������������������������������������������������������������������</text> + </p> + <u-button @click="submit">������</u-button> + </view> + </view> +</template> + +<script> +export default { + data() { + return { + form: {}, + rules: { + name: [ + { + required: true, + message: '���������������', + // ��������������������������������������������������� + trigger: ['change', 'blur'], + }, + ], + password: [ + { + required: true, + message: '���������������', + trigger: ['change', 'blur'], + }, + ], + }, + } + }, + onReady() { + this.$refs.uForm.setRules(this.rules) + }, + methods: {}, + // ������������onReady���������������������onLoad������������������������������������������ +} +</script> + +<style scoped lang="scss"> +.imageContent { + text-align: center; + margin: 38.46rpx 0rpx; +} +.formContent { + padding: 0rpx 48.08rpx; +} +.tips { + font-size: 12px; + margin: 38.46rpx 0; +} + +</style> diff --git a/static/img/headSculpture.png b/static/img/headSculpture.png new file mode 100644 index 0000000..479675f --- /dev/null +++ b/static/img/headSculpture.png Binary files differ diff --git a/static/img/shouye.png b/static/img/shouye.png new file mode 100644 index 0000000..6cc733a --- /dev/null +++ b/static/img/shouye.png Binary files differ diff --git a/static/img/shouyeClick.png b/static/img/shouyeClick.png new file mode 100644 index 0000000..f0effdd --- /dev/null +++ b/static/img/shouyeClick.png Binary files differ diff --git a/static/img/wode-.png b/static/img/wode-.png new file mode 100644 index 0000000..bcc3f2f --- /dev/null +++ b/static/img/wode-.png Binary files differ diff --git a/static/img/wodeClick.png b/static/img/wodeClick.png new file mode 100644 index 0000000..6687d89 --- /dev/null +++ b/static/img/wodeClick.png Binary files differ diff --git a/static/img/xinjian.png b/static/img/xinjian.png new file mode 100644 index 0000000..0449374 --- /dev/null +++ b/static/img/xinjian.png Binary files differ diff --git a/static/img/xinjianClick.png b/static/img/xinjianClick.png new file mode 100644 index 0000000..69439e8 --- /dev/null +++ b/static/img/xinjianClick.png Binary files differ diff --git a/static/logo.png b/static/logo.png new file mode 100644 index 0000000..f60a2c3 --- /dev/null +++ b/static/logo.png Binary files differ diff --git a/store/index.js b/store/index.js new file mode 100644 index 0000000..293363c --- /dev/null +++ b/store/index.js @@ -0,0 +1,7 @@ +import Vue from 'vue' +import Vuex from 'vuex' +import modules from './modules/index.js' +Vue.use(Vuex) + +const store = new Vuex.Store(modules) +export default store diff --git a/store/modules/index.js b/store/modules/index.js new file mode 100644 index 0000000..b32b44c --- /dev/null +++ b/store/modules/index.js @@ -0,0 +1,10 @@ +import _ from 'lodash' + +const files = require.context('.', false, /\.js$/) +const modules = {} + +files.keys().forEach(key => { + if (key === './index.js') return + _.mergeWith(modules,files(key).default) +}) +export default modules diff --git a/store/modules/user.js b/store/modules/user.js new file mode 100644 index 0000000..166094c --- /dev/null +++ b/store/modules/user.js @@ -0,0 +1,111 @@ +import Vue from "vue"; +export default { + state: { + user: null, + tonken:'' + }, + mutations: { + login(state, user) { + state.user = user; + // ������������������ + Vue.prototype.$cache.set("_userInfo", user, 0); + }, + tonken(state, data) { + state.tonken = data; + // ������������������ + Vue.prototype.$cache.set("state",tonken,0); + }, + logout(state) { + state.user = null; + // ������������������������ + Vue.prototype.$cache.delete("_userInfo"); + }, + }, + actions: { + autoLogin({ commit, getters, dispatch }) { + console.log('Vue.prototype.$storage',Vue.prototype.$storage.get("tonken")) + let tonken = Vue.prototype.$storage.get("tonken"); + console.log("tonken", tonken); + // ��������������������������������������������������������������������� + if (tonken) { + const params = { + account: accountInFor.account, + password: accountInFor.password, + }; + uni.showLoading({ + title: "���������������...", + }); + dispatch("login", params) + .then((res) => { + uni.hideLoading(); + // uni.showToast({ + // title: '������������������', + // icon: 'success' + // }) + }) + .catch(() => { + uni.hideLoading(); + uni.showToast({ + title: "���������������������������������", + icon: "none", + }); + setTimeout(() => { + uni.reLaunch({ + url: "/pages/login/login", + }); + }, 1000); + }); + } else { + // ������������������������������������������������������������ + uni.showModal({ + title: "���������", + content: "������������������������������������������", + showCancel: false, + confirmText: "������", + success: (res) => { + if (res.confirm) { + uni.reLaunch({ + url: "/pages/login/login", + }); + } + }, + }); + } + }, + login({ commit }, params) { + return new Promise((resolve, reject) => { + Vue.prototype.$login + .login(params) + .then((res) => { + if (res.ok()) { + console.log(response); + this.$storage.set("token", response.data.token); + this.$storage.setJson("accountInFor", this.form); + let token = this.$storage.get("token"); + commit("login", tmp); + resolve(res); + } else { + reject(res); + } + }) + .catch((err) => { + reject(err); + }); + }); + }, + logout({ commit }) { + commit("logout"); + uni.reLaunch({ + url: "/pages/login/login", + }); + }, + }, + getters: { + user: (state) => { + if (state.user) { + return state.user; + } + // return Vue.prototype.$cache.get('_userInfo') + }, + }, +}; diff --git a/uni.promisify.adaptor.js b/uni.promisify.adaptor.js new file mode 100644 index 0000000..47fbce1 --- /dev/null +++ b/uni.promisify.adaptor.js @@ -0,0 +1,10 @@ +uni.addInterceptor({ + returnValue (res) { + if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) { + return res; + } + return new Promise((resolve, reject) => { + res.then((res) => res[0] ? reject(res[0]) : resolve(res[1])); + }); + }, +}); \ No newline at end of file diff --git a/uni.scss b/uni.scss new file mode 100644 index 0000000..417a13f --- /dev/null +++ b/uni.scss @@ -0,0 +1,77 @@ +/** + * ���������uni-app��������������������������� + * + * uni-app ������������������������������������https://ext.dcloud.net.cn������������������������������������������������������ + * ���������������������������������������������scss������������������������������������������������������������������ import ���������������������������������������������������������������������������������App + * + */ + +/** + * ������������App������������������������������������������������������������������������������������������������������������������������������ + * + * ���������������������������������scss��������������������������������������� scss ������������������������������������������ import ������������ + */ + +/* ������������ */ + +/* ������������������ */ +$uni-color-primary: #007aff; +$uni-color-success: #4cd964; +$uni-color-warning: #f0ad4e; +$uni-color-error: #dd524d; + +/* ������������������ */ +$uni-text-color: #333; //��������� +$uni-text-color-inverse: #fff; //������ +$uni-text-color-grey: #999; //��������������������������������������������� +$uni-text-color-placeholder: #808080; +$uni-text-color-disable: #c0c0c0; + +/* ������������ */ +$uni-bg-color: #ffffff; +$uni-bg-color-grey: #f8f8f8; +$uni-bg-color-hover: #f1f1f1; //������������������ +$uni-bg-color-mask: rgba(0, 0, 0, 0.4); //������������ + +/* ������������ */ +$uni-border-color: #c8c7cc; + +/* ������������ */ + +/* ������������ */ +$uni-font-size-sm: 12px; +$uni-font-size-base: 14px; +$uni-font-size-lg: 16; + +/* ������������ */ +$uni-img-size-sm: 20px; +$uni-img-size-base: 26px; +$uni-img-size-lg: 40px; + +/* Border Radius */ +$uni-border-radius-sm: 2px; +$uni-border-radius-base: 3px; +$uni-border-radius-lg: 6px; +$uni-border-radius-circle: 50%; + +/* ������������ */ +$uni-spacing-row-sm: 5px; +$uni-spacing-row-base: 10px; +$uni-spacing-row-lg: 15px; + +/* ������������ */ +$uni-spacing-col-sm: 4px; +$uni-spacing-col-base: 8px; +$uni-spacing-col-lg: 12px; + +/* ��������� */ +$uni-opacity-disabled: 0.3; // ��������������������������� + +/* ������������������ */ +$uni-color-title: #2c405a; // ������������������ +$uni-font-size-title: 20px; +$uni-color-subtitle: #555555; // ������������������ +$uni-font-size-subtitle: 26px; +$uni-color-paragraph: #3f536e; // ������������������ +$uni-font-size-paragraph: 15px; +@import "@/uni_modules/uview-ui/theme.scss"; diff --git a/uni_modules/cl-upload/changelog.md b/uni_modules/cl-upload/changelog.md new file mode 100644 index 0000000..123de9b --- /dev/null +++ b/uni_modules/cl-upload/changelog.md @@ -0,0 +1,77 @@ +## 1.4.0���2023-07-04��� +������unicloud������������������ +## 1.3.9���2023-06-28��� +��������������������������������� +## 1.3.8���2023-06-02��� +���������������������������������������������������; ���������������������������������; +## 1.3.7���2023-05-22��� +���������������������������������; ������������������������ +## 1.3.6���2023-05-22��� +��������������������������������� +## 1.3.5���2023-05-04��� +���������������cloudType���other��������������������������������������������������� +## 1.3.4���2023-04-27��� +���������������unicloud��������������������������������������� +## 1.3.3���2023-04-27��� +������������������������������ +## 1.3.2���2023-04-24��� +������������APP������cloudType:other ������������http������������ +## 1.3.1���2023-04-19��� +������������������ +## 1.3.0���2023-04-19��� +������������������������������; ��������������������������������������� +## 1.2.9���2023-03-22��� +������������������ +## 1.2.8���2023-03-22��� +������������������ +## 1.2.7���2023-03-21��� +������������������������������������ +## 1.2.6���2023-03-21��� +������������������������������������ +## 1.2.5���2023-03-08��� +������vue3���v-model������������ +## 1.2.4���2023-03-06��� +1.������������������������������video������������������; +2.������unicloud������v-model���������������; +## 1.2.3���2023-02-02��� +������������������������������������ +## 1.2.2���2023-02-01��� +������������������������������������������ +## 1.2.1���2023-01-31��� +������������������������ +## 1.2.0���2022-12-12��� +������uniCloud������ +## 1.1.9���2022-12-12��� +1. ������������������������ +2. ������������������ +## 1.1.8���2022-12-09��� +��������������������������������������������������� +## 1.1.7���2022-12-01��� +������h5������������������������������������������������������������ +## 1.1.6���2022-11-24��� +������������������������������������ +## 1.1.5���2022-11-07��� +������������������ +## 1.1.4���2022-11-07��� +��������������������������������������������������������������������� +## 1.1.3���2022-10-28��� +������������������������ +## 1.1.1���2022-10-28��� +������������������ +## 1.1.0���2022-08-25��� +������base64������������ +## 1.0.9���2022-08-25��� +��������������������������������������� +## 1.0.8���2022-08-01��� +��������������������������� +## 1.0.6���2022-07-30��� +������������������ +## 1.0.5���2022-07-30��� +1. aspect-ratio���������������������height������������ +2. ������������������������������������ +## 1.0.3���2022-07-30��� +��������������������������������� +## 1.0.2���2022-07-30��� +��������������������������������������� +## 1.0.1���2022-07-29��� +��������������� diff --git a/uni_modules/cl-upload/components/cl-image/cl-image.vue b/uni_modules/cl-upload/components/cl-image/cl-image.vue new file mode 100644 index 0000000..61fc4eb --- /dev/null +++ b/uni_modules/cl-upload/components/cl-image/cl-image.vue @@ -0,0 +1,60 @@ +<template> + <image class="image" :src="imgSrc" mode="aspectFill" :disabled="false" :controls='false' @error="imgerror"></image> +</template> + +<script> + export default { + props: { + src: { + type: String, + default: '' + }, + cloudType: { + type: String, + default: 'oss' + }, + }, + data() { + return { + imgSrc: '' + }; + }, + mounted() { + this.setCloudFunction() + }, + methods: { + imgerror(even) { + this.imgSrc = `https://mp-61599c79-d7ee-4a75-a24b-e5a288da6dd3.cdn.bspapp.com/cloudstorage/887c60f0-27f8-46d1-8769-2c45be0f3d7d.png` + }, + setCloudFunction() { + const fileType = this.src.split('.').pop(); + const IMAGE_REGEXP = /(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg|image)/i + if (IMAGE_REGEXP.test(fileType)) { + return this.imgSrc = this.src; + } + + switch (this.cloudType){ + case 'oss': + this.imgSrc = this.src + '?x-oss-process=video/snapshot,t_0,f_jpg' + break; + case 'process': + this.imgSrc = this.src + '?ci-process=snapshot&time=0.01' + break; + case 'vframe': + this.imgSrc = this.src + '?vframe/jpg/offset/0' + break; + default: + this.imgSrc = this.src + break; + } + } + } + } +</script> + +<style lang="scss" scoped> + .image { + width: 100%; + height: 100%; + } +</style> diff --git a/uni_modules/cl-upload/components/cl-upload/cl-upload.vue b/uni_modules/cl-upload/components/cl-upload/cl-upload.vue new file mode 100644 index 0000000..ee28b16 --- /dev/null +++ b/uni_modules/cl-upload/components/cl-upload/cl-upload.vue @@ -0,0 +1,1031 @@ +<template> + <view class="cl-updata"> + <view class="file-list" :style="[listRowStyle]"> + + <view v-for="(item, index) in previewList" @tap="clickSelectedFile(item, index)" class="file-list-row" + :style="[rowStyle]" :key="index"> + + <image + class="_image" + v-if="fileUrlType(item) === 'image'" + :src="item.path" + :style="[imgStyle]" + mode="aspectFill"> + </image> + + <view v-else class="_video" :style="[imgStyle]"> + + <!-- #ifdef MP-WEIXIN || MP-ALIPAY --> + <video + v-if="!autoUpload || cloudType === 'other'" + class="_video" + :style="[imgStyle]" + :src="item.path" + :show-center-play-btn="false" + :show-fullscreen-btn="false" + :show-play-btn="false" + :show-loading="false" + :enable-progress-gesture="false" + :controls="false"> + <view @tap="previewVideo(item, index)" class="play"> + <image style="width: 100%;" :src="playImg" mode="widthFix"></image> + </view> + </video> + + <!-- #endif --> + + <!-- #ifdef APP-PLUS --> + <video + v-if="cloudType === 'other'" + class="_video" + :style="[imgStyle]" + :src="item.path" + :poster="item.path" + :controls="false" + :show-center-play-btn="false" + :show-fullscreen-btn="false" + :show-play-btn="false" + :show-loading="false" + :enable-progress-gesture="false"> + <cover-image class="app_play" :src="playImg" @tap="previewVideo(item, index)"></cover-image> + <cover-view class="remove" v-if="remove" @tap="deleteSelectedFile(item, index)"> + <cover-image class="image" :src="deleteImg" mode="widthFix" @tap="deleteSelectedFile(item, index)"></cover-image> + </cover-view> + </video> + <!-- #endif --> + + <!-- #ifndef MP-WEIXIN || MP-ALIPAY || APP-PLUS --> + <video + v-if="cloudType === 'other'" + class="_video" + :autoplay="false" + :style="[imgStyle]" + :src="item.path" + :controls="false" + :show-center-play-btn="false" + :show-fullscreen-btn="false" + :show-play-btn="false" + :show-loading="false" + :enable-progress-gesture="false" > + <cover-view @tap="previewVideo(item, index)" class="play"> + <cover-image style="width: 100%;" :src="playImg" mode="widthFix"></cover-image> + </cover-view> + </video> + + <!-- #endif --> + + <template v-else> + <cl-image class="pay" :style="[imgStyle]" :cloudType="cloudType" + :src="(item.poster || item.path)"></cl-image> + + <view class="play" @tap="previewVideo(item, index)"> + <image class="play-img" :src="playImg" mode="widthFix"></image> + </view> + </template> + + </view> + + <view class="remove" v-if="remove" @tap.stop="deleteSelectedFile(item, index)"> + <image class="image" :src="deleteImg" mode="widthFix"></image> + </view> + </view> + + <view v-if="add && FileList.length < max" @tap="selectFileTypeOnAdd" :style="[rowStyle]" class="file-list-row"> + <slot name="addImg"> + <div class="add-image"> + <image class="_image" :src="addImg" mode="widthFix"></image> + </div> + </slot> + </view> + </view> + + + <view v-if="tempVideoUrl" class="mask"> + <image @tap="tempVideoUrl = ''" class="_root" :src="closeImg" mode="widthFix"></image> + + <view class="block" @tap.stop> + <video class="block_video" autoplay :src="tempVideoUrl"></video> + </view> + </view> + </view> +</template> + +<script> +import ClImage from '../cl-image/cl-image.vue' +export default { + name: "cl-upload", + components: { ClImage }, + props: { + //������������������ + // #ifdef VUE2 + value: { + type: Array, + default: () => [], + }, + // #endif + + // #ifdef VUE3 + modelValue: { + type: Array, + default: () => [], + }, + // #endif + + // ��������������� oss��������� vframe��������� process��������� other������ + cloudType: { + type: String, + default: 'oss' + }, + // ���������,������������������������ + fileName: { + type: String, + default: 'file' + }, + // ������������ 'image', 'video', 'all' + fileType: { + type: String, + default: 'all' + }, + // ������������������ + imageFormData: { + type: Object | null, + default: () => { } + }, + // ������������������ + videoFromData: { + type: Object, + default: () => { } + }, + + // ������������������������������ + action: { + type: String, + default: '' + }, + + // ������������, ���unicloud��������������� + // https://uniapp.dcloud.net.cn/uniCloud/storage.html#storage-dir + cloudPathAsRealPath: { + type: Boolean, + default: false + }, + + // ��������������������������� + headers: { + type: Object, + default: () => { } + }, + + // ������������������������������ + data: { + type: Object, + default: () => { } + }, + + // ������������������������ + isPreviewImage: { + type: Boolean, + default: true + }, + + // ������������������������������������"default" - ������������������������ "number" - ������������������������ "none" - ��������������������� + indicator: { + type: String, + default: 'none' + }, + // ������������������������������������������ + autoUpload: { + type: Boolean, + default: true + }, + // ������������������������ + remove: { + type: Boolean, + default: true + }, + // ������������������ + add: { + type: Boolean, + default: true + }, + // ������������������ + max: { + type: Number, + default: 9 + }, + // ������������������������ + maxVideo: { + type: Number, + default: 0 + }, + // ������������ + listStyle: { + type: Object, + default: () => { } + }, + // ������������������������ + deleteTitle: { + type: String, + default: '������' + }, + // ������������������������ + deleteText: { + type: String, + default: '������������������������' + }, + // ������������ + loadingText: { + type: String, + default: '���������������...' + }, + // ��������������������������� + useBeforeDelete: { + type: Boolean, + default: false + }, + // ��������������������������� + useBeforeUpload: { + type: Boolean, + default: false + }, + // ������������������ + addImg: { + type: String, + default: 'https://mp-61599c79-d7ee-4a75-a24b-e5a288da6dd3.cdn.bspapp.com/cloudstorage/bb1550b3-e0a8-4a90-a86f-00f8c6afa9fb.png' + }, + // ������������������ + playImg: { + type: String, + default: 'https://mp-61599c79-d7ee-4a75-a24b-e5a288da6dd3.cdn.bspapp.com/cloudstorage/ae40402f-aa53-4344-b553-2322799bebd6.png' + }, + // ������������������ + deleteImg: { + type: String, + default: 'https://mp-61599c79-d7ee-4a75-a24b-e5a288da6dd3.cdn.bspapp.com/cloudstorage/d20177a5-417e-4c5d-a266-1988361c543d.png' + }, + // ������������������������ + closeImg: { + type: String, + default: 'https://mp-61599c79-d7ee-4a75-a24b-e5a288da6dd3.cdn.bspapp.com/cloudstorage/cde4362d-7ec7-4cac-a692-12e1f576be1e.png' + }, + }, + data() { + return { + // ������������ + FileList: [], + + // ������������������ + tempVideoUrl: '', + + // ������������������ + tempFile_paths: [], + + }; + }, + watch: { + // #ifdef VUE2 + 'value': { + handler: function (newVal, oldVal) { + this.FileList = newVal; + }, + deep: true, + immediate: true + }, + // #endif + + // #ifdef VUE3 + 'modelValue': { + handler: function (newVal, oldVal) { + this.FileList = newVal; + }, + deep: true, + immediate: true + }, + // #endif + }, + computed: { + previewList() { + return this.FileList.map(item => { + return { + path: item.path || item, + poster: item.poster || '' + } + }) + }, + listRowStyle() { + const style = { + 'grid-template-columns': `repeat(${this.listStyle?.columns || 4}, 1fr)`, // ������������ + 'grid-column-gap': this.listStyle?.columnGap || '40rpx', // ��������� + 'grid-row-gap': this.listStyle?.rowGap || '40rpx', // ��������� + 'padding': this.listStyle?.padding || '0rpx' // ��������������� + } + + return style; + }, + rowStyle() { + const { height = '140rpx', ratio } = this.listStyle || {}; + const style = { + 'aspect-ratio': height ? '' : ratio || '1/1', // ������������ + 'height': height, + }; + + return style; + }, + + imgStyle() { + const style = { + 'border-radius': this.listStyle?.radius || '6rpx', // ������������ + } + return style; + } + }, + methods: { + /** + * ��������������������� + * @param {object} item ������������ + * @param {number} selectedFileIndex ������������ + * */ + deleteSelectedFile(item, selectedFileIndex) { + + const fileToDelete = this.FileList[selectedFileIndex]; + + // ��������������� + if (this.useBeforeDelete) { + this.$emit('beforeDelete', fileToDelete, selectedFileIndex, () => { + return deleteFileFromList() + }) + } + + if (!this.useBeforeDelete) { + uni.showModal({ + title: this.deleteTitle, + content: this.deleteText, + success: (res) => { + if (res.confirm) { + deleteFileFromList() + } + } + }); + } + + const deleteFileFromList = () => { + const tempFileIndex = this.tempFile_paths.indexOf(item || item.path); + + if (tempFileIndex > -1) { + this.tempFile_paths.splice(tempFileIndex, 1) + } + + this.FileList.splice(selectedFileIndex, 1) + + // #ifdef VUE2 + this.$emit('input', this.FileList) + // #endif + + // #ifdef VUE3 + this.$emit("update:modelValue", this.FileList); + // #endif + } + + }, + + /** + * ��������������������� + * @param {object} item ������������ + * @param {number} index ������������ + * */ + clickSelectedFile(item, index) { + this.previewImage(item?.path ?? item, index); + this.$emit('onImage', { + item, + index + }) + }, + + /** + * ������������������������ + * */ + selectFileTypeOnAdd() { + + switch (this.fileType) { + case 'image': + this.handleFileSelection(1); + break; + case 'video': + this.handleFileSelection(2); + break; + case 'all': + uni.showActionSheet({ + itemList: ['������', '������'], + success: (res) => { + const tapIndex = res.tapIndex; + if (tapIndex === 0) { + this.handleFileSelection(1); + } else { + this.handleFileSelection(2); + } + }, + fail: (res) => { + console.error(res.errMsg); + } + }); + break; + default: + this.handleFileSelection(1); + break; + } + }, + + + /** + * ������������������������ + * @param { number } updataType ������������ 1:������ 2������ + * */ + async handleFileSelection(updataType) { + const that = this; + if (updataType === 1) { + + const data = Object.assign({}, { + // ������������������������������������������9 + count: 9, + // ������ mediaType ��� image ������������������������������������ + // #ifndef MP-TOUTIAO + sizeType: ['original', 'compressed'], + // #endif + // album ������������������camera ������������������������������������ + sourceType: ['camera', 'album'], + + compress: false + }, this.imageFormData) + + data['count'] = this.max - this.FileList.length + + uni.chooseImage({ + ...data, + success: async (res) => { + let tempFiles = res.tempFiles + const compress = that.imageFormData?.compress || false; + + // ������������������������ + if (that.imageFormData?.size ?? false) { + const maxSize = that.imageFormData.size * 1024 * 1024 + + tempFiles.map((imgInfo, index) => { + if (imgInfo.size > maxSize) { + tempFiles.splice(index, 1) + that.$emit('onImageSize', imgInfo) + return uni.showToast({ + title: `������������������${that.imageFormData.size}MB`, + duration: 2000, + icon: 'none' + }); + } + }) + } + + // ������������������ + if (compress) { + const compressedImagePathList = tempFiles.map(imageItem => { + return that.compressImage(imageItem.path) + }) + + Promise.all(compressedImagePathList).then(result => { + upload(result); + }) + + } else { + upload(tempFiles); + } + + function upload(tempImages) { + if (that.autoUpload) { + tempImages.map(item => { + that.onBeforeUploadFile(item, 'image') + }) + } else { + that.FileList = [...that.FileList, ...tempImages] + tempImages.map(item => { + that.tempFile_paths.push(item) + }) + } + } + + }, + fail(err) { + console.error('������������������', err) + that.$emit('onError', err) + } + + }) + } + + if (updataType === 2) { + + // ������������������������������ + const VIDEO_REGEXP = /\.(mp4|flv|avi)/i + const videoList = await that.FileList.filter(item => { + const fileUrl = item?.url ?? item + return VIDEO_REGEXP.test(fileUrl) + }) + + if (that.maxVideo > 0 && videoList.length >= that.maxVideo) { + that.$emit('onVideoMax', that.maxVideo, videoList.length) + return uni.showToast({ + title: '���������������������', + duration: 2000, + icon: 'none' + }); + } + + const data = Object.assign({}, { + // ��������������������������������������������������������� 60 ������ + maxDuration: 60, + // #ifndef MP-TOUTIAO + // 'front'���'back'���������'back' + camera: "back", + // #endif + + // album ���������������������camera ������������������������������������������ + sourceType: ['camera', 'album'], + // ��������������������������������������������������� true������������������ + compressed: true, + // 'front'���'back'���������'back' + }, this.videoFromData) + + uni.chooseVideo({ + ...data, + success: (res) => { + let tempFilePath = { ...res } + tempFilePath['path'] = res.tempFilePath + + // ������������������������ + if (that.videoFromData?.size ?? false) { + const maxSize = that.videoFromData.size * 1024 * 1024 + + if (tempFilePath.size > maxSize) { + uni.showToast({ + title: `������������������${that.videoFromData.size}MB`, + duration: 2000, + icon: 'none' + }); + return false; + } + + } + if (that.autoUpload) { + that.onBeforeUploadFile(tempFilePath, 'video') + } else { + that.FileList.push(tempFilePath) + that.tempFile_paths.push(tempFilePath) + } + }, + fail(err) { + console.error('������������������', err) + } + + }) + } + }, + + /** + * ��������������� + * @param { tempFile } ������������ + * @return { Promise } + * */ + onBeforeUploadFile(tempFile) { + if (this.useBeforeUpload) { + return this.$emit('beforeUpload', tempFile, () => { + return this.updataFile(tempFile); + }) + } + return this.updataFile(tempFile); + }, + + /** + * ������������������������ + * @param { tempFile } ������������ + * @return { Promise } + * */ + updataFile(tempFile) { + const that = this; + const filePath = tempFile.path || tempFile; + const fileType = this.fileUrlType(filePath) == 'image' ? '.png' : '.mp4'; + const fileName = tempFile.name || Date.now() + fileType; + + uni.showLoading({ + title: this.loadingText, + icon: 'loading' + }) + + return new Promise((resolve, reject) => { + // uniCloud������ + if (that.action === 'uniCloud') { + + uniCloud.uploadFile({ + cloudPath: String(fileName), + filePath: filePath, + // #ifdef MP-ALIPAY + fileType: fileType, + // #endif + cloudPathAsRealPath: this.cloudPathAsRealPath, + + onUploadProgress: (progressEvent) => { + const percentCompleted = Math.round( + (progressEvent.loaded * 100) / progressEvent.total + ); + that.$emit('onProgress', percentCompleted) + }, + success(result) { + if (that.autoUpload) { + that.FileList.push(result.fileID) + } else { + that.FileList.map((item, index) => { + if (item === filePath || item.path === filePath) { + that.FileList.splice(index, 1, result.fileID) + } + }) + } + + // #ifdef VUE2 + that.$emit('input', that.FileList) + // #endif + // #ifdef VUE3 + that.$emit("update:modelValue", that.FileList); + // #endif + + resolve(result.fileID) + uni.hideLoading(); + that.$emit('onProgress', { + ...result + }) + }, + fail: (error) => { + uni.hideLoading(); + console.error('error', error); + that.$emit('onError', error) + reject(error) + } + }) + return false; + } + + // ������������������ + const uploadTask = uni.uploadFile({ + url: that.action, + filePath: filePath, + name: that.fileName, + formData: that.data, + header: that.headers, + // #ifdef MP-ALIPAY + fileType: filetype, + // #endif + success: (uploadFileRes) => { + const data = JSON.parse(uploadFileRes.data) + uni.hideLoading(); + that.success(data) + + if (!this.autoUpload) { + that.FileList.map((item, index) => { + if (item === filePath || item.path === filePath) { + that.FileList.splice(index, 1) + } + }) + } + + resolve(data) + }, + fail: (error) => { + uni.hideLoading(); + console.error('error', error); + that.$emit('onError', error) + reject(error) + } + }); + + uploadTask.onProgressUpdate((res) => { + that.$emit('onProgress', { + ...res, + ...tempFile + }) + }); + }) + }, + + /** + * ������������ + * */ + submit() { + + return new Promise((resolve, reject) => { + if (this.tempFile_paths.length <= 0) { + resolve([]) + } + + const uploadedFilePaths = this.tempFile_paths.map(item => { + return this.onBeforeUploadFile(item || item.path) + }) + + Promise.all(uploadedFilePaths).then(res => { + this.tempFile_paths = [] + resolve(res) + }).catch(err => { + reject(err) + }) + }) + + }, + + /** + * ������������ + * @param {array} data ������������������������ + * @return {array} ������������ + * */ + success(data) { + this.$emit('onSuccess', data); + + // ���������������������-��������������� + // const list = data.map(item=> { + // return JSON.parse(item).data.link; + // }) + // this.$emit('input', [...this.FileList, ...list]); + }, + /** + * ������������ + * @param {array} tempFilePaths ������������������ + * @return {array} ��������������������������� + * */ + async compressImage(tempFilePaths) { + const that = this; + + return new Promise((resolve, reject) => { + + if (typeof tempFilePaths !== 'string') { + console.error('������������������') + reject([]) + } + + uni.showLoading({ + title: '���������...', + icon: 'loading', + }) + + // #ifdef H5 + this.canvasDataURL(tempFilePaths, { + quality: that.imageFormData.quality / 100 + }, (base64Codes) => { + resolve(base64Codes); + uni.hideLoading(); + }) + // #endif + + // #ifndef H5 + uni.compressImage({ + src: tempFilePaths, + quality: that.imageFormData.quality || 80, + success: res => { + resolve(res.tempFilePath); + uni.hideLoading(); + }, + fail(err) { + reject(err); + uni.hideLoading(); + } + }) + // #endif + + }) + }, + + /** + * H5������������������ + * @param {string} path ������������ + * @param {object} obj ������������ + * @param {function} callback ������������ + * @return {string} base64 + * */ + canvasDataURL(path, obj, callback) { + var img = new Image(); + img.src = path; + img.onload = function () { + var that = this; + // ��������������������� + var w = that.width, + h = that.height, + scale = w / h; + w = obj.width || w; + h = obj.height || (w / scale); + var quality = 0.8; // ���������������������0.8 + //������canvas + var canvas = document.createElement('canvas'); + var ctx = canvas.getContext('2d'); + // ������������������ + var anw = document.createAttribute("width"); + anw.nodeValue = w; + var anh = document.createAttribute("height"); + anh.nodeValue = h; + canvas.setAttributeNode(anw); + canvas.setAttributeNode(anh); + ctx.drawImage(that, 0, 0, w, h); + // ������������ + if (obj.quality && obj.quality <= 1 && obj.quality > 0) { + quality = obj.quality; + } + // quality������������������������������������������ + var base64 = canvas.toDataURL('image/jpeg', quality); + // ������������������base64������ + callback(base64); + } + }, + + /** + * ������������ + * @param {string, object} item ������������ + * */ + previewImage(item) { + if (this.fileUrlType(item) === 'video') return false; + if (!this.isPreviewImage) return false; + + const imgs = this.FileList.filter(item => { + return this.fileUrlType(item) !== 'video' + }).map(item => item?.path ?? item) + const current = imgs.indexOf(item || item.path); + + uni.previewImage({ + current: current, + urls: imgs, + success() { + }, + fail(err) { + console.log(err); + } + }) + }, + + /** + * ������������ + * @param {string, object} item ������������ + * @param {number} index ������ + * */ + previewVideo(item, index) { + this.$emit('onVideo', { + item, + index + }) + this.tempVideoUrl = item.path; + }, + + /** + * ������img������ + * @param {string, object} item ������������ + * @return {boolean} ������img������ + * */ + fileUrlType(file) { + const filePath = file.path || file; + + if (this.isBase64(filePath)) return 'image' + + const fileType = filePath.split('.').pop(); + + const IMAGE_REGEXP = /(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg|image)/i + if (IMAGE_REGEXP.test(fileType)) { + return 'image'; + } else { + return 'video'; + } + }, + // ���������������base64 + isBase64(str) { + if (str === '' || typeof str !== 'string') return console.error('������������������, base64', str); + return str.includes('blob:') || str.includes('data:image'); + } + } +} +</script> + +<style lang="scss" scoped> +.cl-updata { + + .file-list { + display: grid; + + &-row { + display: inline-flex; + align-items: center; + position: relative; + + .play-img { + width: 100%; + } + + ._image { + height: 100%; + width: 100%; + } + + ._video { + position: relative; + width: 100%; + height: 100%; + overflow: hidden; + } + + .video-fixed { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 100%; + height: 100%; + border-radius: 10rpx; + z-index: 96; + } + + .play { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 30%; + z-index: 95; + } + + .app_play { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 50rpx; + height: 50rpx; + } + + .remove { + position: absolute; + top: 0; + right: 0; + background-color: #373737; + height: 50rpx; + width: 50rpx; + border-bottom-left-radius: 200rpx; + z-index: 97; + + .image { + width: 20rpx; + height: 20rpx; + position: absolute; + right: 12rpx; + top: 12rpx; + } + } + } + + .add-image { + display: flex; + align-items: center; + justify-content: center; + border: 2rpx dashed #ccc; + width: 100%; + height: 100%; + border-radius: 5rpx; + + &:active { + opacity: 0.8; + } + + ._image { + width: 40%; + } + } + } + + .mask { + background-color: #000; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 99; + + .block { + padding: 0 30rpx; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 100%; + + .block_video { + width: 100%; + height: 78vh; + } + } + + ._root { + width: 60rpx; + height: 60rpx; + position: absolute; + left: 40rpx; + top: 5vh + } + } +} +</style> diff --git a/uni_modules/cl-upload/package.json b/uni_modules/cl-upload/package.json new file mode 100644 index 0000000..a8e3a0d --- /dev/null +++ b/uni_modules/cl-upload/package.json @@ -0,0 +1,82 @@ +{ + "id": "cl-upload", + "displayName": "��������������������� ���������������������������������������uniCloud������ ���������", + "version": "1.4.0", + "description": "������������������������������������������������������������������uniCloud���������������������������������", + "keywords": [ + "������������������������������������������������", + "uniCloud������" +], + "repository": "", + "engines": { + "HBuilderX": "^3.5.3" + }, + "dcloudext": { + "type": "component-vue", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "���", + "data": "���", + "permissions": "���" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "Vue": { + "vue2": "y", + "vue3": "y" + }, + "App": { + "app-vue": "u", + "app-nvue": "u" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "���������������(Android)": "y", + "QQ���������(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "���������": { + "������": "y", + "������": "y", + "������": "u", + "������������": "y", + "QQ": "u", + "������": "u", + "������": "u", + "������": "u", + "������": "u" + }, + "���������": { + "������": "u", + "������": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/cl-upload/readme.md b/uni_modules/cl-upload/readme.md new file mode 100644 index 0000000..528b5f2 --- /dev/null +++ b/uni_modules/cl-upload/readme.md @@ -0,0 +1,253 @@ +### cl-upload ������������ + +> ��������������������������������������������������������������������������������� + + +> `���������������������������������������������������������������������������������������������������������������������,���������������������������������������������������������������������������������������������promise������ ������������` + +### ������������ +1. ratio ���������������������������������������������������height������������ +2. ������������������������������������������������������������������������ +3. ������������������������������������������������������������api������������������������������������������������������������������������������ +4. **������������������`https`, http���������������������������������** +5. ������������������`https`������������`cloudType: other` + +### H5������������ + + +#### list������������ + +1. ������������ +``` +['������1','������2'] +``` +2. JSON������ +``` +[ + { + path: '������1.png', + // ������������ + }, + { + path: '������2.mp4', + poster: '���������������.png' + // ������������ + }, + { + path: '������3.mp4', + poster: require('../../static/c1.png'), // ������������������������������ + // ������������ + }, +] +``` + +#### ������������ + +``` +<cl-upload v-model="list" action="������������" @onSuccess="onSuccess"></cl-upload> + +methods: { + /** + * ������������������������������������������ + * ��������������������������������������������������������������� + * */ + onSuccess(reslut) { + // ������������������������������������������list������������������������ + this.list.push(reslut.url) + }, +} +``` +### uniCloud������ +> ������������������������,������������������ + +``` +<cl-upload v-model="list" action="uniCloud"></cl-upload> +``` + +### ��������������� +> ������ listStyle ������������������������������������������������������������������ + +``` +<cl-upload v-model="list" :listStyle="{ + columns: 2, + columnGap: '20rpx', + rowGap:'20rpx', + padding:'10rpx', + height:'300rpx', + radius:'20rpx' +}"> + <template v-slot:addImg> + <view class="newAddImg"> + <view>���</view> + <text >������</text> + </view> + </template> +</cl-upload> +``` + +### ������������ +> ��������������������������������������� +``` +<cl-upload v-model="list" :add="false" :remove="false"></cl-upload> +``` + +### ������������ + +> ������ autoUpload ��������������������������������������������� refs ������������������������������������������������������������������������������ + +``` +<cl-upload + ref="upload2" + v-model="list2" + :autoUpload="false"></cl-upload> + +<button @tap="submit">������������</button> + +methods: { + submit() { + /** + * ������������������������������ + * */ + this.$refs.upload2.submit().then(reslut=>{ + console.log(reslut); // ��������������������������������������� + + // ������������������������������������������������ + // ������uniCloud������������ + const imgUrls = reslut.list.map(imgInfo=> imgInfo.url); + this.list2 = [...this.list2, ...imgUrls] + }) + }, +} +``` + +### ��������������������������������� +``` +/ ** +* ��������������������� useBeforeDelete +* ��������������������� useBeforeUpload +*/ +<cl-upload v-model="list" + useBeforeDelete + useBeforeUpload + @beforeDelete="beforeDelete" + @beforeUpload="beforeUpload"></cl-upload> + + +methods: { + /** + * ��������������� + * @param {Object} item ��������������������������������������� + * @param {Number} index ������������������������������������ + * @param {Function} next ��������������������������������������������� + * */ + beforeDelete(item, index, next) { + uni.showModal({ + title: '������������', + content: '���������������������������������', + success: res => { + if (res.confirm) { + // ��������������������� + setTimeout(() => { + next(); + }, 1000); + } + } + }); + }, + /** + * ��������������� + * @param {Object} tempFile ������������������������ + * @param {Function} next ��������������������������������������������� + * */ + beforeUpload(tempFile, next) { + // ��������������������� + // ������������������������������������������������������next(), ���������������������������list + } +} +``` + +## API + +| ������ | ������ | ������ | ��������� | ��������� | +| --- | --- | --- | --- | --- | +| action | ������������ | String |-| uniCloud | +| cloudPathAsRealPath | ������������, ���unicloud���������������`1.4.0` `HBuilderX 3.8.5` | Boolean |false| true | +| cloudType | ���������������(������������������������������������������ other���������video������������,������������������������������) | String |oss| ���������:oss ���������:vframe ���������:process ������:other | +| headers | ��������������������������� | Object | - |- | +| data | ������������������������������ | Object | - | - | +| fileName| ���������,������������������������ | String | file | - | +| fileType | ������������ | String | all | 'image', 'video', 'all' | +| imageFormData | ������������������ | Object | - | - | +| videoFromData | ������������������ | Object | - | - | +| listStyle | ������������ |Object | - | - | +| isPreviewImage | ������������������������ | Boolean | true |false | +| remove | ������������������������ | Boolean | true |false | +| add | ������������������ | Boolean | true |false | +| max | ������������������ | Number | 9 | - | +| maxVideo | ������������������������ | Number | ��������� | - | +| deleteTitle| ������������������������ | String | ������ | - | +| deleteText| ������������������������ | String | ������������������������ | - | +| loadingText| ������������ | String | ���������������... | - | +| useBeforeDelete| ��������������������������� | Boolean | false | true | +| useBeforeUpload | ��������������������������� | Boolean | false | true | +| addImg| ������������������ | String | - | - | +| playImg| ������������������ | String | - | - | +| deleteImg| ������������������ | String | - | - | +| closeImg| ������������������������ | String | - | - | + +#### imageFormData + +| ������ | ������ | ������ | ��������� | ��������� | +| --- | --- | --- | --- | --- | +| count | ��������������������������������� | number |9| - | +| sizeType | original ���������compressed ��������� | array | ������������������ |- | +| sourceType | ������������������ | array | ['camera ', 'album'] | ['camera ', 'album'] | +| compress | ������������������������ | Boolean | false | true | +| quality | ������������ | number | 80 | - | +| size | ������������ | number | - | ������MB | + +#### videoFromData + +| ������ | ������ | ������ | ��������� | ��������� | +| --- | --- | --- | --- | --- | +| maxDuration | ������������������������������ | number |60| ������60��� | +| camera | ������������������������ | array | - |- | +| compressed | ��������������������������������������� | Boolean | true |- | +| sourceType | ������������������ | array | ['camera ', 'album'] | ['camera ', 'album'] | +| size | ������������ | number | - | ������MB | + +#### listStyle + +| ������ | ������ | ������ | ��������� | ��������� | +| --- | --- | --- | --- | --- | +| columns | ������������ | number |4| - | +| columnGap | ��������� | string | '40rpx' |- | +| rowGap | ��������� | string | '40rpx' |- | +| padding | ��������������� | string | '0 0rpx' |- | +| ratio | ������������ | string | '1/1' | ������������������������,������������height������ | +| height | ������������ | string | '140rpx' |- | +| radius | ������������ | string | '6rpx' |- | + +#### Events + +| ��������� | ������ | ������������ | +| --- | --- | --- | +| onSuccess | ������������ | data: ��������������������� | +| onError | ������������ | error:������������ | +| onImage | ������������ | item: ������������ index: ������������ | +| onVideo | ������������ | item: ������������ index: ������������ | +| onProgress | ������������ | onProgress������������| +| onVideoMax | ������������������������������ | maxVideo, fileLength| +| onImageSize | ������������������������������ | ������������ | +| beforeDelete | ��������������� | item: ������������ index:������������ next:������������������������ | +| beforeUpload | ��������������� | tempFile: ������������ next:������������������������ | + +#### onProgress������������ +| ��������� | ������ | +| --- | --- | +| progress | ��������������������� | +| totalBytesSent | ��������������������������� | +| totalBytesExpectedToSend | ������������������������������������ | + + +### [������������������������ uniapp ������QQ��� 553291781](https://jq.qq.com/?_wv=1027&k=5UkMN1QX) \ No newline at end of file diff --git a/uni_modules/uview-ui/LICENSE b/uni_modules/uview-ui/LICENSE new file mode 100644 index 0000000..4db40ef --- /dev/null +++ b/uni_modules/uview-ui/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 www.uviewui.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/uni_modules/uview-ui/README.md b/uni_modules/uview-ui/README.md new file mode 100644 index 0000000..c78ff47 --- /dev/null +++ b/uni_modules/uview-ui/README.md @@ -0,0 +1,66 @@ +<p align="center"> + <img alt="logo" src="https://uviewui.com/common/logo.png" width="120" height="120" style="margin-bottom: 10px;"> +</p> +<h3 align="center" style="margin: 30px 0 30px;font-weight: bold;font-size:40px;">uView 2.0</h3> +<h3 align="center">������������������������UI������</h3> + +[](https://github.com/umicro/uView2.0) +[](https://github.com/umicro/uView2.0) +[](https://github.com/umicro/uView2.0/issues) +[](https://uviewui.com) +[](https://gitee.com/umicro/uView2.0/releases) +[](https://en.wikipedia.org/wiki/MIT_License) + +## ������ + +uView UI������[uni-app](https://uniapp.dcloud.io/)������������nvue���uni-app������������������������������������������������������������������������������������ + +## [���������������https://uviewui.com](https://uviewui.com) + + +## ������ + +���������������**������**��������������������������������������� +<br> +<br> +<img src="https://uviewui.com/common/weixin_mini_qrcode.png" width="220" height="220" > + + +## ������ + +- [������������](https://www.uviewui.com/) +- [������������](https://www.uviewui.com/components/changelog.html) +- [������������](https://www.uviewui.com/components/changeGuide.html) +- [������������](https://www.uviewui.com/cooperation/about.html) + +## ������������ + +���������������������QQ������������������[������������](https://www.uviewui.com/components/addQQGroup.html) + +## ������PR + +> ���������������������������������������PR������������������������������������uView2.0���������������������������������������������������h5���ios app���android app���������nvue���������vue��������� +> ������������������������bug������������������������������������������������������������������������������������������������������������������������������ + +## ������ + +#### **uni-app������������������** ������ [https://ext.dcloud.net.cn/plugin?id=1593](https://ext.dcloud.net.cn/plugin?id=1593) + +���������[������������������](https://www.uviewui.com/components/install.html)������������������������ + +## ������������ + +���������[������������](https://uviewui.com/components/quickstart.html)������������������������ + +## ������������ +������easycom���������������������������������������`import`������������������������������ + +```html +<template> + <u-button text="������"></u-button> +</template> +``` + +## ������������ +uView������[MIT](https://en.wikipedia.org/wiki/MIT_License)���������������������������������������������������������������������������������uView��������������������������� + diff --git a/uni_modules/uview-ui/changelog.md b/uni_modules/uview-ui/changelog.md new file mode 100644 index 0000000..f2bae72 --- /dev/null +++ b/uni_modules/uview-ui/changelog.md @@ -0,0 +1,362 @@ +## 2.0.36���2023-03-27��� +# uView2.0������������������������������������������ + +1. ������`deepClone` & `deepMerge`������ +2. ������������ +## 2.0.34���2022-09-24��� +# uView2.0������������������������������������������ + +1. `u-input`���`u-textarea`������`ignoreCompositionEvent`������ +2. ������`route`��������������������������������� +3. ������`u-no-network`������`z-index`��������������� +4. ������`textarea`���������h5���confirmType=""��������������� +5. `u-rate`������`nvue` +6. ������������������������������������������(���������������������������������������������������2017���������������������������) +7. `form-item`������`labelPosition`������ +8. `u-calendar`������`maxDate`������������������������������������������������08���00������������������������������������ (#724) +9. `u-radio`���������������������������������������������label������ (#680) +10. ������`timeFormat`���������safari��������������������� (#664) +## 2.0.33���2022-06-17��� +# uView2.0������������������������������������������ + +1. ������`loadmore`������`lineColor`������������������ +2. ������`u-parse`������`imgtap`���`linktap`��������������� +## 2.0.32���2022-06-16��� +# uView2.0������������������������������������������ +1. `u-loadmore`���������������������������/������ +2. ������`u-swiper-action`��������������������������������������������� +3. ������`u-list`������������ +4. ������`notice-bar`������������������������������������������������������ +5. `u-loading-page`���������������������������������`iconSize` +6. ������`u-tooltip`������`color`������������������������ +7. ������`u--input`������������`blur`���������������`undefined`���bug +8. `u-code-input`������������������������������������������������������������`adjustPosition` +9. ������`image`������`load`��������������������������� +10. ������`button`������`loadingSize`������������������ +10. ������������ +## 2.0.31���2022-04-19��� +# uView2.0������������������������������������������ + +1. ������`upload`���`vue`������������������������������������������������ +2. ��������������������������������������������������������������������������������� +3. ������`u-code-input`���������`nvue`���������������`app`������������������������������`app`������������������ +4. ������`actionSheet`��������������������������������������������������������� +5. ������������ +## 2.0.30���2022-04-04��� +# uView2.0������������������������������������������ + +1. `u-rate`������`readonly`������ +2. `tabs`������������������������������ +3. ������`u-subsection` `mode`���`subsection`������������������������������������ +4. `u-code-input`������������������������ +5. ������`popup`���`open`��������������� +6. ������`u-flex-column`��������������� +7. ������`u-datetime-picker`��������������������������������� +8. ������`u-datetime-picker`��������������������������������������� +9. `u-swiper`������`m3u8`������ +10. `u-swiper`������������image���video������ +11. ������`swiper`���������������������������������������`type`������ +12. ������`u-row-notice`������������������ +13. ������`u-switch`���������`unit`���`rpx`���,`nodeStyle`��������������� +14. ������`datetime-picker`������`showToolbar`���`visibleItemCount`��������������������� +15. ������`upload`���������������������������������������������`previewImage`���������������`false`������������������������������������������ +16. ������`u-checkbox-group`������`shape`��������������������� +17. ������`u-upload`���`capture`������������������������������������������ +18. ������`u-action-sheet`������������������������������������������ +19. ������`u-list`������������������������������������ +20. ������`u-text`��������������������������������� +21. ������`u-textarea`��������������������� +22. ������������ +## 2.0.29���2022-03-13��� +# uView2.0������������������������������������������ + +1. ������`u--text`������������`decoration`������������������������ +2. ������`u-datetime-picker`������`formatter`��������������������� +3. ������`u-datetime-picker` `intercept` ���������undefined +4. ��������������������� uni..config.unit = 'rpx'��������������������� `transform` ��������������������������������������������� +5. ������mixin���bem������������������������������������������������������������ +6. ���������������������������������������������`u-datetime-picker`���������������������������������������bug +7. ������`u-datetime-picker`������`formatter`��������������������� +8. ������`u-image`������`loading`������������������ +9. ������`config.unit`������������`rpx`������������������������������������������������������ +10. ������`u-datetime-picker`������`itemHeight`������������ +11. ������������ +## 2.0.28���2022-02-22��� +# uView2.0������������������������������������������ + +1. search������������searchIconSize������ +2. ������Safari/Webkit������������������������2022-02-17 12:00:56 +3. ������text value.js ���������������format������������ +4. priceFormat��������������������������������� +5. priceFormat������������������������������������������ +6. ������������rules������ +7. ������avatar������src������������������������������ +8. ������������ +## 2.0.27���2022-01-28��� +# uView2.0������������������������������������������ + +1.������������ +## 2.0.26���2022-01-28��� +# uView2.0������������������������������������������ + +1.������������ +## 2.0.25���2022-01-27��� +# uView2.0������������������������������������������ + +1. ������text������mode=price������������������������������������������ +2. ������$u.setConfig()������������������uView���������config, props, zIndex, color������������������[������uView������������������](https://uviewui.com/components/setting.html#%E9%BB%98%E8%AE%A4%E5%8D%95%E4%BD%8D%E9%85%8D%E7%BD%AE) +3. ������form���������errorType=toast��������������������������������������������������� +4. ������$u.addUnit()������������������������������������������ +## 2.0.24���2022-01-25��� +# uView2.0������������������������������������������ + +1. ������swiper���current���������0��������������� +2. ������u-icon������stop��������������������� +3. ���������������������������������rpx��������������� +4. ������Layout������ vue������gutter��������������������������� +5. ������search���������������������������rpx -> px��� +6. ������u-image slot ��������������������������������������� +7. ������u-index-list���footer���������header��������������������������� +8. ���������������������u-popup������������������ +9. ������u-image���nvue-app��������������� +10. ������u-popup������������ +11. ������u-tooltip������ +12. ������box-sizing���app������������ +13. ������u-navbar��������������������������������� +14. ������������ +## 2.0.23���2022-01-24��� +# uView2.0������������������������������������������ + +1. ������image���������hx3.3.9���nvue��������������������������������� +2. ������col������gutter���������rpx������������������������������ +3. ������text��������������������������������������������� +4. navbar������titleStyle������ +5. ���������hx3.3.9���������nvue��������������������������������� +## 2.0.22���2022-01-19��� +# uView2.0������������������������������������������ + +1. $u.page()��������������������������������������������������������� +2. picker������������immediateChange������ +3. ������$u.pages()������ +## 2.0.21���2022-01-19��� +# uView2.0������������������������������������������ + +1. ���������form���������������������rules���������������������model������ +2. ���������������������������������rpx��������������� +3. ������������������������������tabbar������������safeAreaInsetBottom������������placeholder��������������������� +4. ������swiper���current���������0��������������� +5. ������u-icon������stop��������������������� +6. ������upload���������accept=all��������������������� +7. ���������text������mode���phone���call��������������������� +8. ������u-form clearValidate������ +9. ������������ +## 2.0.20���2022-01-14��� +# uView2.0������������������������������������������ + +1. ������calendar������������������������������������������������������������������������������������ +2. ������Slider������disabled props ������������ +3. ������u-notice-bar������������������������index������������������ +4. ������u-collapse-item���vue������������app������������������������������������ +5. ��������������������������������������� +6. ������������������������������������������������������������ +7. ��������������������������������������������� +8. search������������������������icon������ +9. ������u-form clearValidate��������������� +10. upload h5���������������������������������������name��������� +11. ������upload���������������url���blob��������������������������� +12. u-code-input ��������������������������������������������� +13. ������Upload������ disabled���true������������������hoverClass������������ +14. ������������ios app���grid������������������ +15. ������������ +## 2.0.19���2021-12-29��� +# uView2.0������������������������������������������ + +1. ���������������������������������������������������������������HbuilderX3.3.4���������������������->������������������������������������������������������������������������ +2. ���������������������setData������������������������������$u.route()��������������������������������� +3. navbar������autoBack������ +4. ������avatar��������������������� +5. ������cell������������������ +6. ������������ +## 2.0.18���2021-12-28��� +# uView2.0������������������������������������������ + +1. ������app��������������������� +2. ������������������������������setData��������������������� +3. ������������������ +4. ���������������������������������0������������������������������ +5. ������SwipeAction������������������������������������������ +6. ������input���placeholder������������������������������true������ +7. ������divider������click������������������ +8. ������u-code-input maxlength ������������ String ��������������������� +9. ��������� grid������ 1���2��� ���������������algin��������������������� +10. ������form-item���label���top������������������������������������ +11. ������������ +## 2.0.17���2021-12-26��� +## uView���������������������������������������������������������������������������������������������������������������������������������[������������uView](https://www.oschina.net/project/top_cn_2021/?id=583) + +# uView2.0������������������������������������������ + +1. ������HBuilderX3.3.3.20211225��������������������������� +2. calendar������������monthNum������ +3. navbar������center slot +## 2.0.16���2021-12-25��� +## uView���������������������������������������������������������������������������������������������������������������������������������[������������uView](https://www.oschina.net/project/top_cn_2021/?id=583) + +# uView2.0������������������������������������������ + +1. ���������������������setData������������ +2. ������count-down������change��������������������� +## 2.0.15���2021-12-21��� +## uView���������������������������������������������������������������������������������������������������������������������������������[������������uView](https://www.oschina.net/project/top_cn_2021/?id=583) + +# uView2.0������������������������������������������ + +1. ������Cell���������titleWidth������ +2. ������cheakbox������ischecked��������� +3. ������keyboard������������"."��������������������� +4. ������number-keyboard���������������������"."������������ +5. ������Input��������� readonly������ +6. ������u-avatar ������������app���H5������������������ +7. ������Upload������deletable������ +8. ������upload���������maxSize������������������ +9. ������tabs lineWidth��������������������������������������������������������������� +10. ������rate������������padding���view��������������������������������������������������������������������������������� +## 2.0.13���2021-12-14��� +## [���������������������������364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY) + +# uView2.0������������������������������������������ + +1. ���������������������������rpx������������������������������������������������������ +## 2.0.12���2021-12-14��� +## [���������������������������364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY) + +# uView2.0������������������������������������������ + +1. ������tabs���������vue������������������������������ +2. ������upload��������������������������������������������������� +3. ������uni.$u.config.unit���������������������������������������������������[������������������](https://www.uviewui.com/components/setting.html#%E9%BB%98%E8%AE%A4%E5%8D%95%E4%BD%8D%E9%85%8D%E7%BD%AE) +4. ������textarea������������������v-model��������������������������������� +5. ������nvue������������������������������������������ +## 2.0.11���2021-12-13��� +## [���������������������������364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY) + +# uView2.0������������������������������������������ + +1. text������align��������������������� +2. subsection������������keyName������ +3. upload������������������[Object file]��������������� +4. ������notify������������������ +5. codeInput������������disabledDot������ +6. ������actionSheet������round��������������������� +7. calendar������������round��������������������������� +8. ������swipeAction���������vue��������������������������������� +9. button���������throttleTime��������������������������� +10. ������u-notify������������������close()��������������� +11. input������readonly��������������� +12. tag������type���������info��������������� +## 2.0.10���2021-12-08��� +## [���������������������������364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY) + +# uView2.0������������������������������������������ + +1. ������button sendMessagePath��������������� +2. ������DatetimePicker���������title������ +3. ������u-toast������loading=true��������� +4. ������u-text���������������0������ +5. ������u-toast���������icon��������������������� +6. button���icon��������������������������������� +7. IndexList���������������# +## 2.0.9���2021-12-01��� +## [���������������������������232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU) + +# uView2.0������������������������������������������ + +1. ������swiper���height������100%���(���vue������)������������������������click��������������������������� +2. ������tabs���������list���������������������������������������list������������������������������������ +3. ������datetime-picker������������������������������������������������������������������������������������v-model������������������ +4. ������upload������������������������������������������������������������������ +## 2.0.8���2021-12-01��� +## [���������������������������232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU) + +# uView2.0������������������������������������������ + +1. ������toast���position������������������ +2. ������input���ios nvue������������������������������ +3. avatar-group������������extraValue��������������������������������������������� +4. tabs������������keyName��������������������������������������������� +5. ������text��������������������������������������������� +6. ������picker������item������������������������ +## 2.0.7���2021-11-30��� +## [���������������������������232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU) + +# uView2.0������������������������������������������ + +1. ������radio���checkbox������������v-model������������������ +2. ������form������validator������������������������ +3. ������backtop������mode��������������������������������������� +4. ������Album���previewFullImage��������������������� +5. ������u-datetime-picker������mode='time'��������������������������������������������������� +## 2.0.6���2021-11-27��� +## [���������������������������232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU) + +# uView2.0������������������������������������������ + +1. ������tag���������vue��������������������������� +2. ������popup������������������������������������������ +3. ������tabs������lineColor������������������������������ +4. propgress������������������������������������������������ +## 2.0.5���2021-11-25��� +## [���������������������������232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU) + +# uView2.0������������������������������������������ + +1. calendar���vue������������������������ +2. form������labelPosition���errorType��������������������� +3. input������inputAlign��������������� +4. ������������������ +## 2.0.4���2021-11-23��� +## [���������������������������232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU) + +# uView2.0������������������������������������������ + +0. input������������@confirm���������������subfix���prefix������������ +1. component.scss���������������vue��������������������������� +2. ������subsection���vue������������������������������ +3. tag���������bgColor������������������������ +4. upload������������������������ +5. ��������������������������� +## 2.0.3���2021-11-16��� +## [���������������������������1129077272](https://jq.qq.com/?_wv=1027&k=KnbeceDU) + +# uView2.0������������������������������������������ + +1. uView2.0���������������������nvue +2. uView2.0���1.x��������������������������������������������������������� +3. ������uView2.0������������������������������������������������ +4. ���������������������1.x������������������������[������1.x](https://www.uviewui.com/components/diff1.x.html) +5. ������modal���confirm������������������������������ +6. ������input������@input������������������������ +7. ������������������ +## 2.0.2���2021-11-16��� +## [���������������������������1129077272](https://jq.qq.com/?_wv=1027&k=KnbeceDU) + +# uView2.0������������������������������������������ + +1. uView2.0���������������������nvue +2. uView2.0���1.x��������������������������������������������������������� +3. ������uView2.0������������������������������������������������ +4. ���������������������1.x������������������������[������1.x](https://www.uviewui.com/components/diff1.x.html) +5. ������input������formatter������������������ +6. ������loading-icon���������scss���������������������������������������scss +## 2.0.0(2020-11-15) +## [���������������������������1129077272](https://jq.qq.com/?_wv=1027&k=KnbeceDU) + +# uView2.0������������������������������������������ + +1. uView2.0���������������������nvue +2. uView2.0���1.x��������������������������������������������������������� +3. ������uView2.0������������������������������������������������ +4. ���������������������1.x������������������������[������1.x](https://www.uviewui.com/components/diff1.x.html) +5. ������input������formatter������������������ + + diff --git a/uni_modules/uview-ui/components/u--form/u--form.vue b/uni_modules/uview-ui/components/u--form/u--form.vue new file mode 100644 index 0000000..fdfc212 --- /dev/null +++ b/uni_modules/uview-ui/components/u--form/u--form.vue @@ -0,0 +1,78 @@ +<template> + <uvForm + ref="uForm" + :model="model" + :rules="rules" + :errorType="errorType" + :borderBottom="borderBottom" + :labelPosition="labelPosition" + :labelWidth="labelWidth" + :labelAlign="labelAlign" + :labelStyle="labelStyle" + :customStyle="customStyle" + > + <slot /> + </uvForm> +</template> + +<script> + /** + * ���������������������������������nvue������u-form���uni-app������������������u-form���nvue������������form������ + * ���������nvue���������������u--form���������������������u-form.vue��������������������������� + */ + import uvForm from '../u-form/u-form.vue'; + import props from '../u-form/props.js' + export default { + // #ifdef MP-WEIXIN + name: 'u-form', + // #endif + // #ifndef MP-WEIXIN + name: 'u--form', + // #endif + mixins: [uni.$u.mpMixin, props, uni.$u.mixin], + components: { + uvForm + }, + created() { + this.children = [] + }, + methods: { + // ������������������������������������������������������������������������������������������������������������������������������������ + setRules(rules) { + this.$refs.uForm.setRules(rules) + }, + validate() { + /** + * ������������������������������this.$parent���������������������u--form������������������������u-form + * ���������u-form������������������������������children������������������������������������������������������u-form������������ + * ������������������������������������������������u--form���children���������u-form������children + */ + // #ifdef MP-WEIXIN + this.setMpData() + // #endif + return this.$refs.uForm.validate() + }, + validateField(value, callback) { + // #ifdef MP-WEIXIN + this.setMpData() + // #endif + return this.$refs.uForm.validateField(value, callback) + }, + resetFields() { + // #ifdef MP-WEIXIN + this.setMpData() + // #endif + return this.$refs.uForm.resetFields() + }, + clearValidate(props) { + // #ifdef MP-WEIXIN + this.setMpData() + // #endif + return this.$refs.uForm.clearValidate(props) + }, + setMpData() { + this.$refs.uForm.children = this.children + } + }, + } +</script> diff --git a/uni_modules/uview-ui/components/u--image/u--image.vue b/uni_modules/uview-ui/components/u--image/u--image.vue new file mode 100644 index 0000000..21b7ab1 --- /dev/null +++ b/uni_modules/uview-ui/components/u--image/u--image.vue @@ -0,0 +1,47 @@ +<template> + <uvImage + :src="src" + :mode="mode" + :width="width" + :height="height" + :shape="shape" + :radius="radius" + :lazyLoad="lazyLoad" + :showMenuByLongpress="showMenuByLongpress" + :loadingIcon="loadingIcon" + :errorIcon="errorIcon" + :showLoading="showLoading" + :showError="showError" + :fade="fade" + :webp="webp" + :duration="duration" + :bgColor="bgColor" + :customStyle="customStyle" + @click="$emit('click')" + @error="$emit('error')" + @load="$emit('load')" + > + <template v-slot:loading> + <slot name="loading"></slot> + </template> + <template v-slot:error> + <slot name="error"></slot> + </template> + </uvImage> +</template> + +<script> + /** + * ���������������������������������nvue������u-image���uni-app������������������u-image���nvue������������image������ + * ���������nvue���������������u--image���������������������u-iamge.vue��������������������������� + */ + import uvImage from '../u-image/u-image.vue'; + import props from '../u-image/props.js'; + export default { + name: 'u--image', + mixins: [uni.$u.mpMixin, props, uni.$u.mixin], + components: { + uvImage + }, + } +</script> \ No newline at end of file diff --git a/uni_modules/uview-ui/components/u--input/u--input.vue b/uni_modules/uview-ui/components/u--input/u--input.vue new file mode 100644 index 0000000..1e58b01 --- /dev/null +++ b/uni_modules/uview-ui/components/u--input/u--input.vue @@ -0,0 +1,73 @@ +<template> + <uvInput + :value="value" + :type="type" + :fixed="fixed" + :disabled="disabled" + :disabledColor="disabledColor" + :clearable="clearable" + :password="password" + :maxlength="maxlength" + :placeholder="placeholder" + :placeholderClass="placeholderClass" + :placeholderStyle="placeholderStyle" + :showWordLimit="showWordLimit" + :confirmType="confirmType" + :confirmHold="confirmHold" + :holdKeyboard="holdKeyboard" + :focus="focus" + :autoBlur="autoBlur" + :disableDefaultPadding="disableDefaultPadding" + :cursor="cursor" + :cursorSpacing="cursorSpacing" + :selectionStart="selectionStart" + :selectionEnd="selectionEnd" + :adjustPosition="adjustPosition" + :inputAlign="inputAlign" + :fontSize="fontSize" + :color="color" + :prefixIcon="prefixIcon" + :suffixIcon="suffixIcon" + :suffixIconStyle="suffixIconStyle" + :prefixIconStyle="prefixIconStyle" + :border="border" + :readonly="readonly" + :shape="shape" + :customStyle="customStyle" + :formatter="formatter" + :ignoreCompositionEvent="ignoreCompositionEvent" + @focus="$emit('focus')" + @blur="e => $emit('blur', e)" + @keyboardheightchange="$emit('keyboardheightchange')" + @change="e => $emit('change', e)" + @input="e => $emit('input', e)" + @confirm="e => $emit('confirm', e)" + @clear="$emit('clear')" + @click="$emit('click')" + > + <!-- #ifdef MP --> + <slot name="prefix"></slot> + <slot name="suffix"></slot> + <!-- #endif --> + <!-- #ifndef MP --> + <slot name="prefix" slot="prefix"></slot> + <slot name="suffix" slot="suffix"></slot> + <!-- #endif --> + </uvInput> +</template> + +<script> + /** + * ���������������������������������nvue������u-input���uni-app������������������u-input���nvue������������input������ + * ���������nvue���������������u--input���������������������u-input.vue��������������������������� + */ + import uvInput from '../u-input/u-input.vue'; + import props from '../u-input/props.js' + export default { + name: 'u--input', + mixins: [uni.$u.mpMixin, props, uni.$u.mixin], + components: { + uvInput + }, + } +</script> \ No newline at end of file diff --git a/uni_modules/uview-ui/components/u--text/u--text.vue b/uni_modules/uview-ui/components/u--text/u--text.vue new file mode 100644 index 0000000..44ee52a --- /dev/null +++ b/uni_modules/uview-ui/components/u--text/u--text.vue @@ -0,0 +1,44 @@ +<template> + <uvText + :type="type" + :show="show" + :text="text" + :prefixIcon="prefixIcon" + :suffixIcon="suffixIcon" + :mode="mode" + :href="href" + :format="format" + :call="call" + :openType="openType" + :bold="bold" + :block="block" + :lines="lines" + :color="color" + :decoration="decoration" + :size="size" + :iconStyle="iconStyle" + :margin="margin" + :lineHeight="lineHeight" + :align="align" + :wordWrap="wordWrap" + :customStyle="customStyle" + @click="$emit('click')" + ></uvText> +</template> + +<script> +/** + * ���������������������������������nvue������u-text���uni-app������������������u-text���nvue������������input������ + * ���������nvue���������������u--input���������������������u-text.vue��������������������������� + * ���������v-bind="$attrs"��������������������������������������������������������������������������� + */ +import uvText from "../u-text/u-text.vue"; +import props from "../u-text/props.js"; +export default { + name: "u--text", + mixins: [uni.$u.mpMixin, props, uni.$u.mixin], + components: { + uvText, + }, +}; +</script> diff --git a/uni_modules/uview-ui/components/u--textarea/u--textarea.vue b/uni_modules/uview-ui/components/u--textarea/u--textarea.vue new file mode 100644 index 0000000..f4df0b9 --- /dev/null +++ b/uni_modules/uview-ui/components/u--textarea/u--textarea.vue @@ -0,0 +1,48 @@ +<template> + <uvTextarea + :value="value" + :placeholder="placeholder" + :height="height" + :confirmType="confirmType" + :disabled="disabled" + :count="count" + :focus="focus" + :autoHeight="autoHeight" + :fixed="fixed" + :cursorSpacing="cursorSpacing" + :cursor="cursor" + :showConfirmBar="showConfirmBar" + :selectionStart="selectionStart" + :selectionEnd="selectionEnd" + :adjustPosition="adjustPosition" + :disableDefaultPadding="disableDefaultPadding" + :holdKeyboard="holdKeyboard" + :maxlength="maxlength" + :border="border" + :customStyle="customStyle" + :formatter="formatter" + :ignoreCompositionEvent="ignoreCompositionEvent" + @focus="e => $emit('focus')" + @blur="e => $emit('blur')" + @linechange="e => $emit('linechange', e)" + @confirm="e => $emit('confirm')" + @input="e => $emit('input', e)" + @keyboardheightchange="e => $emit('keyboardheightchange')" + ></uvTextarea> +</template> + +<script> + /** + * ���������������������������������nvue������u--textarea���uni-app������������������u-textarea���nvue������������textarea������ + * ���������nvue���������������u--textarea���������������������u-textarea.vue��������������������������� + */ + import uvTextarea from '../u-textarea/u-textarea.vue'; + import props from '../u-textarea/props.js' + export default { + name: 'u--textarea', + mixins: [uni.$u.mpMixin, props, uni.$u.mixin], + components: { + uvTextarea + }, + } +</script> diff --git a/uni_modules/uview-ui/components/u-action-sheet/props.js b/uni_modules/uview-ui/components/u-action-sheet/props.js new file mode 100644 index 0000000..e96e04f --- /dev/null +++ b/uni_modules/uview-ui/components/u-action-sheet/props.js @@ -0,0 +1,54 @@ +export default { + props: { + // ������������������������ ���������false��� + show: { + type: Boolean, + default: uni.$u.props.actionSheet.show + }, + // ������ + title: { + type: String, + default: uni.$u.props.actionSheet.title + }, + // ��������������������������� + description: { + type: String, + default: uni.$u.props.actionSheet.description + }, + // ������ + actions: { + type: Array, + default: uni.$u.props.actionSheet.actions + }, + // ������������������������������������������������ + cancelText: { + type: String, + default: uni.$u.props.actionSheet.cancelText + }, + // ������������������������������������������ + closeOnClickAction: { + type: Boolean, + default: uni.$u.props.actionSheet.closeOnClickAction + }, + // ������������������������������true��� + safeAreaInsetBottom: { + type: Boolean, + default: uni.$u.props.actionSheet.safeAreaInsetBottom + }, + // ������������������������ + openType: { + type: String, + default: uni.$u.props.actionSheet.openType + }, + // ������������������������������ (������true) + closeOnClickOverlay: { + type: Boolean, + default: uni.$u.props.actionSheet.closeOnClickOverlay + }, + // ��������� + round: { + type: [Boolean, String, Number], + default: uni.$u.props.actionSheet.round + } + } +} diff --git a/uni_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue b/uni_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue new file mode 100644 index 0000000..26d5d8d --- /dev/null +++ b/uni_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue @@ -0,0 +1,278 @@ + +<template> + <u-popup + :show="show" + mode="bottom" + @close="closeHandler" + :safeAreaInsetBottom="safeAreaInsetBottom" + :round="round" + > + <view class="u-action-sheet"> + <view + class="u-action-sheet__header" + v-if="title" + > + <text class="u-action-sheet__header__title u-line-1">{{title}}</text> + <view + class="u-action-sheet__header__icon-wrap" + @tap.stop="cancel" + > + <u-icon + name="close" + size="17" + color="#c8c9cc" + bold + ></u-icon> + </view> + </view> + <text + class="u-action-sheet__description" + :style="[{ + marginTop: `${title && description ? 0 : '18px'}` + }]" + v-if="description" + >{{description}}</text> + <slot> + <u-line v-if="description"></u-line> + <view class="u-action-sheet__item-wrap"> + <template v-for="(item, index) in actions"> + <!-- #ifdef MP --> + <button + :key="index" + class="u-reset-button" + :openType="item.openType" + @getuserinfo="onGetUserInfo" + @contact="onContact" + @getphonenumber="onGetPhoneNumber" + @error="onError" + @launchapp="onLaunchApp" + @opensetting="onOpenSetting" + :lang="lang" + :session-from="sessionFrom" + :send-message-title="sendMessageTitle" + :send-message-path="sendMessagePath" + :send-message-img="sendMessageImg" + :show-message-card="showMessageCard" + :app-parameter="appParameter" + @tap="selectHandler(index)" + :hover-class="!item.disabled && !item.loading ? 'u-action-sheet--hover' : ''" + > + <!-- #endif --> + <view + class="u-action-sheet__item-wrap__item" + @tap.stop="selectHandler(index)" + :hover-class="!item.disabled && !item.loading ? 'u-action-sheet--hover' : ''" + :hover-stay-time="150" + > + <template v-if="!item.loading"> + <text + class="u-action-sheet__item-wrap__item__name" + :style="[itemStyle(index)]" + >{{ item.name }}</text> + <text + v-if="item.subname" + class="u-action-sheet__item-wrap__item__subname" + >{{ item.subname }}</text> + </template> + <u-loading-icon + v-else + custom-class="van-action-sheet__loading" + size="18" + mode="circle" + /> + </view> + <!-- #ifdef MP --> + </button> + <!-- #endif --> + <u-line v-if="index !== actions.length - 1"></u-line> + </template> + </view> + </slot> + <u-gap + bgColor="#eaeaec" + height="6" + v-if="cancelText" + ></u-gap> + <view hover-class="u-action-sheet--hover"> + <text + @touchmove.stop.prevent + :hover-stay-time="150" + v-if="cancelText" + class="u-action-sheet__cancel-text" + @tap="cancel" + >{{cancelText}}</text> + </view> + </view> + </u-popup> +</template> + +<script> + import openType from '../../libs/mixin/openType' + import button from '../../libs/mixin/button' + import props from './props.js'; + /** + * ActionSheet ������������ + * @description ������������������������������������������������������������������������������������������������������������uni���uni.showActionSheetAPI������������������������������������������������������ + * @tutorial https://www.uviewui.com/components/actionSheet.html + * + * @property {Boolean} show ������������������������ ��������� false ��� + * @property {String} title ������������������ + * @property {String} description ��������������������������� + * @property {Array<Object>} actions ��������������������������������������������� + * @property {String} cancelText ���������������������������,������������������������ + * @property {Boolean} closeOnClickAction ������������������������������������������ ��������� true ��� + * @property {Boolean} safeAreaInsetBottom ��������������������� ��������� true ��� + * @property {String} openType ������������������������ (contact | launchApp | getUserInfo | openSetting ���getPhoneNumber ���error ) + * @property {Boolean} closeOnClickOverlay ������������������������������ (������ true ) + * @property {Number|String} round ��������������������������� (������ 0 ) + * @property {String} lang ������������������������������������zh_CN ���������������zh_TW ���������������en ������ + * @property {String} sessionFrom ���������������openType="contact"��������� + * @property {String} sendMessageTitle ������������������������������openType="contact"��������� + * @property {String} sendMessagePath ���������������������������������������������������openType="contact"��������� + * @property {String} sendMessageImg ������������������������������openType="contact"��������� + * @property {Boolean} showMessageCard ������������������������������������������������������ true������������������������������������������������"���������������������������"������������������������������������������������������������openType="contact"��������� ��������� false ��� + * @property {String} appParameter ������ APP ��������� APP ������������������openType=launchApp ��������� + * + * @event {Function} select ������ActionSheet������������������ + * @event {Function} close ��������������������������� + * @event {Function} getuserinfo ������������������������������������������������������������������������ detail ��������� wx.getUserInfo ������������������openType="getUserInfo"��������� + * @event {Function} contact ���������������������openType="contact"��������� + * @event {Function} getphonenumber ������������������������������openType="getPhoneNumber"��������� + * @event {Function} error ���������������������������������������������������openType="error"��������� + * @event {Function} launchapp ������ APP ������������������openType="launchApp"��������� + * @event {Function} opensetting ������������������������������������openType="openSetting"��������� + * @example <u-action-sheet :actions="list" :title="title" :show="show"></u-action-sheet> + */ + export default { + name: "u-action-sheet", + // ������props���������methods���������������mixin��������������������������������������� + mixins: [openType, button, uni.$u.mixin, props], + data() { + return { + + } + }, + computed: { + // ��������������������� + itemStyle() { + return (index) => { + let style = {}; + if (this.actions[index].color) style.color = this.actions[index].color + if (this.actions[index].fontSize) style.fontSize = uni.$u.addUnit(this.actions[index].fontSize) + // ������������������������ + if (this.actions[index].disabled) style.color = '#c0c4cc' + return style; + } + }, + }, + methods: { + closeHandler() { + // ���������������������������������������close������ + if(this.closeOnClickOverlay) { + this.$emit('close') + } + }, + // ������������������ + cancel() { + this.$emit('close') + }, + selectHandler(index) { + const item = this.actions[index] + if (item && !item.disabled && !item.loading) { + this.$emit('select', item) + if (this.closeOnClickAction) { + this.$emit('close') + } + } + }, + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + $u-action-sheet-reset-button-width:100% !default; + $u-action-sheet-title-font-size: 16px !default; + $u-action-sheet-title-padding: 12px 30px !default; + $u-action-sheet-title-color: $u-main-color !default; + $u-action-sheet-header-icon-wrap-right:15px !default; + $u-action-sheet-header-icon-wrap-top:15px !default; + $u-action-sheet-description-font-size:13px !default; + $u-action-sheet-description-color:14px !default; + $u-action-sheet-description-margin: 18px 15px !default; + $u-action-sheet-item-wrap-item-padding:15px !default; + $u-action-sheet-item-wrap-name-font-size:16px !default; + $u-action-sheet-item-wrap-subname-font-size:13px !default; + $u-action-sheet-item-wrap-subname-color: #c0c4cc !default; + $u-action-sheet-item-wrap-subname-margin-top:10px !default; + $u-action-sheet-cancel-text-font-size:16px !default; + $u-action-sheet-cancel-text-color:$u-content-color !default; + $u-action-sheet-cancel-text-font-size:15px !default; + $u-action-sheet-cancel-text-hover-background-color:rgb(242, 243, 245) !default; + + .u-reset-button { + width: $u-action-sheet-reset-button-width; + } + + .u-action-sheet { + text-align: center; + &__header { + position: relative; + padding: $u-action-sheet-title-padding; + &__title { + font-size: $u-action-sheet-title-font-size; + color: $u-action-sheet-title-color; + font-weight: bold; + text-align: center; + } + + &__icon-wrap { + position: absolute; + right: $u-action-sheet-header-icon-wrap-right; + top: $u-action-sheet-header-icon-wrap-top; + } + } + + &__description { + font-size: $u-action-sheet-description-font-size; + color: $u-tips-color; + margin: $u-action-sheet-description-margin; + text-align: center; + } + + &__item-wrap { + + &__item { + padding: $u-action-sheet-item-wrap-item-padding; + @include flex; + align-items: center; + justify-content: center; + flex-direction: column; + + &__name { + font-size: $u-action-sheet-item-wrap-name-font-size; + color: $u-main-color; + text-align: center; + } + + &__subname { + font-size: $u-action-sheet-item-wrap-subname-font-size; + color: $u-action-sheet-item-wrap-subname-color; + margin-top: $u-action-sheet-item-wrap-subname-margin-top; + text-align: center; + } + } + } + + &__cancel-text { + font-size: $u-action-sheet-cancel-text-font-size; + color: $u-action-sheet-cancel-text-color; + text-align: center; + padding: $u-action-sheet-cancel-text-font-size; + } + + &--hover { + background-color: $u-action-sheet-cancel-text-hover-background-color; + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-album/props.js b/uni_modules/uview-ui/components/u-album/props.js new file mode 100644 index 0000000..75cdb37 --- /dev/null +++ b/uni_modules/uview-ui/components/u-album/props.js @@ -0,0 +1,59 @@ +export default { + props: { + // ���������������Array<String>|Array<Object>������ + urls: { + type: Array, + default: uni.$u.props.album.urls + }, + // ��������������������������������������������������������������������� + keyName: { + type: String, + default: uni.$u.props.album.keyName + }, + // ��������������������������������� + singleSize: { + type: [String, Number], + default: uni.$u.props.album.singleSize + }, + // ������������������������ + multipleSize: { + type: [String, Number], + default: uni.$u.props.album.multipleSize + }, + // ������������������������������������������������ + space: { + type: [String, Number], + default: uni.$u.props.album.space + }, + // ��������������������������������������� + singleMode: { + type: String, + default: uni.$u.props.album.singleMode + }, + // ��������������������������������������� + multipleMode: { + type: String, + default: uni.$u.props.album.multipleMode + }, + // ��������������������������������������������������������������������������������������� + maxCount: { + type: [String, Number], + default: uni.$u.props.album.maxCount + }, + // ������������������������ + previewFullImage: { + type: Boolean, + default: uni.$u.props.album.previewFullImage + }, + // ���������������������������������������singleSize���multipleSize������������ + rowCount: { + type: [String, Number], + default: uni.$u.props.album.rowCount + }, + // ������maxCount������������������������������������ + showMore: { + type: Boolean, + default: uni.$u.props.album.showMore + } + } +} diff --git a/uni_modules/uview-ui/components/u-album/u-album.vue b/uni_modules/uview-ui/components/u-album/u-album.vue new file mode 100644 index 0000000..687e2d5 --- /dev/null +++ b/uni_modules/uview-ui/components/u-album/u-album.vue @@ -0,0 +1,259 @@ +<template> + <view class="u-album"> + <view + class="u-album__row" + ref="u-album__row" + v-for="(arr, index) in showUrls" + :forComputedUse="albumWidth" + :key="index" + > + <view + class="u-album__row__wrapper" + v-for="(item, index1) in arr" + :key="index1" + :style="[imageStyle(index + 1, index1 + 1)]" + @tap="previewFullImage ? onPreviewTap(getSrc(item)) : ''" + > + <image + :src="getSrc(item)" + :mode=" + urls.length === 1 + ? imageHeight > 0 + ? singleMode + : 'widthFix' + : multipleMode + " + :style="[ + { + width: imageWidth, + height: imageHeight + } + ]" + ></image> + <view + v-if=" + showMore && + urls.length > rowCount * showUrls.length && + index === showUrls.length - 1 && + index1 === showUrls[showUrls.length - 1].length - 1 + " + class="u-album__row__wrapper__text" + > + <u--text + :text="`+${urls.length - maxCount}`" + color="#fff" + :size="multipleSize * 0.3" + align="center" + customStyle="justify-content: center" + ></u--text> + </view> + </view> + </view> + </view> +</template> + +<script> +import props from './props.js' +// #ifdef APP-NVUE +// ������weex������������KPI���������������������������������������������������������������������������dom��������������������� +const dom = uni.requireNativePlugin('dom') +// #endif + +/** + * Album ������ + * @description ��������������������������������������������������������������������������������������������������������������������� + * @tutorial https://www.uviewui.com/components/album.html + * + * @property {Array} urls ������������������ Array<String>|Array<Object>������ + * @property {String} keyName ��������������������������������������������������������������������� + * @property {String | Number} singleSize ��������������������������������� ��������� 180 ��� + * @property {String | Number} multipleSize ������������������������ ��������� 70 ��� + * @property {String | Number} space ������������������������������������������������ ��������� 6 ��� + * @property {String} singleMode ��������������������������������������� ��������� 'scaleToFill' ��� + * @property {String} multipleMode ��������������������������������������� ��������� 'aspectFill' ��� + * @property {String | Number} maxCount ��������������������������� ��������� 9 ��� + * @property {Boolean} previewFullImage ������������������������ ��������� true ��� + * @property {String | Number} rowCount ���������������������������������������singleSize���multipleSize������������ ��������� 3 ��� + * @property {Boolean} showMore ������maxCount������������������������������������ ��������� true ��� + * + * @event {Function} albumWidth ������������������������������������������������������������������������������������������������������ ��������������� width ��� + * @example <u-album :urls="urls2" @albumWidth="width => albumWidth = width" multipleSize="68" ></u-album> + */ +export default { + name: 'u-album', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + // ��������������� + singleWidth: 0, + // ��������������� + singleHeight: 0, + // ������������������������������������������������������������������������������������������������������ + singlePercent: 0.6 + } + }, + watch: { + urls: { + immediate: true, + handler(newVal) { + if (newVal.length === 1) { + this.getImageRect() + } + } + } + }, + computed: { + imageStyle() { + return (index1, index2) => { + const { space, rowCount, multipleSize, urls } = this, + { addUnit, addStyle } = uni.$u, + rowLen = this.showUrls.length, + allLen = this.urls.length + const style = { + marginRight: addUnit(space), + marginBottom: addUnit(space) + } + // ��������������������������������������������������������� + if (index1 === rowLen) style.marginBottom = 0 + // ������������������������������������������������������������������ + if ( + index2 === rowCount || + (index1 === rowLen && + index2 === this.showUrls[index1 - 1].length) + ) + style.marginRight = 0 + return style + } + }, + // ������������������������������ + showUrls() { + const arr = [] + this.urls.map((item, index) => { + // ������������������������ + if (index + 1 <= this.maxCount) { + // ������������������������������������ + const itemIndex = Math.floor(index / this.rowCount) + // ��������������������������������� + if (!arr[itemIndex]) { + arr[itemIndex] = [] + } + arr[itemIndex].push(item) + } + }) + return arr + }, + imageWidth() { + return uni.$u.addUnit( + this.urls.length === 1 ? this.singleWidth : this.multipleSize + ) + }, + imageHeight() { + return uni.$u.addUnit( + this.urls.length === 1 ? this.singleHeight : this.multipleSize + ) + }, + // ������������������������������������������������computed������������������urls������������������������������������������������ + // ��������������������������������������������������������������������������������������������������������������������������� + albumWidth() { + let width = 0 + if (this.urls.length === 1) { + width = this.singleWidth + } else { + width = + this.showUrls[0].length * this.multipleSize + + this.space * (this.showUrls[0].length - 1) + } + this.$emit('albumWidth', width) + return width + } + }, + methods: { + // ������������ + onPreviewTap(url) { + const urls = this.urls.map((item) => { + return this.getSrc(item) + }) + uni.previewImage({ + current: url, + urls + }) + }, + // ��������������������� + getSrc(item) { + return uni.$u.test.object(item) + ? (this.keyName && item[this.keyName]) || item.src + : item + }, + // ��������������������������������� + // ������������������������������������������������������������������������download��������������������������� + // ���������������������������������������������������������������������������(singlePercent) + getImageRect() { + const src = this.getSrc(this.urls[0]) + uni.getImageInfo({ + src, + success: (res) => { + // ������������������������������������������ + const isHorizotal = res.width >= res.height + this.singleWidth = isHorizotal + ? this.singleSize + : (res.width / res.height) * this.singleSize + this.singleHeight = !isHorizotal + ? this.singleSize + : (res.height / res.width) * this.singleWidth + }, + fail: () => { + this.getComponentWidth() + } + }) + }, + // ��������������������� + async getComponentWidth() { + // ������������������������������dom������ + await uni.$u.sleep(30) + // #ifndef APP-NVUE + this.$uGetRect('.u-album__row').then((size) => { + this.singleWidth = size.width * this.singlePercent + }) + // #endif + + // #ifdef APP-NVUE + // ������ref="u-album__row"������������������������for���������������������this.$refs['u-album__row']��������������� + const ref = this.$refs['u-album__row'][0] + ref && + dom.getComponentRect(ref, (res) => { + this.singleWidth = res.size.width * this.singlePercent + }) + // #endif + } + } +} +</script> + +<style lang="scss" scoped> +@import '../../libs/css/components.scss'; + +.u-album { + @include flex(column); + + &__row { + @include flex(row); + flex-wrap: wrap; + + &__wrapper { + position: relative; + + &__text { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.3); + @include flex(row); + justify-content: center; + align-items: center; + } + } + } +} +</style> \ No newline at end of file diff --git a/uni_modules/uview-ui/components/u-alert/props.js b/uni_modules/uview-ui/components/u-alert/props.js new file mode 100644 index 0000000..4297e2c --- /dev/null +++ b/uni_modules/uview-ui/components/u-alert/props.js @@ -0,0 +1,44 @@ +export default { + props: { + // ������������ + title: { + type: String, + default: uni.$u.props.alert.title + }, + // ���������success/warning/info/error + type: { + type: String, + default: uni.$u.props.alert.type + }, + // ��������������� + description: { + type: String, + default: uni.$u.props.alert.description + }, + // ��������������� + closable: { + type: Boolean, + default: uni.$u.props.alert.closable + }, + // ������������������ + showIcon: { + type: Boolean, + default: uni.$u.props.alert.showIcon + }, + // ������������������light-���������dark-������ + effect: { + type: String, + default: uni.$u.props.alert.effect + }, + // ������������������ + center: { + type: Boolean, + default: uni.$u.props.alert.center + }, + // ������������ + fontSize: { + type: [String, Number], + default: uni.$u.props.alert.fontSize + } + } +} diff --git a/uni_modules/uview-ui/components/u-alert/u-alert.vue b/uni_modules/uview-ui/components/u-alert/u-alert.vue new file mode 100644 index 0000000..81f7d43 --- /dev/null +++ b/uni_modules/uview-ui/components/u-alert/u-alert.vue @@ -0,0 +1,243 @@ +<template> + <u-transition + mode="fade" + :show="show" + > + <view + class="u-alert" + :class="[`u-alert--${type}--${effect}`]" + @tap.stop="clickHandler" + :style="[$u.addStyle(customStyle)]" + > + <view + class="u-alert__icon" + v-if="showIcon" + > + <u-icon + :name="iconName" + size="18" + :color="iconColor" + ></u-icon> + </view> + <view + class="u-alert__content" + :style="[{ + paddingRight: closable ? '20px' : 0 + }]" + > + <text + class="u-alert__content__title" + v-if="title" + :style="[{ + fontSize: $u.addUnit(fontSize), + textAlign: center ? 'center' : 'left' + }]" + :class="[effect === 'dark' ? 'u-alert__text--dark' : `u-alert__text--${type}--light`]" + >{{ title }}</text> + <text + class="u-alert__content__desc" + v-if="description" + :style="[{ + fontSize: $u.addUnit(fontSize), + textAlign: center ? 'center' : 'left' + }]" + :class="[effect === 'dark' ? 'u-alert__text--dark' : `u-alert__text--${type}--light`]" + >{{ description }}</text> + </view> + <view + class="u-alert__close" + v-if="closable" + @tap.stop="closeHandler" + > + <u-icon + name="close" + :color="iconColor" + size="15" + ></u-icon> + </view> + </view> + </u-transition> +</template> + +<script> + import props from './props.js'; + /** + * Alert ������������ + * @description ��������������������������������������������� + * @tutorial https://www.uviewui.com/components/alertTips.html + * + * @property {String} title ��������������� + * @property {String} type ��������������������� ��������� 'warning' ��� + * @property {String} description ���������������������������title��������������������������������������� + * @property {Boolean} closable ������������(���������������icon������) ��������� false ��� + * @property {Boolean} showIcon ��������������������������������� ��� ������ false ��� + * @property {String} effect ��������������������������������������� ��������� 'light' ��� + * @property {Boolean} center ������������������ ��������� false ��� + * @property {String | Number} fontSize ������������ ��������� 14 ��� + * @property {Object} customStyle ��������������������������������� + * @event {Function} click ��������������������� + * @example <u-alert :title="title" type = "warning" :closable="closable" :description = "description"></u-alert> + */ + export default { + name: 'u-alert', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + show: true + } + }, + computed: { + iconColor() { + return this.effect === 'light' ? this.type : '#fff' + }, + // ��������������������������������� + iconName() { + switch (this.type) { + case 'success': + return 'checkmark-circle-fill'; + break; + case 'error': + return 'close-circle-fill'; + break; + case 'warning': + return 'error-circle-fill'; + break; + case 'info': + return 'info-circle-fill'; + break; + case 'primary': + return 'more-circle-fill'; + break; + default: + return 'error-circle-fill'; + } + } + }, + methods: { + // ������������ + clickHandler() { + this.$emit('click') + }, + // ������������������ + closeHandler() { + this.show = false + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-alert { + position: relative; + background-color: $u-primary; + padding: 8px 10px; + @include flex(row); + align-items: center; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + + &--primary--dark { + background-color: $u-primary; + } + + &--primary--light { + background-color: #ecf5ff; + } + + &--error--dark { + background-color: $u-error; + } + + &--error--light { + background-color: #FEF0F0; + } + + &--success--dark { + background-color: $u-success; + } + + &--success--light { + background-color: #f5fff0; + } + + &--warning--dark { + background-color: $u-warning; + } + + &--warning--light { + background-color: #FDF6EC; + } + + &--info--dark { + background-color: $u-info; + } + + &--info--light { + background-color: #f4f4f5; + } + + &__icon { + margin-right: 5px; + } + + &__content { + @include flex(column); + flex: 1; + + &__title { + color: $u-main-color; + font-size: 14px; + font-weight: bold; + color: #fff; + margin-bottom: 2px; + } + + &__desc { + color: $u-main-color; + font-size: 14px; + flex-wrap: wrap; + color: #fff; + } + } + + &__title--dark, + &__desc--dark { + color: #FFFFFF; + } + + &__text--primary--light, + &__text--primary--light { + color: $u-primary; + } + + &__text--success--light, + &__text--success--light { + color: $u-success; + } + + &__text--warning--light, + &__text--warning--light { + color: $u-warning; + } + + &__text--error--light, + &__text--error--light { + color: $u-error; + } + + &__text--info--light, + &__text--info--light { + color: $u-info; + } + + &__close { + position: absolute; + top: 11px; + right: 10px; + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-avatar-group/props.js b/uni_modules/uview-ui/components/u-avatar-group/props.js new file mode 100644 index 0000000..58b42ac --- /dev/null +++ b/uni_modules/uview-ui/components/u-avatar-group/props.js @@ -0,0 +1,52 @@ +export default { + props: { + // ��������������� + urls: { + type: Array, + default: uni.$u.props.avatarGroup.urls + }, + // ��������������������������� + maxCount: { + type: [String, Number], + default: uni.$u.props.avatarGroup.maxCount + }, + // ������������ + shape: { + type: String, + default: uni.$u.props.avatarGroup.shape + }, + // ������������������ + mode: { + type: String, + default: uni.$u.props.avatarGroup.mode + }, + // ������maxCount������������������������������������ + showMore: { + type: Boolean, + default: uni.$u.props.avatarGroup.showMore + }, + // ������������ + size: { + type: [String, Number], + default: uni.$u.props.avatarGroup.size + }, + // ��������������������������������������������������������������������� + keyName: { + type: String, + default: uni.$u.props.avatarGroup.keyName + }, + // ��������������������������� + gap: { + type: [String, Number], + validator(value) { + return value >= 0 && value <= 1 + }, + default: uni.$u.props.avatarGroup.gap + }, + // ��������������������� + extraValue: { + type: [Number, String], + default: uni.$u.props.avatarGroup.extraValue + } + } +} diff --git a/uni_modules/uview-ui/components/u-avatar-group/u-avatar-group.vue b/uni_modules/uview-ui/components/u-avatar-group/u-avatar-group.vue new file mode 100644 index 0000000..7e996d7 --- /dev/null +++ b/uni_modules/uview-ui/components/u-avatar-group/u-avatar-group.vue @@ -0,0 +1,103 @@ +<template> + <view class="u-avatar-group"> + <view + class="u-avatar-group__item" + v-for="(item, index) in showUrl" + :key="index" + :style="{ + marginLeft: index === 0 ? 0 : $u.addUnit(-size * gap) + }" + > + <u-avatar + :size="size" + :shape="shape" + :mode="mode" + :src="$u.test.object(item) ? keyName && item[keyName] || item.url : item" + ></u-avatar> + <view + class="u-avatar-group__item__show-more" + v-if="showMore && index === showUrl.length - 1 && (urls.length > maxCount || extraValue > 0)" + @tap="clickHandler" + > + <u--text + color="#ffffff" + :size="size * 0.4" + :text="`+${extraValue || urls.length - showUrl.length}`" + align="center" + customStyle="justify-content: center" + ></u--text> + </view> + </view> + </view> +</template> + +<script> + import props from './props.js'; + /** + * AvatarGroup ��������� + * @description ��������������������������������������������������������������������������������������������������������������������� + * @tutorial https://www.uviewui.com/components/avatar.html + * + * @property {Array} urls ��������������� ��������� [] ��� + * @property {String | Number} maxCount ��������������������������� ��� ������ 5 ��� + * @property {String} shape ��������������� 'circle' (������) | 'square' ��� + * @property {String} mode ��������������������������� 'scaleToFill' ��� + * @property {Boolean} showMore ������maxCount������������������������������������ ��������� true ��� + * @property {String | Number} size ������������ ��������� 40 ��� + * @property {String} keyName ��������������������������������������������������������������������� + * @property {String | Number} gap ������������������������������0.4������������40%��� ��������� 0.5 ��� + * @property {String | Number} extraValue ��������������������� + * @event {Function} showMore ��������������������� + * @example <u-avatar-group:urls="urls" size="35" gap="0.4" ></u-avatar-group:urls=> + */ + export default { + name: 'u-avatar-group', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + + } + }, + computed: { + showUrl() { + return this.urls.slice(0, this.maxCount) + } + }, + methods: { + clickHandler() { + this.$emit('showMore') + } + }, + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-avatar-group { + @include flex; + + &__item { + margin-left: -10px; + position: relative; + + &--no-indent { + // ������������������������������������:first-child������������������������������nvue��������� + margin-left: 0; + } + + &__show-more { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + background-color: rgba(0, 0, 0, 0.3); + @include flex; + align-items: center; + justify-content: center; + border-radius: 100px; + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-avatar/props.js b/uni_modules/uview-ui/components/u-avatar/props.js new file mode 100644 index 0000000..34ca0f2 --- /dev/null +++ b/uni_modules/uview-ui/components/u-avatar/props.js @@ -0,0 +1,78 @@ +export default { + props: { + // ������������������(���������������������) + src: { + type: String, + default: uni.$u.props.avatar.src + }, + // ���������������circle-���������square-������ + shape: { + type: String, + default: uni.$u.props.avatar.shape + }, + // ������������ + size: { + type: [String, Number], + default: uni.$u.props.avatar.size + }, + // ������������ + mode: { + type: String, + default: uni.$u.props.avatar.mode + }, + // ��������������� + text: { + type: String, + default: uni.$u.props.avatar.text + }, + // ��������� + bgColor: { + type: String, + default: uni.$u.props.avatar.bgColor + }, + // ������������ + color: { + type: String, + default: uni.$u.props.avatar.color + }, + // ������������ + fontSize: { + type: [String, Number], + default: uni.$u.props.avatar.fontSize + }, + // ��������������� + icon: { + type: String, + default: uni.$u.props.avatar.icon + }, + // ������������������������������������������������QQ��������������� + mpAvatar: { + type: Boolean, + default: uni.$u.props.avatar.mpAvatar + }, + // ��������������������������� + randomBgColor: { + type: Boolean, + default: uni.$u.props.avatar.randomBgColor + }, + // ���������������������������(���������������������������) + defaultUrl: { + type: String, + default: uni.$u.props.avatar.defaultUrl + }, + // ���������������randomBgColor���true������������������������������������������������������������������������������������������������0-19������ + colorIndex: { + type: [String, Number], + // ������������������������������0-19������ + validator(n) { + return uni.$u.test.range(n, [0, 19]) || n === '' + }, + default: uni.$u.props.avatar.colorIndex + }, + // ��������������� + name: { + type: String, + default: uni.$u.props.avatar.name + } + } +} diff --git a/uni_modules/uview-ui/components/u-avatar/u-avatar.vue b/uni_modules/uview-ui/components/u-avatar/u-avatar.vue new file mode 100644 index 0000000..3319be5 --- /dev/null +++ b/uni_modules/uview-ui/components/u-avatar/u-avatar.vue @@ -0,0 +1,172 @@ +<template> + <view + class="u-avatar" + :class="[`u-avatar--${shape}`]" + :style="[{ + backgroundColor: (text || icon) ? (randomBgColor ? colors[colorIndex !== '' ? colorIndex : $u.random(0, 19)] : bgColor) : 'transparent', + width: $u.addUnit(size), + height: $u.addUnit(size), + }, $u.addStyle(customStyle)]" + @tap="clickHandler" + > + <slot> + <!-- #ifdef MP-WEIXIN || MP-QQ || MP-BAIDU --> + <open-data + v-if="mpAvatar && allowMp" + type="userAvatarUrl" + :style="[{ + width: $u.addUnit(size), + height: $u.addUnit(size) + }]" + /> + <!-- #endif --> + <!-- #ifndef MP-WEIXIN && MP-QQ && MP-BAIDU --> + <template v-if="mpAvatar && allowMp"></template> + <!-- #endif --> + <u-icon + v-else-if="icon" + :name="icon" + :size="fontSize" + :color="color" + ></u-icon> + <u--text + v-else-if="text" + :text="text" + :size="fontSize" + :color="color" + align="center" + customStyle="justify-content: center" + ></u--text> + <image + class="u-avatar__image" + v-else + :class="[`u-avatar__image--${shape}`]" + :src="avatarUrl || defaultUrl" + :mode="mode" + @error="errorHandler" + :style="[{ + width: $u.addUnit(size), + height: $u.addUnit(size) + }]" + ></image> + </slot> + </view> +</template> + +<script> + import props from './props.js'; + const base64Avatar = + "data:image/jpg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAA8AAD/4QMraHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjMtYzAxMSA2Ni4xNDU2NjEsIDIwMTIvMDIvMDYtMTQ6NTY6MjcgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzYgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjREMEQwRkY0RjgwNDExRUE5OTY2RDgxODY3NkJFODMxIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjREMEQwRkY1RjgwNDExRUE5OTY2RDgxODY3NkJFODMxIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NEQwRDBGRjJGODA0MTFFQTk5NjZEODE4Njc2QkU4MzEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NEQwRDBGRjNGODA0MTFFQTk5NjZEODE4Njc2QkU4MzEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7/7gAOQWRvYmUAZMAAAAAB/9sAhAAGBAQEBQQGBQUGCQYFBgkLCAYGCAsMCgoLCgoMEAwMDAwMDBAMDg8QDw4MExMUFBMTHBsbGxwfHx8fHx8fHx8fAQcHBw0MDRgQEBgaFREVGh8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx//wAARCADIAMgDAREAAhEBAxEB/8QAcQABAQEAAwEBAAAAAAAAAAAAAAUEAQMGAgcBAQAAAAAAAAAAAAAAAAAAAAAQAAIBAwICBgkDBQAAAAAAAAABAhEDBCEFMVFBYXGREiKBscHRMkJSEyOh4XLxYjNDFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8A/fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHbHFyZ/Dam+yLA+Z2L0Pjtyj2poD4AAAAAAAAAAAAAAAAAAAAAAAAKWFs9y6lcvvwQeqj8z9wFaziY1n/HbUX9XF97A7QAGXI23EvJ1goyfzR0YEfN269jeZ+a03pNe0DIAAAAAAAAAAAAAAAAAAAACvtO3RcVkXlWutuL9YFYAAAAAOJRjKLjJVi9GmB5/csH/mu1h/in8PU+QGMAAAAAAAAAAAAAAAAAAaMDG/6MmMH8C80+xAelSSVFolwQAAAAAAAHVlWI37ErUulaPk+hgeYnCUJuElSUXRrrQHAAAAAAAAAAAAAAAAABa2Oz4bM7r4zdF2ICmAAAAAAAAAg7zZ8GX41wuJP0rRgYAAAAAAAAAAAAAAAAAD0m2R8ODaXU33tsDSAAAAAAAAAlb9HyWZcnJd9PcBHAAAAAAAAAAAAAAAAAPS7e64Vn+KA0AAAAAAAAAJm+v8Ftf3ewCKAAAAAAAAAAAAAAAAAX9muqeGo9NttP06+0DcAAAAAAAAAjb7dTu2ra+VOT9P8AQCWAAAAAAAAAAAAAAAAAUNmyPt5Ltv4bui/kuAF0AAAAAAADiUlGLlJ0SVW+oDzOXfd/Ind6JPRdS0QHSAAAAAAAAAAAAAAAAAE2nVaNcGB6Lbs6OTao9LsF51z60BrAAAAAABJ3jOVHjW3r/sa9QEgAAAAAAAAAAAAAAAAAAAPu1duWriuW34ZR4MC9hbnZyEoy8l36XwfYBsAAADaSq9EuLAlZ+7xSdrGdW9Hc5dgEdtt1erfFgAAAAAAAAAAAAAAAAADVjbblX6NR8MH80tEBRs7HYivyzlN8lovaBPzduvY0m6eK10TXtAyAarO55lpJK54orolr+4GqO/Xaea1FvqbXvA+Z77kNeW3GPbV+4DJfzcm/pcm3H6Vou5AdAFLC2ed2Pjv1txa8sV8T6wOL+yZEKu1JXFy4MDBOE4ScZxcZLinoB8gAAAAAAAAAAAB242LeyJ+C3GvN9C7QLmJtePYpKS+5c+p8F2IDYAANJqj1T4oCfk7Nj3G5Wn9qXJax7gJ93Z82D8sVNc4v30A6Xg5i42Z+iLfqARwcyT0sz9MWvWBps7LlTf5Grce9/oBTxdtxseklHxT+uWr9AGoAB138ezfj4bsFJdD6V2MCPm7RdtJzs1uW1xXzL3gTgAAAAAAAAADRhYc8q74I6RWs5ckB6GxYtWLat21SK731sDsAAAAAAAAAAAAAAAASt021NO/YjrxuQXT1oCOAAAAAAABzGLlJRSq26JAelwsWONYjbXxcZvmwO8AAAAAAAAAAAAAAAAAAef3TEWPkVivx3NY9T6UBiAAAAAABo2+VmGXblddIJ8eivRUD0oAAAAAAAAAAAAAAAAAAAYt4tKeFKVNYNSXfRgefAAAAAAAAr7VuSSWPedKaW5v1MCsAAAAAAAAAAAAAAAAAAIe6bj96Ts2n+JPzSXzP3ATgAAAAAAAAFbbt1UUrOQ9FpC4/UwK6aaqtU+DAAAAAAAAAAAAAAA4lKMIuUmoxWrb4ARNx3R3q2rLpa4Sl0y/YCcAAAAAAAAAAANmFud7G8r89r6X0dgFvGzLGRGtuWvTF6NAdwAAAAAAAAAAAy5W442PVN+K59EePp5ARMvOv5MvO6QXCC4AZwAAAAAAAAAAAAAcxlKLUotprg1owN+PvORborq+7Hnwl3gUbO74VzRydt8pKn68ANcJwmqwkpLmnUDkAAAAfNy9atqtyagut0AxXt5xIV8Fbj6lRd7Am5G65V6qUvtwfyx94GMAAAAAAAAAAAAAAAAAAAOU2nVOj5gdsc3LiqRvTpyqwOxbnnrhdfpSfrQB7pnv/AGvuS9gHXPMy5/Fem1yq0v0A6W29XqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf//Z"; + /** + * Avatar ������ + * @description ��������������������������������������������������������������������������������������������������������������������� + * @tutorial https://www.uviewui.com/components/avatar.html + * + * @property {String} src ���������������������������������������������������������(���������������������) + * @property {String} shape ������������ ��� circle (������) | square��� + * @property {String | Number} size ���������������������������������������(large, default, mini)��������������� ��������� 40 ��� + * @property {String} mode ���������������������������������uni���image���������mode������������������������������������������������������widthFix��� ��������� 'scaleToFill' ��� + * @property {String} text ���������������������������������������src + * @property {String} bgColor ��������������������������������������� ��������� '#c0c4cc' ��� + * @property {String} color ������������ ��������� '#ffffff' ��� + * @property {String | Number} fontSize ������������ ��������� 18 ��� + * @property {String} icon ��������������� + * @property {Boolean} mpAvatar ������������������������������������������������QQ��������������� ��������� false ��� + * @property {Boolean} randomBgColor ��������������������������� ��������� false ��� + * @property {String} defaultUrl ���������������������������(���������������������������) + * @property {String | Number} colorIndex ���������������randomBgColor���true������������������������������������������������������������������������������������������������0-19������ + * @property {String} name ��������������� ��������� 'level' ��� + * @property {Object} customStyle ��������������������������������� + * + * @event {Function} click ��������������������� index: ������������������������ + * @example <u-avatar :src="src" mode="square"></u-avatar> + */ + export default { + name: 'u-avatar', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + // ������������randomBgColor���������true������������������������������������������������������������������������������������������ + colors: ['#ffb34b', '#f2bba9', '#f7a196', '#f18080', '#88a867', '#bfbf39', '#89c152', '#94d554', '#f19ec2', + '#afaae4', '#e1b0df', '#c38cc1', '#72dcdc', '#9acdcb', '#77b1cc', '#448aca', '#86cefa', '#98d1ee', + '#73d1f1', + '#80a7dc' + ], + avatarUrl: this.src, + allowMp: false + } + }, + watch: { + // ������������src������������������������������avatarUrl������������������������������������������������������������src������������ + // ���������������������������������props��������������������������������������� + src: { + immediate: true, + handler(newVal) { + this.avatarUrl = newVal + // ���������������src������������������error���������������������������������������������src���''������������������������������������������ + if(!newVal) { + this.errorHandler() + } + } + } + }, + computed: { + imageStyle() { + const style = {} + return style + } + }, + created() { + this.init() + }, + methods: { + init() { + // ������������������������������������������open-data������ + // ������������������������uni.getUserInfo���������������������������������������������������(������)������������������������ + // ������������������������������������������������������������ + // #ifdef MP-WEIXIN || MP-QQ || MP-BAIDU + this.allowMp = true + // #endif + }, + // ���������������name������������������������������������������"/"������������������������ + isImg() { + return this.src.indexOf('/') !== -1 + }, + // ������������������������������ + errorHandler() { + this.avatarUrl = this.defaultUrl || base64Avatar + }, + clickHandler() { + this.$emit('click', this.name) + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-avatar { + @include flex; + align-items: center; + justify-content: center; + + &--circle { + border-radius: 100px; + } + + &--square { + border-radius: 4px; + } + + &__image { + &--circle { + border-radius: 100px; + } + + &--square { + border-radius: 4px; + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-back-top/props.js b/uni_modules/uview-ui/components/u-back-top/props.js new file mode 100644 index 0000000..6c702c2 --- /dev/null +++ b/uni_modules/uview-ui/components/u-back-top/props.js @@ -0,0 +1,54 @@ +export default { + props: { + // ������������������������circle-���������square-������ + mode: { + type: String, + default: uni.$u.props.backtop.mode + }, + // ��������������� + icon: { + type: String, + default: uni.$u.props.backtop.icon + }, + // ������������ + text: { + type: String, + default: uni.$u.props.backtop.text + }, + // ������������������������ + duration: { + type: [String, Number], + default: uni.$u.props.backtop.duration + }, + // ������������ + scrollTop: { + type: [String, Number], + default: uni.$u.props.backtop.scrollTop + }, + // ���������������������������������������px + top: { + type: [String, Number], + default: uni.$u.props.backtop.top + }, + // ���������������������������������������������px + bottom: { + type: [String, Number], + default: uni.$u.props.backtop.bottom + }, + // ���������������������������������������������px + right: { + type: [String, Number], + default: uni.$u.props.backtop.right + }, + // ������ + zIndex: { + type: [String, Number], + default: uni.$u.props.backtop.zIndex + }, + // ������������������������������ + iconStyle: { + type: Object, + default: uni.$u.props.backtop.iconStyle + } + } +} diff --git a/uni_modules/uview-ui/components/u-back-top/u-back-top.vue b/uni_modules/uview-ui/components/u-back-top/u-back-top.vue new file mode 100644 index 0000000..2d07566 --- /dev/null +++ b/uni_modules/uview-ui/components/u-back-top/u-back-top.vue @@ -0,0 +1,129 @@ +<template> + <u-transition + mode="fade" + :customStyle="backTopStyle" + :show="show" + > + <view + class="u-back-top" + :style="[contentStyle]" + v-if="!$slots.default && !$slots.$default" + @click="backToTop" + > + <u-icon + :name="icon" + :custom-style="iconStyle" + ></u-icon> + <text + v-if="text" + class="u-back-top__text" + >{{text}}</text> + </view> + <slot v-else /> + </u-transition> +</template> + +<script> + import props from './props.js'; + // #ifdef APP-NVUE + const dom = weex.requireModule('dom') + // #endif + /** + * backTop ������������ + * @description ������������������������������������������������������������������������������������������������������������������������ + * @tutorial https://uviewui.com/components/backTop.html + * + * @property {String} mode ������������������������circle-���������square-������ ��������� 'circle' ��� + * @property {String} icon ��������������� ��������� 'arrow-upward' ��� ��������������������� + * @property {String} text ������������ + * @property {String | Number} duration ������������������������ ��������� 100��� + * @property {String | Number} scrollTop ������������ ��������� 0 ��� + * @property {String | Number} top ���������������������������������������px ��������� 400 ��� + * @property {String | Number} bottom ���������������������������������������������px ��������� 100 ��� + * @property {String | Number} right ���������������������������������������������px ��������� 20 ��� + * @property {String | Number} zIndex ������ ��������� 9 ��� + * @property {Object<Object>} iconStyle ������������������������������ ��������� {color: '#909399',fontSize: '19px'}��� + * @property {Object} customStyle ��������������������������������� + * + * @example <u-back-top :scrollTop="scrollTop"></u-back-top> + */ + export default { + name: 'u-back-top', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + computed: { + backTopStyle() { + // ������������������ + const style = { + bottom: uni.$u.addUnit(this.bottom), + right: uni.$u.addUnit(this.right), + width: '40px', + height: '40px', + position: 'fixed', + zIndex: 10, + } + return style + }, + show() { + return uni.$u.getPx(this.scrollTop) > uni.$u.getPx(this.top) + }, + contentStyle() { + const style = {} + let radius = 0 + // ������������ + if(this.mode === 'circle') { + radius = '100px' + } else { + radius = '4px' + } + // ������������������nvue������������������������ + style.borderTopLeftRadius = radius + style.borderTopRightRadius = radius + style.borderBottomLeftRadius = radius + style.borderBottomRightRadius = radius + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) + } + }, + methods: { + backToTop() { + // #ifdef APP-NVUE + if (!this.$parent.$refs['u-back-top']) { + uni.$u.error(`nvue������������������������������������������"ref='u-back-top'`) + } + dom.scrollToElement(this.$parent.$refs['u-back-top'], { + offset: 0 + }) + // #endif + + // #ifndef APP-NVUE + uni.pageScrollTo({ + scrollTop: 0, + duration: this.duration + }); + // #endif + this.$emit('click') + } + } + } +</script> + +<style lang="scss" scoped> + @import '../../libs/css/components.scss'; + $u-back-top-flex:1 !default; + $u-back-top-height:100% !default; + $u-back-top-background-color:#E1E1E1 !default; + $u-back-top-tips-font-size:12px !default; + .u-back-top { + @include flex; + flex-direction: column; + align-items: center; + flex:$u-back-top-flex; + height: $u-back-top-height; + justify-content: center; + background-color: $u-back-top-background-color; + + &__tips { + font-size:$u-back-top-tips-font-size; + transform: scale(0.8); + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-badge/props.js b/uni_modules/uview-ui/components/u-badge/props.js new file mode 100644 index 0000000..74c032c --- /dev/null +++ b/uni_modules/uview-ui/components/u-badge/props.js @@ -0,0 +1,72 @@ +export default { + props: { + // ������������������ + isDot: { + type: Boolean, + default: uni.$u.props.badge.isDot + }, + // ��������������� + value: { + type: [Number, String], + default: uni.$u.props.badge.value + }, + // ������������ + show: { + type: Boolean, + default: uni.$u.props.badge.show + }, + // ������������������������������������ '{max}+' + max: { + type: [Number, String], + default: uni.$u.props.badge.max + }, + // ���������������error|warning|success|primary + type: { + type: String, + default: uni.$u.props.badge.type + }, + // ������������ 0 ������������������ Badge + showZero: { + type: Boolean, + default: uni.$u.props.badge.showZero + }, + // ���������������������������type������������������type��������������� + bgColor: { + type: [String, null], + default: uni.$u.props.badge.bgColor + }, + // ������������ + color: { + type: [String, null], + default: uni.$u.props.badge.color + }, + // ���������������circle-���������������������horn-������������������ + shape: { + type: String, + default: uni.$u.props.badge.shape + }, + // ������������������������������overflow|ellipsis|limit + // overflow���������max���������������������������`${max}+` + // ellipsis���������max���������������������`${max}...` + // limit���������1000���������������������������1000���������`${value/1000}K`���������2.2k���3.34w���������������2��������� + numberType: { + type: String, + default: uni.$u.props.badge.numberType + }, + // ������badge��������������������������� [x, y]���������������������top���right���������absolute���true��������� + offset: { + type: Array, + default: uni.$u.props.badge.offset + }, + // ��������������������������������� + inverted: { + type: Boolean, + default: uni.$u.props.badge.inverted + }, + // ������������������ + absolute: { + type: Boolean, + default: uni.$u.props.badge.absolute + } + } +} diff --git a/uni_modules/uview-ui/components/u-badge/u-badge.vue b/uni_modules/uview-ui/components/u-badge/u-badge.vue new file mode 100644 index 0000000..53cfc81 --- /dev/null +++ b/uni_modules/uview-ui/components/u-badge/u-badge.vue @@ -0,0 +1,171 @@ +<template> + <text + v-if="show && ((Number(value) === 0 ? showZero : true) || isDot)" + :class="[isDot ? 'u-badge--dot' : 'u-badge--not-dot', inverted && 'u-badge--inverted', shape === 'horn' && 'u-badge--horn', `u-badge--${type}${inverted ? '--inverted' : ''}`]" + :style="[$u.addStyle(customStyle), badgeStyle]" + class="u-badge" + >{{ isDot ? '' :showValue }}</text> +</template> + +<script> + import props from './props.js'; + /** + * badge ��������� + * @description ��������������������������������������������������������������������������������������������������������������������������������� + * @tutorial https://uviewui.com/components/badge.html + * + * @property {Boolean} isDot ������������������ ��������� false ��� + * @property {String | Number} value ��������������� + * @property {Boolean} show ������������ ��������� true ��� + * @property {String | Number} max ������������������������������������ '{max}+' ���������999��� + * @property {String} type ���������������error|warning|success|primary ��������� 'error' ��� + * @property {Boolean} showZero ������������ 0 ������������������ Badge ��������� false ��� + * @property {String} bgColor ���������������������������type������������������type��������������� + * @property {String} color ������������ ��������� '#ffffff' ��� + * @property {String} shape ���������������circle-���������������������horn-������������������ ��������� 'circle' ��� + * @property {String} numberType ������������������������������overflow|ellipsis|limit ��������� 'overflow' ��� + * @property {Array}} offset ������badge��������������������������� [x, y]���������������������top���right���������absolute���true��������� + * @property {Boolean} inverted ������������������������������������������ false ��� + * @property {Boolean} absolute ��������������������������� false ��� + * @property {Object} customStyle ��������������������������������� + * @example <u-badge :type="type" :count="count"></u-badge> + */ + export default { + name: 'u-badge', + mixins: [uni.$u.mpMixin, props, uni.$u.mixin], + computed: { + // ���������badge��������������������������������� + boxStyle() { + let style = {}; + return style; + }, + // ��������������������� + badgeStyle() { + const style = {} + if(this.color) { + style.color = this.color + } + if (this.bgColor && !this.inverted) { + style.backgroundColor = this.bgColor + } + if (this.absolute) { + style.position = 'absolute' + // ���������������offset������ + if(this.offset.length) { + // top���right���������offset������������������������������������������������������������right������top + const top = this.offset[0] + const right = this.offset[1] || top + style.top = uni.$u.addUnit(top) + style.right = uni.$u.addUnit(right) + } + } + return style + }, + showValue() { + switch (this.numberType) { + case "overflow": + return Number(this.value) > Number(this.max) ? this.max + "+" : this.value + break; + case "ellipsis": + return Number(this.value) > Number(this.max) ? "..." : this.value + break; + case "limit": + return Number(this.value) > 999 ? Number(this.value) >= 9999 ? + Math.floor(this.value / 1e4 * 100) / 100 + "w" : Math.floor(this.value / + 1e3 * 100) / 100 + "k" : this.value + break; + default: + return Number(this.value) + } + }, + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + $u-badge-primary: $u-primary !default; + $u-badge-error: $u-error !default; + $u-badge-success: $u-success !default; + $u-badge-info: $u-info !default; + $u-badge-warning: $u-warning !default; + $u-badge-dot-radius: 100px !default; + $u-badge-dot-size: 8px !default; + $u-badge-dot-right: 4px !default; + $u-badge-dot-top: 0 !default; + $u-badge-text-font-size: 11px !default; + $u-badge-text-right: 10px !default; + $u-badge-text-padding: 2px 5px !default; + $u-badge-text-align: center !default; + $u-badge-text-color: #FFFFFF !default; + + .u-badge { + border-top-right-radius: $u-badge-dot-radius; + border-top-left-radius: $u-badge-dot-radius; + border-bottom-left-radius: $u-badge-dot-radius; + border-bottom-right-radius: $u-badge-dot-radius; + @include flex; + line-height: $u-badge-text-font-size; + text-align: $u-badge-text-align; + font-size: $u-badge-text-font-size; + color: $u-badge-text-color; + + &--dot { + height: $u-badge-dot-size; + width: $u-badge-dot-size; + } + + &--inverted { + font-size: 13px; + } + + &--not-dot { + padding: $u-badge-text-padding; + } + + &--horn { + border-bottom-left-radius: 0; + } + + &--primary { + background-color: $u-badge-primary; + } + + &--primary--inverted { + color: $u-badge-primary; + } + + &--error { + background-color: $u-badge-error; + } + + &--error--inverted { + color: $u-badge-error; + } + + &--success { + background-color: $u-badge-success; + } + + &--success--inverted { + color: $u-badge-success; + } + + &--info { + background-color: $u-badge-info; + } + + &--info--inverted { + color: $u-badge-info; + } + + &--warning { + background-color: $u-badge-warning; + } + + &--warning--inverted { + color: $u-badge-warning; + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-button/nvue.scss b/uni_modules/uview-ui/components/u-button/nvue.scss new file mode 100644 index 0000000..490db7d --- /dev/null +++ b/uni_modules/uview-ui/components/u-button/nvue.scss @@ -0,0 +1,46 @@ +$u-button-active-opacity:0.75 !default; +$u-button-loading-text-margin-left:4px !default; +$u-button-text-color: #FFFFFF !default; +$u-button-text-plain-error-color:$u-error !default; +$u-button-text-plain-warning-color:$u-warning !default; +$u-button-text-plain-success-color:$u-success !default; +$u-button-text-plain-info-color:$u-info !default; +$u-button-text-plain-primary-color:$u-primary !default; +.u-button { + &--active { + opacity: $u-button-active-opacity; + } + + &--active--plain { + background-color: rgb(217, 217, 217); + } + + &__loading-text { + margin-left:$u-button-loading-text-margin-left; + } + + &__text, + &__loading-text { + color:$u-button-text-color; + } + + &__text--plain--error { + color:$u-button-text-plain-error-color; + } + + &__text--plain--warning { + color:$u-button-text-plain-warning-color; + } + + &__text--plain--success{ + color:$u-button-text-plain-success-color; + } + + &__text--plain--info { + color:$u-button-text-plain-info-color; + } + + &__text--plain--primary { + color:$u-button-text-plain-primary-color; + } +} \ No newline at end of file diff --git a/uni_modules/uview-ui/components/u-button/props.js b/uni_modules/uview-ui/components/u-button/props.js new file mode 100644 index 0000000..07fd844 --- /dev/null +++ b/uni_modules/uview-ui/components/u-button/props.js @@ -0,0 +1,161 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-16 10:04:04 + * @LastAuthor : LQ + * @lastTime : 2021-08-16 10:04:24 + * @FilePath : /u-view2.0/uview-ui/components/u-button/props.js + */ +export default { + props: { + // ��������������� + hairline: { + type: Boolean, + default: uni.$u.props.button.hairline + }, + // ������������������������info���primary���error���warning���success + type: { + type: String, + default: uni.$u.props.button.type + }, + // ���������������large���normal���small���mini + size: { + type: String, + default: uni.$u.props.button.size + }, + // ���������������circle������������������������square��������������� + shape: { + type: String, + default: uni.$u.props.button.shape + }, + // ������������������ + plain: { + type: Boolean, + default: uni.$u.props.button.plain + }, + // ������������������ + disabled: { + type: Boolean, + default: uni.$u.props.button.disabled + }, + // ��������������� + loading: { + type: Boolean, + default: uni.$u.props.button.loading + }, + // ��������������������� + loadingText: { + type: [String, Number], + default: uni.$u.props.button.loadingText + }, + // ������������������������ + loadingMode: { + type: String, + default: uni.$u.props.button.loadingMode + }, + // ������������������ + loadingSize: { + type: [String, Number], + default: uni.$u.props.button.loadingSize + }, + // ���������������������������uniapp������������button������������������ + // https://uniapp.dcloud.io/component/button + openType: { + type: String, + default: uni.$u.props.button.openType + }, + // ������ <form> ������������������������������ <form> ��������� submit/reset ������ + // ���������submit���������������������reset������������������ + formType: { + type: String, + default: uni.$u.props.button.formType + }, + // ������ APP ��������� APP ������������������open-type=launchApp��������� + // ���������������������QQ��������������� + appParameter: { + type: String, + default: uni.$u.props.button.appParameter + }, + // ��������������������������������������������������������������������������������� + hoverStopPropagation: { + type: Boolean, + default: uni.$u.props.button.hoverStopPropagation + }, + // ������������������������������������zh_CN ���������������zh_TW ���������������en ��������������������������������� + lang: { + type: String, + default: uni.$u.props.button.lang + }, + // ���������������open-type="contact"������������������������������������ + sessionFrom: { + type: String, + default: uni.$u.props.button.sessionFrom + }, + // ������������������������������open-type="contact"��������� + // ��������������������������������������������� + sendMessageTitle: { + type: String, + default: uni.$u.props.button.sendMessageTitle + }, + // ���������������������������������������������������open-type="contact"��������� + // ��������������������������������������������������� + sendMessagePath: { + type: String, + default: uni.$u.props.button.sendMessagePath + }, + // ������������������������������open-type="contact"��������� + // ��������������������������������������������������� + sendMessageImg: { + type: String, + default: uni.$u.props.button.sendMessageImg + }, + // ������������������������������������������������������ true������������������������������������������������"���������������������������"��������� + // ���������������������������������������������������open-type="contact"��������� + showMessageCard: { + type: Boolean, + default: uni.$u.props.button.showMessageCard + }, + // ���������������������������������������data-xxx���������������target.dataset.name������ + dataName: { + type: String, + default: uni.$u.props.button.dataName + }, + // ������������������������������������������ + throttleTime: { + type: [String, Number], + default: uni.$u.props.button.throttleTime + }, + // ��������������������������������������������� + hoverStartTime: { + type: [String, Number], + default: uni.$u.props.button.hoverStartTime + }, + // ��������������������������������������������������� + hoverStayTime: { + type: [String, Number], + default: uni.$u.props.button.hoverStayTime + }, + // ������������������������������props������������������slot������������ + // nvue������������������������������ + text: { + type: [String, Number], + default: uni.$u.props.button.text + }, + // ������������ + icon: { + type: String, + default: uni.$u.props.button.icon + }, + // ������������ + iconColor: { + type: String, + default: uni.$u.props.button.icon + }, + // ���������������������������linear-gradient��������� + color: { + type: String, + default: uni.$u.props.button.color + } + } +} diff --git a/uni_modules/uview-ui/components/u-button/u-button.vue b/uni_modules/uview-ui/components/u-button/u-button.vue new file mode 100644 index 0000000..5494351 --- /dev/null +++ b/uni_modules/uview-ui/components/u-button/u-button.vue @@ -0,0 +1,490 @@ +<template> + <!-- #ifndef APP-NVUE --> + <button + :hover-start-time="Number(hoverStartTime)" + :hover-stay-time="Number(hoverStayTime)" + :form-type="formType" + :open-type="openType" + :app-parameter="appParameter" + :hover-stop-propagation="hoverStopPropagation" + :send-message-title="sendMessageTitle" + :send-message-path="sendMessagePath" + :lang="lang" + :data-name="dataName" + :session-from="sessionFrom" + :send-message-img="sendMessageImg" + :show-message-card="showMessageCard" + @getphonenumber="getphonenumber" + @getuserinfo="getuserinfo" + @error="error" + @opensetting="opensetting" + @launchapp="launchapp" + :hover-class="!disabled && !loading ? 'u-button--active' : ''" + class="u-button u-reset-button" + :style="[baseColor, $u.addStyle(customStyle)]" + @tap="clickHandler" + :class="bemClass" + > + <template v-if="loading"> + <u-loading-icon + :mode="loadingMode" + :size="loadingSize * 1.15" + :color="loadingColor" + ></u-loading-icon> + <text + class="u-button__loading-text" + :style="[{ fontSize: textSize + 'px' }]" + >{{ loadingText || text }}</text + > + </template> + <template v-else> + <u-icon + v-if="icon" + :name="icon" + :color="iconColorCom" + :size="textSize * 1.35" + :customStyle="{ marginRight: '2px' }" + ></u-icon> + <slot> + <text + class="u-button__text" + :style="[{ fontSize: textSize + 'px' }]" + >{{ text }}</text + > + </slot> + </template> + </button> + <!-- #endif --> + + <!-- #ifdef APP-NVUE --> + <view + :hover-start-time="Number(hoverStartTime)" + :hover-stay-time="Number(hoverStayTime)" + class="u-button" + :hover-class=" + !disabled && !loading && !color && (plain || type === 'info') + ? 'u-button--active--plain' + : !disabled && !loading && !plain + ? 'u-button--active' + : '' + " + @tap="clickHandler" + :class="bemClass" + :style="[baseColor, $u.addStyle(customStyle)]" + > + <template v-if="loading"> + <u-loading-icon + :mode="loadingMode" + :size="loadingSize * 1.15" + :color="loadingColor" + ></u-loading-icon> + <text + class="u-button__loading-text" + :style="[nvueTextStyle]" + :class="[plain && `u-button__text--plain--${type}`]" + >{{ loadingText || text }}</text + > + </template> + <template v-else> + <u-icon + v-if="icon" + :name="icon" + :color="iconColorCom" + :size="textSize * 1.35" + ></u-icon> + <text + class="u-button__text" + :style="[ + { + marginLeft: icon ? '2px' : 0, + }, + nvueTextStyle, + ]" + :class="[plain && `u-button__text--plain--${type}`]" + >{{ text }}</text + > + </template> + </view> + <!-- #endif --> +</template> + +<script> +import button from "../../libs/mixin/button.js"; +import openType from "../../libs/mixin/openType.js"; +import props from "./props.js"; +/** + * button ������ + * @description Button ������ + * @tutorial https://www.uviewui.com/components/button.html + * + * @property {Boolean} hairline ������������������������������ (������ true ) + * @property {String} type ������������������������info���primary���error���warning���success (������ 'info' ) + * @property {String} size ���������������large���normal���mini ��������� normal��� + * @property {String} shape ���������������circle������������������������square��������������� ��������� 'square' ��� + * @property {Boolean} plain ������������������������������������ ��������� false��� + * @property {Boolean} disabled ������������ ��������� false��� + * @property {Boolean} loading ������������������������ loading ������(App-nvue ������������ ios ���������������Android������������) ��������� false��� + * @property {String | Number} loadingText ��������������������� + * @property {String} loadingMode ������������������������ ��������� 'spinner' ��� + * @property {String | Number} loadingSize ������������������ ��������� 15 ��� + * @property {String} openType ���������������������������uniapp������������button������������������ + * @property {String} formType ������ <form> ������������������������������ <form> ��������� submit/reset ������ + * @property {String} appParameter ������ APP ��������� APP ������������������open-type=launchApp��������� ������������������������������QQ������������������ + * @property {Boolean} hoverStopPropagation ������������������������������������������������������������������������������������������ true ��� + * @property {String} lang ������������������������������������zh_CN ���������������zh_TW ���������������en ��������������� en ��� + * @property {String} sessionFrom ���������������openType="contact"��������� + * @property {String} sendMessageTitle ������������������������������openType="contact"��������� + * @property {String} sendMessagePath ���������������������������������������������������openType="contact"��������� + * @property {String} sendMessageImg ������������������������������openType="contact"��������� + * @property {Boolean} showMessageCard ������������������������������������������������������ true������������������������������������������������"���������������������������"������������������������������������������������������������openType="contact"������������������false��� + * @property {String} dataName ���������������������������������������data-xxx���������������target.dataset.name������ + * @property {String | Number} throttleTime ������������������������������������������ ��������� 0 ) + * @property {String | Number} hoverStartTime ��������������������������������������������� ��������� 0 ) + * @property {String | Number} hoverStayTime ��������������������������������������������������� ��������� 200 ) + * @property {String | Number} text ������������������������������props������������������slot���������������������nvue��������������������������������� + * @property {String} icon ������������ + * @property {String} iconColor ������������������ + * @property {String} color ���������������������������linear-gradient��������� + * @property {Object} customStyle ��������������������������������� + * + * @event {Function} click ������������������������������������������ + * @event {Function} getphonenumber open-type="getPhoneNumber"��������� + * @event {Function} getuserinfo ���������������������������������������������������������������������������������detail���������������������uni.getUserInfo + * @event {Function} error ������������������������������������������������ + * @event {Function} opensetting ������������������������������������������ + * @event {Function} launchapp ������ APP ��������������� + * @example <u-button>������</u-button> + */ +export default { + name: "u-button", + // #ifdef MP + mixins: [uni.$u.mpMixin, uni.$u.mixin, button, openType, props], + // #endif + // #ifndef MP + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + // #endif + data() { + return {}; + }, + computed: { + // ������bem��������������� + bemClass() { + // this.bem���������computed������������mixin��� + if (!this.color) { + return this.bem( + "button", + ["type", "shape", "size"], + ["disabled", "plain", "hairline"] + ); + } else { + // ������nvue������������������color���������������������������type������������������type��������������������������������������� + return this.bem( + "button", + ["shape", "size"], + ["disabled", "plain", "hairline"] + ); + } + }, + loadingColor() { + if (this.plain) { + // ���������������color������������color������������������type������������ + return this.color + ? this.color + : uni.$u.config.color[`u-${this.type}`]; + } + if (this.type === "info") { + return "#c9c9c9"; + } + return "rgb(200, 200, 200)"; + }, + iconColorCom() { + // ���������������������������������color������color��������������������������������� + // u-icon���color��������������������������������� + if (this.iconColor) return this.iconColor; + if (this.plain) { + return this.color ? this.color : this.type; + } else { + return this.type === "info" ? "#000000" : "#ffffff"; + } + }, + baseColor() { + let style = {}; + if (this.color) { + // ������������������color��������������������������������������������������������������� + style.color = this.plain ? this.color : "white"; + if (!this.plain) { + // ��������������������������������������������� + style["background-color"] = this.color; + } + if (this.color.indexOf("gradient") !== -1) { + // ���������������������������������������������������������������������backgroundImage��������������� + // weex���������������������borderWidth��������������������������������������������� + // ������weex������������������������������������������������������������������������������������������������ + style.borderTopWidth = 0; + style.borderRightWidth = 0; + style.borderBottomWidth = 0; + style.borderLeftWidth = 0; + if (!this.plain) { + style.backgroundImage = this.color; + } + } else { + // ��������������������������������������������� + style.borderColor = this.color; + style.borderWidth = "1px"; + style.borderStyle = "solid"; + } + } + return style; + }, + // nvue������������������������������������������������������������������������text��������������������������� + nvueTextStyle() { + let style = {}; + // ������������������color��������������������������������������������������������������� + if (this.type === "info") { + style.color = "#323233"; + } + if (this.color) { + style.color = this.plain ? this.color : "white"; + } + style.fontSize = this.textSize + "px"; + return style; + }, + // ������������ + textSize() { + let fontSize = 14, + { size } = this; + if (size === "large") fontSize = 16; + if (size === "normal") fontSize = 14; + if (size === "small") fontSize = 12; + if (size === "mini") fontSize = 10; + return fontSize; + }, + }, + methods: { + clickHandler() { + // ������������������������������������������ + if (!this.disabled && !this.loading) { + // ������������������������this.throttle��������������������������������� + uni.$u.throttle(() => { + this.$emit("click"); + }, this.throttleTime); + } + }, + // ���������������uniapp��������������������������������������������� + getphonenumber(res) { + this.$emit("getphonenumber", res); + }, + getuserinfo(res) { + this.$emit("getuserinfo", res); + }, + error(res) { + this.$emit("error", res); + }, + opensetting(res) { + this.$emit("opensetting", res); + }, + launchapp(res) { + this.$emit("launchapp", res); + }, + }, +}; +</script> + +<style lang="scss" scoped> +@import "../../libs/css/components.scss"; + +/* #ifndef APP-NVUE */ +@import "./vue.scss"; +/* #endif */ + +/* #ifdef APP-NVUE */ +@import "./nvue.scss"; +/* #endif */ + +$u-button-u-button-height: 40px !default; +$u-button-text-font-size: 15px !default; +$u-button-loading-text-font-size: 15px !default; +$u-button-loading-text-margin-left: 4px !default; +$u-button-large-width: 100% !default; +$u-button-large-height: 50px !default; +$u-button-normal-padding: 0 12px !default; +$u-button-large-padding: 0 15px !default; +$u-button-normal-font-size: 14px !default; +$u-button-small-min-width: 60px !default; +$u-button-small-height: 30px !default; +$u-button-small-padding: 0px 8px !default; +$u-button-mini-padding: 0px 8px !default; +$u-button-small-font-size: 12px !default; +$u-button-mini-height: 22px !default; +$u-button-mini-font-size: 10px !default; +$u-button-mini-min-width: 50px !default; +$u-button-disabled-opacity: 0.5 !default; +$u-button-info-color: #323233 !default; +$u-button-info-background-color: #fff !default; +$u-button-info-border-color: #ebedf0 !default; +$u-button-info-border-width: 1px !default; +$u-button-info-border-style: solid !default; +$u-button-success-color: #fff !default; +$u-button-success-background-color: $u-success !default; +$u-button-success-border-color: $u-button-success-background-color !default; +$u-button-success-border-width: 1px !default; +$u-button-success-border-style: solid !default; +$u-button-primary-color: #fff !default; +$u-button-primary-background-color: $u-primary !default; +$u-button-primary-border-color: $u-button-primary-background-color !default; +$u-button-primary-border-width: 1px !default; +$u-button-primary-border-style: solid !default; +$u-button-error-color: #fff !default; +$u-button-error-background-color: $u-error !default; +$u-button-error-border-color: $u-button-error-background-color !default; +$u-button-error-border-width: 1px !default; +$u-button-error-border-style: solid !default; +$u-button-warning-color: #fff !default; +$u-button-warning-background-color: $u-warning !default; +$u-button-warning-border-color: $u-button-warning-background-color !default; +$u-button-warning-border-width: 1px !default; +$u-button-warning-border-style: solid !default; +$u-button-block-width: 100% !default; +$u-button-circle-border-top-right-radius: 100px !default; +$u-button-circle-border-top-left-radius: 100px !default; +$u-button-circle-border-bottom-left-radius: 100px !default; +$u-button-circle-border-bottom-right-radius: 100px !default; +$u-button-square-border-top-right-radius: 3px !default; +$u-button-square-border-top-left-radius: 3px !default; +$u-button-square-border-bottom-left-radius: 3px !default; +$u-button-square-border-bottom-right-radius: 3px !default; +$u-button-icon-min-width: 1em !default; +$u-button-plain-background-color: #fff !default; +$u-button-hairline-border-width: 0.5px !default; + +.u-button { + height: $u-button-u-button-height; + position: relative; + align-items: center; + justify-content: center; + @include flex; + /* #ifndef APP-NVUE */ + box-sizing: border-box; + /* #endif */ + flex-direction: row; + + &__text { + font-size: $u-button-text-font-size; + } + + &__loading-text { + font-size: $u-button-loading-text-font-size; + margin-left: $u-button-loading-text-margin-left; + } + + &--large { + /* #ifndef APP-NVUE */ + width: $u-button-large-width; + /* #endif */ + height: $u-button-large-height; + padding: $u-button-large-padding; + } + + &--normal { + padding: $u-button-normal-padding; + font-size: $u-button-normal-font-size; + } + + &--small { + /* #ifndef APP-NVUE */ + min-width: $u-button-small-min-width; + /* #endif */ + height: $u-button-small-height; + padding: $u-button-small-padding; + font-size: $u-button-small-font-size; + } + + &--mini { + height: $u-button-mini-height; + font-size: $u-button-mini-font-size; + /* #ifndef APP-NVUE */ + min-width: $u-button-mini-min-width; + /* #endif */ + padding: $u-button-mini-padding; + } + + &--disabled { + opacity: $u-button-disabled-opacity; + } + + &--info { + color: $u-button-info-color; + background-color: $u-button-info-background-color; + border-color: $u-button-info-border-color; + border-width: $u-button-info-border-width; + border-style: $u-button-info-border-style; + } + + &--success { + color: $u-button-success-color; + background-color: $u-button-success-background-color; + border-color: $u-button-success-border-color; + border-width: $u-button-success-border-width; + border-style: $u-button-success-border-style; + } + + &--primary { + color: $u-button-primary-color; + background-color: $u-button-primary-background-color; + border-color: $u-button-primary-border-color; + border-width: $u-button-primary-border-width; + border-style: $u-button-primary-border-style; + } + + &--error { + color: $u-button-error-color; + background-color: $u-button-error-background-color; + border-color: $u-button-error-border-color; + border-width: $u-button-error-border-width; + border-style: $u-button-error-border-style; + } + + &--warning { + color: $u-button-warning-color; + background-color: $u-button-warning-background-color; + border-color: $u-button-warning-border-color; + border-width: $u-button-warning-border-width; + border-style: $u-button-warning-border-style; + } + + &--block { + @include flex; + width: $u-button-block-width; + } + + &--circle { + border-top-right-radius: $u-button-circle-border-top-right-radius; + border-top-left-radius: $u-button-circle-border-top-left-radius; + border-bottom-left-radius: $u-button-circle-border-bottom-left-radius; + border-bottom-right-radius: $u-button-circle-border-bottom-right-radius; + } + + &--square { + border-bottom-left-radius: $u-button-square-border-top-right-radius; + border-bottom-right-radius: $u-button-square-border-top-left-radius; + border-top-left-radius: $u-button-square-border-bottom-left-radius; + border-top-right-radius: $u-button-square-border-bottom-right-radius; + } + + &__icon { + /* #ifndef APP-NVUE */ + min-width: $u-button-icon-min-width; + line-height: inherit !important; + vertical-align: top; + /* #endif */ + } + + &--plain { + background-color: $u-button-plain-background-color; + } + + &--hairline { + border-width: $u-button-hairline-border-width !important; + } +} +</style> diff --git a/uni_modules/uview-ui/components/u-button/vue.scss b/uni_modules/uview-ui/components/u-button/vue.scss new file mode 100644 index 0000000..32019b2 --- /dev/null +++ b/uni_modules/uview-ui/components/u-button/vue.scss @@ -0,0 +1,80 @@ +// nvue���hover-class������ +$u-button-before-top:50% !default; +$u-button-before-left:50% !default; +$u-button-before-width:100% !default; +$u-button-before-height:100% !default; +$u-button-before-transform:translate(-50%, -50%) !default; +$u-button-before-opacity:0 !default; +$u-button-before-background-color:#000 !default; +$u-button-before-border-color:#000 !default; +$u-button-active-before-opacity:.15 !default; +$u-button-icon-margin-left:4px !default; +$u-button-plain-u-button-info-color:$u-info; +$u-button-plain-u-button-success-color:$u-success; +$u-button-plain-u-button-error-color:$u-error; +$u-button-plain-u-button-warning-color:$u-error; + +.u-button { + width: 100%; + + &__text { + white-space: nowrap; + line-height: 1; + } + + &:before { + position: absolute; + top:$u-button-before-top; + left:$u-button-before-left; + width:$u-button-before-width; + height:$u-button-before-height; + border: inherit; + border-radius: inherit; + transform:$u-button-before-transform; + opacity:$u-button-before-opacity; + content: " "; + background-color:$u-button-before-background-color; + border-color:$u-button-before-border-color; + } + + &--active { + &:before { + opacity: .15 + } + } + + &__icon+&__text:not(:empty), + &__loading-text { + margin-left:$u-button-icon-margin-left; + } + + &--plain { + &.u-button--primary { + color: $u-primary; + } + } + + &--plain { + &.u-button--info { + color:$u-button-plain-u-button-info-color; + } + } + + &--plain { + &.u-button--success { + color:$u-button-plain-u-button-success-color; + } + } + + &--plain { + &.u-button--error { + color:$u-button-plain-u-button-error-color; + } + } + + &--plain { + &.u-button--warning { + color:$u-button-plain-u-button-warning-color; + } + } +} diff --git a/uni_modules/uview-ui/components/u-calendar/header.vue b/uni_modules/uview-ui/components/u-calendar/header.vue new file mode 100644 index 0000000..dc4f7d0 --- /dev/null +++ b/uni_modules/uview-ui/components/u-calendar/header.vue @@ -0,0 +1,99 @@ +<template> + <view class="u-calendar-header u-border-bottom"> + <text + class="u-calendar-header__title" + v-if="showTitle" + >{{ title }}</text> + <text + class="u-calendar-header__subtitle" + v-if="showSubtitle" + >{{ subtitle }}</text> + <view class="u-calendar-header__weekdays"> + <text class="u-calendar-header__weekdays__weekday">���</text> + <text class="u-calendar-header__weekdays__weekday">���</text> + <text class="u-calendar-header__weekdays__weekday">���</text> + <text class="u-calendar-header__weekdays__weekday">���</text> + <text class="u-calendar-header__weekdays__weekday">���</text> + <text class="u-calendar-header__weekdays__weekday">���</text> + <text class="u-calendar-header__weekdays__weekday">���</text> + </view> + </view> +</template> + +<script> + export default { + name: 'u-calendar-header', + mixins: [uni.$u.mpMixin, uni.$u.mixin], + props: { + // ������ + title: { + type: String, + default: '' + }, + // ��������� + subtitle: { + type: String, + default: '' + }, + // ������������������ + showTitle: { + type: Boolean, + default: true + }, + // ��������������������� + showSubtitle: { + type: Boolean, + default: true + }, + }, + data() { + return { + + } + }, + methods: { + name() { + + } + }, + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-calendar-header { + padding-bottom: 4px; + + &__title { + font-size: 16px; + color: $u-main-color; + text-align: center; + height: 42px; + line-height: 42px; + font-weight: bold; + } + + &__subtitle { + font-size: 14px; + color: $u-main-color; + height: 40px; + text-align: center; + line-height: 40px; + font-weight: bold; + } + + &__weekdays { + @include flex; + justify-content: space-between; + + &__weekday { + font-size: 13px; + color: $u-main-color; + line-height: 30px; + flex: 1; + text-align: center; + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-calendar/month.vue b/uni_modules/uview-ui/components/u-calendar/month.vue new file mode 100644 index 0000000..c20937f --- /dev/null +++ b/uni_modules/uview-ui/components/u-calendar/month.vue @@ -0,0 +1,579 @@ +<template> + <view class="u-calendar-month-wrapper" ref="u-calendar-month-wrapper"> + <view v-for="(item, index) in months" :key="index" :class="[`u-calendar-month-${index}`]" + :ref="`u-calendar-month-${index}`" :id="`month-${index}`"> + <text v-if="index !== 0" class="u-calendar-month__title">{{ item.year }}���{{ item.month }}���</text> + <view class="u-calendar-month__days"> + <view v-if="showMark" class="u-calendar-month__days__month-mark-wrapper"> + <text class="u-calendar-month__days__month-mark-wrapper__text">{{ item.month }}</text> + </view> + <view class="u-calendar-month__days__day" v-for="(item1, index1) in item.date" :key="index1" + :style="[dayStyle(index, index1, item1)]" @tap="clickHandler(index, index1, item1)" + :class="[item1.selected && 'u-calendar-month__days__day__select--selected']"> + <view class="u-calendar-month__days__day__select" :style="[daySelectStyle(index, index1, item1)]"> + <text class="u-calendar-month__days__day__select__info" + :class="[item1.disabled && 'u-calendar-month__days__day__select__info--disabled']" + :style="[textStyle(item1)]">{{ item1.day }}</text> + <text v-if="getBottomInfo(index, index1, item1)" + class="u-calendar-month__days__day__select__buttom-info" + :class="[item1.disabled && 'u-calendar-month__days__day__select__buttom-info--disabled']" + :style="[textStyle(item1)]">{{ getBottomInfo(index, index1, item1) }}</text> + <text v-if="item1.dot" class="u-calendar-month__days__day__select__dot"></text> + </view> + </view> + </view> + </view> + </view> +</template> + +<script> + // #ifdef APP-NVUE + // ������nvue��������������������������������������������������������������������������� + const dom = uni.requireNativePlugin('dom') + // #endif + import dayjs from '../../libs/util/dayjs.js'; + export default { + name: 'u-calendar-month', + mixins: [uni.$u.mpMixin, uni.$u.mixin], + props: { + // ��������������������������� + showMark: { + type: Boolean, + default: true + }, + // ������������������������������������������������ + color: { + type: String, + default: '#3c9cff' + }, + // ������������ + months: { + type: Array, + default: () => [] + }, + // ������������������ + mode: { + type: String, + default: 'single' + }, + // ������������ + rowHeight: { + type: [String, Number], + default: 58 + }, + // mode=multiple��������������������������������� + maxCount: { + type: [String, Number], + default: Infinity + }, + // mode=range������������������������������������������ + startText: { + type: String, + default: '������' + }, + // mode=range��������������������������������������������� + endText: { + type: String, + default: '������' + }, + // ������������������������mode���multiple���range������������������������ + defaultDate: { + type: [Array, String, Date], + default: null + }, + // ��������������������� + minDate: { + type: [String, Number], + default: 0 + }, + // ������������������ + maxDate: { + type: [String, Number], + default: 0 + }, + // ������������������maxDate��������������������������� + maxMonth: { + type: [String, Number], + default: 2 + }, + // ��������������������������������������������������������� + readonly: { + type: Boolean, + default: uni.$u.props.calendar.readonly + }, + // ���������������������������������������������������mode = range��������� + maxRange: { + type: [Number, String], + default: Infinity + }, + // ���������������������������������������������������������mode = range��������� + rangePrompt: { + type: String, + default: '' + }, + // ���������������������������������������������������������������������mode = range��������� + showRangePrompt: { + type: Boolean, + default: true + }, + // ������������������������������������������������������mode = range��������� + allowSameDay: { + type: Boolean, + default: false + } + }, + data() { + return { + // ��������������������� + width: 0, + // ���������������������item + item: {}, + selected: [] + } + }, + watch: { + selectedChange: { + immediate: true, + handler(n) { + this.setDefaultDate() + } + } + }, + computed: { + // ��������������������������������������������������������������������������������� + selectedChange() { + return [this.minDate, this.maxDate, this.defaultDate] + }, + dayStyle(index1, index2, item) { + return (index1, index2, item) => { + const style = {} + let week = item.week + // ������������������������������������2��������� + const dayWidth = Number(parseFloat(this.width / 7).toFixed(3).slice(0, -1)) + // ��������������������������� + // #ifdef APP-NVUE + style.width = uni.$u.addUnit(dayWidth) + // #endif + style.height = uni.$u.addUnit(this.rowHeight) + if (index2 === 0) { + // ������������������������������������0������������������������������������������������������������������������item������ + week = (week === 0 ? 7 : week) - 1 + style.marginLeft = uni.$u.addUnit(week * dayWidth) + } + if (this.mode === 'range') { + // ������������������������������������DCloud���������iOS������������������������������������������bug + style.paddingLeft = 0 + style.paddingRight = 0 + style.paddingBottom = 0 + style.paddingTop = 0 + } + return style + } + }, + daySelectStyle() { + return (index1, index2, item) => { + let date = dayjs(item.date).format("YYYY-MM-DD"), + style = {} + // ������date���������selected������������������������������������������0���������������dateSame���������������������������includes������ + if (this.selected.some(item => this.dateSame(item, date))) { + style.backgroundColor = this.color + } + if (this.mode === 'single') { + if (date === this.selected[0]) { + // ���������������nvue������������������������������������������������������������������������������ + style.borderTopLeftRadius = '3px' + style.borderBottomLeftRadius = '3px' + style.borderTopRightRadius = '3px' + style.borderBottomRightRadius = '3px' + } + } else if (this.mode === 'range') { + if (this.selected.length >= 2) { + const len = this.selected.length - 1 + // ��������������������������������������������������� + if (this.dateSame(date, this.selected[0])) { + style.borderTopLeftRadius = '3px' + style.borderBottomLeftRadius = '3px' + } + // ������������������������������������������������������ + if (this.dateSame(date, this.selected[len])) { + style.borderTopRightRadius = '3px' + style.borderBottomRightRadius = '3px' + } + // ��������������������������������������������������������������������������������������������������������������������������������������� + if (dayjs(date).isAfter(dayjs(this.selected[0])) && dayjs(date).isBefore(dayjs(this + .selected[len]))) { + style.backgroundColor = uni.$u.colorGradient(this.color, '#ffffff', 100)[90] + // ������������������������������������������������������������������������mark������������ + style.opacity = 0.7 + } + } else if (this.selected.length === 1) { + // ������������������������������������DCloud���������iOS������������������������������������������bug + // ������������������������������nvue���iOS���uni-app���bug��������������������������� + style.borderTopLeftRadius = '3px' + style.borderBottomLeftRadius = '3px' + } + } else { + if (this.selected.some(item => this.dateSame(item, date))) { + style.borderTopLeftRadius = '3px' + style.borderBottomLeftRadius = '3px' + style.borderTopRightRadius = '3px' + style.borderBottomRightRadius = '3px' + } + } + return style + } + }, + // ��������������������������� + textStyle() { + return (item) => { + const date = dayjs(item.date).format("YYYY-MM-DD"), + style = {} + // ������������������������������������������ + if (this.selected.some(item => this.dateSame(item, date))) { + style.color = '#ffffff' + } + if (this.mode === 'range') { + const len = this.selected.length - 1 + // ��������������������������������������������������������������������������������������������������������������� + if (dayjs(date).isAfter(dayjs(this.selected[0])) && dayjs(date).isBefore(dayjs(this + .selected[len]))) { + style.color = this.color + } + } + return style + } + }, + // ��������������������������� + getBottomInfo() { + return (index1, index2, item) => { + const date = dayjs(item.date).format("YYYY-MM-DD") + const bottomInfo = item.bottomInfo + // ������������������������������������������������������������0��� + if (this.mode === 'range' && this.selected.length > 0) { + if (this.selected.length === 1) { + // ������������������������������������������������������������������������������������������������������������������ + if (this.dateSame(date, this.selected[0])) return this.startText + else return bottomInfo + } else { + const len = this.selected.length - 1 + // ������������������������������2��������������������������������������������������������������� + if (this.dateSame(date, this.selected[0]) && this.dateSame(date, this.selected[1]) && + len === 1) { + // ���������������2������������������������������������������������������������������item��� + return `${this.startText}/${this.endText}` + } else if (this.dateSame(date, this.selected[0])) { + return this.startText + } else if (this.dateSame(date, this.selected[len])) { + return this.endText + } else { + return bottomInfo + } + } + } else { + return bottomInfo + } + } + } + }, + mounted() { + this.init() + }, + methods: { + init() { + // ��������������������� + this.$emit('monthSelected', this.selected) + this.$nextTick(() => { + // ������������������������������������������������������������������������������������������������������������������������������������ + // ������nvue������$nextTick���������100%��������� + uni.$u.sleep(10).then(() => { + this.getWrapperWidth() + this.getMonthRect() + }) + }) + }, + // ������������������������������ + dateSame(date1, date2) { + return dayjs(date1).isSame(dayjs(date2)) + }, + // ������������������������������������������nvue���������������������������������������css������������������item��������� + getWrapperWidth() { + // #ifdef APP-NVUE + dom.getComponentRect(this.$refs['u-calendar-month-wrapper'], res => { + this.width = res.size.width + }) + // #endif + // #ifndef APP-NVUE + this.$uGetRect('.u-calendar-month-wrapper').then(size => { + this.width = size.width + }) + // #endif + }, + getMonthRect() { + // ������������������������������������������������������scroll-view��������������������������������������������������������� + const promiseAllArr = this.months.map((item, index) => this.getMonthRectByPromise( + `u-calendar-month-${index}`)) + // ��������������� + Promise.all(promiseAllArr).then( + sizes => { + let height = 1 + const topArr = [] + for (let i = 0; i < this.months.length; i++) { + // ���������months���������������scroll-view��������������������������������������������������� + topArr[i] = height + height += sizes[i].height + } + // ������������������������������this.months[i].top���������(������������)���������������������month���top������������������������������������������ + this.$emit('updateMonthTop', topArr) + }) + }, + // ��������������������������������� + getMonthRectByPromise(el) { + // #ifndef APP-NVUE + // $uGetRect���uView���������������������������������������������������������https://www.uviewui.com/js/getRect.html + // ���������������������this.$uGetRect���������������uni.$u.getRect������������������������������������ + return new Promise(resolve => { + this.$uGetRect(`.${el}`).then(size => { + resolve(size) + }) + }) + // #endif + + // #ifdef APP-NVUE + // nvue������������dom������������������������ + // ������������promise���������������������������������������then������ + return new Promise(resolve => { + dom.getComponentRect(this.$refs[el][0], res => { + resolve(res.size) + }) + }) + // #endif + }, + // ��������������������� + clickHandler(index1, index2, item) { + if (this.readonly) { + return; + } + this.item = item + const date = dayjs(item.date).format("YYYY-MM-DD") + if (item.disabled) return + // ��������������������������������������������������� + let selected = uni.$u.deepClone(this.selected) + if (this.mode === 'single') { + // ��������������������������������������������������������������� + selected = [date] + } else if (this.mode === 'multiple') { + if (selected.some(item => this.dateSame(item, date))) { + // ��������������������������������������������������������������������������������������������� + const itemIndex = selected.findIndex(item => item === date) + selected.splice(itemIndex, 1) + } else { + // ������������������������������������������������������������������������������������������������������������ + if (selected.length < this.maxCount) selected.push(date) + } + } else { + // ������������������ + if (selected.length === 0 || selected.length >= 2) { + // ������������������0������������2��������������������������������������������������������� + selected = [date] + } else if (selected.length === 1) { + // ��������������������������������� + const existsDate = selected[0] + // ������������������������������������������������������������������������������������������������ + if (dayjs(date).isBefore(existsDate)) { + selected = [date] + } else if (dayjs(date).isAfter(existsDate)) { + // ������������������������������������������������������������������������������������������ + if(dayjs(dayjs(date).subtract(this.maxRange, 'day')).isAfter(dayjs(selected[0])) && this.showRangePrompt) { + if(this.rangePrompt) { + uni.$u.toast(this.rangePrompt) + } else { + uni.$u.toast(`������������������������ ${this.maxRange} ���`) + } + return + } + // ������������������������������������������������������������������������ + selected.push(date) + const startDate = selected[0] + const endDate = selected[1] + const arr = [] + let i = 0 + do { + // ��������������������������������������������������������� + arr.push(dayjs(startDate).add(i, 'day').format("YYYY-MM-DD")) + i++ + // ��������������������������������������������������������������� + } while (dayjs(startDate).add(i, 'day').isBefore(dayjs(endDate))) + // ������������������������������������computed������������������������������arr������������������������������������������������������������������������ + arr.push(endDate) + selected = arr + } else { + // ��������������������������������������������������������������������������������������������������������������������� + if (selected[0] === date && !this.allowSameDay) return + selected.push(date) + } + } + } + this.setSelected(selected) + }, + // ������������������ + setDefaultDate() { + if (!this.defaultDate) { + // ��������������������������������������������������������������������������������� + const selected = [dayjs().format("YYYY-MM-DD")] + return this.setSelected(selected, false) + } + let defaultDate = [] + const minDate = this.minDate || dayjs().format("YYYY-MM-DD") + const maxDate = this.maxDate || dayjs(minDate).add(this.maxMonth - 1, 'month').format("YYYY-MM-DD") + if (this.mode === 'single') { + // ���������������������������������������������Date��������� + if (!uni.$u.test.array(this.defaultDate)) { + defaultDate = [dayjs(this.defaultDate).format("YYYY-MM-DD")] + } else { + defaultDate = [this.defaultDate[0]] + } + } else { + // ��������������������������������� + if (!uni.$u.test.array(this.defaultDate)) return + defaultDate = this.defaultDate + } + // ��������������������������������������������������������������������������������������������� + defaultDate = defaultDate.filter(item => { + return dayjs(item).isAfter(dayjs(minDate).subtract(1, 'day')) && dayjs(item).isBefore(dayjs( + maxDate).add(1, 'day')) + }) + this.setSelected(defaultDate, false) + }, + setSelected(selected, event = true) { + this.selected = selected + event && this.$emit('monthSelected', this.selected) + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-calendar-month-wrapper { + margin-top: 4px; + } + + .u-calendar-month { + + &__title { + font-size: 14px; + line-height: 42px; + height: 42px; + color: $u-main-color; + text-align: center; + font-weight: bold; + } + + &__days { + position: relative; + @include flex; + flex-wrap: wrap; + + &__month-mark-wrapper { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + @include flex; + justify-content: center; + align-items: center; + + &__text { + font-size: 155px; + color: rgba(231, 232, 234, 0.83); + } + } + + &__day { + @include flex; + padding: 2px; + /* #ifndef APP-NVUE */ + // vue���������css���������������������������������������������������������js������������������������������������������������������ + width: calc(100% / 7); + box-sizing: border-box; + /* #endif */ + + &__select { + flex: 1; + @include flex; + align-items: center; + justify-content: center; + position: relative; + + &__dot { + width: 7px; + height: 7px; + border-radius: 100px; + background-color: $u-error; + position: absolute; + top: 12px; + right: 7px; + } + + &__buttom-info { + color: $u-content-color; + text-align: center; + position: absolute; + bottom: 5px; + font-size: 10px; + text-align: center; + left: 0; + right: 0; + + &--selected { + color: #ffffff; + } + + &--disabled { + color: #cacbcd; + } + } + + &__info { + text-align: center; + font-size: 16px; + + &--selected { + color: #ffffff; + } + + &--disabled { + color: #cacbcd; + } + } + + &--selected { + background-color: $u-primary; + @include flex; + justify-content: center; + align-items: center; + flex: 1; + border-radius: 3px; + } + + &--range-selected { + opacity: 0.3; + border-radius: 0; + } + + &--range-start-selected { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + + &--range-end-selected { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + } + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-calendar/props.js b/uni_modules/uview-ui/components/u-calendar/props.js new file mode 100644 index 0000000..2ad7bc7 --- /dev/null +++ b/uni_modules/uview-ui/components/u-calendar/props.js @@ -0,0 +1,144 @@ +export default { + props: { + // ������������������ + title: { + type: String, + default: uni.$u.props.calendar.title + }, + // ������������������ + showTitle: { + type: Boolean, + default: uni.$u.props.calendar.showTitle + }, + // ��������������������� + showSubtitle: { + type: Boolean, + default: uni.$u.props.calendar.showSubtitle + }, + // ���������������������single-���������������������multiple-���������������������������range-������������������ + mode: { + type: String, + default: uni.$u.props.calendar.mode + }, + // mode=range������������������������������������������ + startText: { + type: String, + default: uni.$u.props.calendar.startText + }, + // mode=range��������������������������������������������� + endText: { + type: String, + default: uni.$u.props.calendar.endText + }, + // ��������������� + customList: { + type: Array, + default: uni.$u.props.calendar.customList + }, + // ������������������������������������������������ + color: { + type: String, + default: uni.$u.props.calendar.color + }, + // ��������������������� + minDate: { + type: [String, Number], + default: uni.$u.props.calendar.minDate + }, + // ������������������ + maxDate: { + type: [String, Number], + default: uni.$u.props.calendar.maxDate + }, + // ������������������������mode���multiple���range������������������������ + defaultDate: { + type: [Array, String, Date, null], + default: uni.$u.props.calendar.defaultDate + }, + // mode=multiple��������������������������������� + maxCount: { + type: [String, Number], + default: uni.$u.props.calendar.maxCount + }, + // ������������ + rowHeight: { + type: [String, Number], + default: uni.$u.props.calendar.rowHeight + }, + // ��������������������� + formatter: { + type: [Function, null], + default: uni.$u.props.calendar.formatter + }, + // ������������������ + showLunar: { + type: Boolean, + default: uni.$u.props.calendar.showLunar + }, + // ��������������������������� + showMark: { + type: Boolean, + default: uni.$u.props.calendar.showMark + }, + // ��������������������� + confirmText: { + type: String, + default: uni.$u.props.calendar.confirmText + }, + // ������������������������������������������ + confirmDisabledText: { + type: String, + default: uni.$u.props.calendar.confirmDisabledText + }, + // ������������������������ + show: { + type: Boolean, + default: uni.$u.props.calendar.show + }, + // ������������������������������������ + closeOnClickOverlay: { + type: Boolean, + default: uni.$u.props.calendar.closeOnClickOverlay + }, + // ��������������������������������������������������������� + readonly: { + type: Boolean, + default: uni.$u.props.calendar.readonly + }, + // ������������������������ + showConfirm: { + type: Boolean, + default: uni.$u.props.calendar.showConfirm + }, + // ���������������������������������������������������mode = range��������� + maxRange: { + type: [Number, String], + default: uni.$u.props.calendar.maxRange + }, + // ���������������������������������������������������������mode = range��������� + rangePrompt: { + type: String, + default: uni.$u.props.calendar.rangePrompt + }, + // ���������������������������������������������������������������������mode = range��������� + showRangePrompt: { + type: Boolean, + default: uni.$u.props.calendar.showRangePrompt + }, + // ������������������������������������������������������mode = range��������� + allowSameDay: { + type: Boolean, + default: uni.$u.props.calendar.allowSameDay + }, + // ��������� + round: { + type: [Boolean, String, Number], + default: uni.$u.props.calendar.round + }, + // ������������������������ + monthNum: { + type: [Number, String], + default: 3 + } + } +} diff --git a/uni_modules/uview-ui/components/u-calendar/u-calendar.vue b/uni_modules/uview-ui/components/u-calendar/u-calendar.vue new file mode 100644 index 0000000..511f993 --- /dev/null +++ b/uni_modules/uview-ui/components/u-calendar/u-calendar.vue @@ -0,0 +1,384 @@ +<template> + <u-popup + :show="show" + mode="bottom" + closeable + @close="close" + :round="round" + :closeOnClickOverlay="closeOnClickOverlay" + > + <view class="u-calendar"> + <uHeader + :title="title" + :subtitle="subtitle" + :showSubtitle="showSubtitle" + :showTitle="showTitle" + ></uHeader> + <scroll-view + :style="{ + height: $u.addUnit(listHeight) + }" + scroll-y + @scroll="onScroll" + :scroll-top="scrollTop" + :scrollIntoView="scrollIntoView" + > + <uMonth + :color="color" + :rowHeight="rowHeight" + :showMark="showMark" + :months="months" + :mode="mode" + :maxCount="maxCount" + :startText="startText" + :endText="endText" + :defaultDate="defaultDate" + :minDate="innerMinDate" + :maxDate="innerMaxDate" + :maxMonth="monthNum" + :readonly="readonly" + :maxRange="maxRange" + :rangePrompt="rangePrompt" + :showRangePrompt="showRangePrompt" + :allowSameDay="allowSameDay" + ref="month" + @monthSelected="monthSelected" + @updateMonthTop="updateMonthTop" + ></uMonth> + </scroll-view> + <slot name="footer" v-if="showConfirm"> + <view class="u-calendar__confirm"> + <u-button + shape="circle" + :text=" + buttonDisabled ? confirmDisabledText : confirmText + " + :color="color" + @click="confirm" + :disabled="buttonDisabled" + ></u-button> + </view> + </slot> + </view> + </u-popup> +</template> + +<script> +import uHeader from './header.vue' +import uMonth from './month.vue' +import props from './props.js' +import util from './util.js' +import dayjs from '../../libs/util/dayjs.js' +import Calendar from '../../libs/util/calendar.js' +/** + * Calendar ������ + * @description ������������������������������������������������������������������������������������������������������. + * @tutorial https://www.uviewui.com/components/calendar.html + * + * @property {String} title ������������ (������ ������������ ) + * @property {Boolean} showTitle ������������������ (������ true ) + * @property {Boolean} showSubtitle ��������������������� (������ true ) + * @property {String} mode ������������������ single-���������������������multiple-���������������������������range-������������������ ��� ������ 'single' ) + * @property {String} startText mode=range������������������������������������������ (������ '������' ) + * @property {String} endText mode=range��������������������������������������������� (������ '������' ) + * @property {Array} customList ��������������� + * @property {String} color ������������������������������������������������ (������ ���#3c9cff' ) + * @property {String | Number} minDate ��������������������� (������ 0 ) + * @property {String | Number} maxDate ������������������ (������ 0 ) + * @property {Array | String| Date} defaultDate ������������������������mode���multiple���range������������������������ + * @property {String | Number} maxCount mode=multiple��������������������������������� (������ Number.MAX_SAFE_INTEGER ) + * @property {String | Number} rowHeight ������������ (������ 56 ) + * @property {Function} formatter ��������������������� + * @property {Boolean} showLunar ������������������ (������ false ) + * @property {Boolean} showMark ��������������������������� (������ true ) + * @property {String} confirmText ��������������������� (������ '������' ) + * @property {String} confirmDisabledText ������������������������������������������ (������ '������' ) + * @property {Boolean} show ������������������������ (������ false ) + * @property {Boolean} closeOnClickOverlay ������������������������������������ (������ false ) + * @property {Boolean} readonly ��������������������������������������������������������� (������ false ) + * @property {String | Number} maxRange ���������������������������������������������������mode = range��������� + * @property {String} rangePrompt ���������������������������������������������������������mode = range��������� + * @property {Boolean} showRangePrompt ���������������������������������������������������������������������mode = range��������� (������ true ) + * @property {Boolean} allowSameDay ������������������������������������������������������mode = range��������� (������ false ) + * @property {Number|String} round ��������������������������� (������ 0 ) + * @property {Number|String} monthNum ��������������������������� (������ 3 ) + * + * @event {Function()} confirm ��������������������������� ��������������������������������� + * @event {Function()} close ��������������������� ��������������������������������������� + * @example <u-calendar :defaultDate="defaultDateMultiple" :show="show" mode="multiple" @confirm="confirm"> + </u-calendar> + * */ +export default { + name: 'u-calendar', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + components: { + uHeader, + uMonth + }, + data() { + return { + // ������������������������������ + months: [], + // ���������������������������������������������������index������ + monthIndex: 0, + // ��������������������������� + listHeight: 0, + // month������������������������������ + selected: [], + scrollIntoView: '', + scrollTop:0, + // ������������������ + innerFormatter: (value) => value + } + }, + watch: { + selectedChange: { + immediate: true, + handler(n) { + this.setMonth() + } + }, + // ������������������������������������ + show: { + immediate: true, + handler(n) { + this.setMonth() + } + } + }, + computed: { + // ������maxDate���minDate������������������(2021-10-10)���������������(���������)���������dayjs������������������������������������������������������������������������ + innerMaxDate() { + return uni.$u.test.number(this.maxDate) + ? Number(this.maxDate) + : this.maxDate + }, + innerMinDate() { + return uni.$u.test.number(this.minDate) + ? Number(this.minDate) + : this.minDate + }, + // ��������������������������������������������������������������������������������� + selectedChange() { + return [this.innerMinDate, this.innerMaxDate, this.defaultDate] + }, + subtitle() { + // ���������������this.months��������������������������������������������� + if (this.months.length) { + return `${this.months[this.monthIndex].year}���${ + this.months[this.monthIndex].month + }���` + } else { + return '' + } + }, + buttonDisabled() { + // ���������range���������������������������������������1���������������������������������disabled������ + if (this.mode === 'range') { + if (this.selected.length <= 1) { + return true + } else { + return false + } + } else { + return false + } + } + }, + mounted() { + this.start = Date.now() + this.init() + }, + methods: { + // ������������������������������������������������props������������������������ref������������ + setFormatter(e) { + this.innerFormatter = e + }, + // month������������������������������������������������������������ + monthSelected(e) { + this.selected = e + if (!this.showConfirm) { + // ������������������������������������������������������������������������������������������������2������������������������ + if ( + this.mode === 'multiple' || + this.mode === 'single' || + (this.mode === 'range' && this.selected.length >= 2) + ) { + this.$emit('confirm', this.selected) + } + } + }, + init() { + // ������maxDate���������������minDate + if ( + this.innerMaxDate && + this.innerMinDate && + new Date(this.innerMaxDate).getTime() < new Date(this.innerMinDate).getTime() + ) { + return uni.$u.error('maxDate������������minDate') + } + // ��������������������� + this.listHeight = this.rowHeight * 5 + 30 + this.setMonth() + }, + close() { + this.$emit('close') + }, + // ������������������ + confirm() { + if (!this.buttonDisabled) { + this.$emit('confirm', this.selected) + } + }, + // ������������������������������������ + getMonths(minDate, maxDate) { + const minYear = dayjs(minDate).year() + const minMonth = dayjs(minDate).month() + 1 + const maxYear = dayjs(maxDate).year() + const maxMonth = dayjs(maxDate).month() + 1 + return (maxYear - minYear) * 12 + (maxMonth - minMonth) + 1 + }, + // ������������������ + setMonth() { + // ������������������������ + const minDate = this.innerMinDate || dayjs().valueOf() + // ���������������������������������������������3������ + const maxDate = + this.innerMaxDate || + dayjs(minDate) + .add(this.monthNum - 1, 'month') + .valueOf() + // ��������������������������������������������������� + const months = uni.$u.range( + 1, + this.monthNum, + this.getMonths(minDate, maxDate) + ) + // ��������������� + this.months = [] + for (let i = 0; i < months; i++) { + this.months.push({ + date: new Array( + dayjs(minDate).add(i, 'month').daysInMonth() + ) + .fill(1) + .map((item, index) => { + // ���������������1-31 + let day = index + 1 + // ���������0-6���0��������� + const week = dayjs(minDate) + .add(i, 'month') + .date(day) + .day() + const date = dayjs(minDate) + .add(i, 'month') + .date(day) + .format('YYYY-MM-DD') + let bottomInfo = '' + if (this.showLunar) { + // ��������������������������� + const lunar = Calendar.solar2lunar( + dayjs(date).year(), + dayjs(date).month() + 1, + dayjs(date).date() + ) + bottomInfo = lunar.IDayCn + } + let config = { + day, + week, + // ������������������������������������������������������������������������disabled������ + disabled: + dayjs(date).isBefore( + dayjs(minDate).format('YYYY-MM-DD') + ) || + dayjs(date).isAfter( + dayjs(maxDate).format('YYYY-MM-DD') + ), + // ���������������������������������������formatter������������������������������������������������������������ + date: new Date(date), + bottomInfo, + dot: false, + month: + dayjs(minDate).add(i, 'month').month() + 1 + } + const formatter = + this.formatter || this.innerFormatter + return formatter(config) + }), + // ��������������������� + month: dayjs(minDate).add(i, 'month').month() + 1, + // ������������ + year: dayjs(minDate).add(i, 'month').year() + }) + } + + }, + // ������������������������������ + scrollIntoDefaultMonth(selected) { + // ������������������������������������������ + const _index = this.months.findIndex(({ + year, + month + }) => { + month = uni.$u.padZero(month) + return `${year}-${month}` === selected + }) + if (_index !== -1) { + // #ifndef MP-WEIXIN + this.$nextTick(() => { + this.scrollIntoView = `month-${_index}` + }) + // #endif + // #ifdef MP-WEIXIN + this.scrollTop = this.months[_index].top || 0; + // #endif + } + }, + // scroll-view������������ + onScroll(event) { + // ���������������0���������������������scroll-view��������������������������������������������� + const scrollTop = Math.max(0, event.detail.scrollTop) + // ��������������������������������������������������������������������������������������������������������������� + for (let i = 0; i < this.months.length; i++) { + if (scrollTop >= (this.months[i].top || this.listHeight)) { + this.monthIndex = i + } + } + }, + // ���������������top��� + updateMonthTop(topArr = []) { + // ���������������������top������������onScroll������������������ + topArr.map((item, index) => { + this.months[index].top = item + }) + + // ��������������������������� + if (!this.defaultDate) { + // ��������������������������������������������������������������������������������� + const selected = dayjs().format("YYYY-MM") + this.scrollIntoDefaultMonth(selected) + return + } + let selected = dayjs().format("YYYY-MM"); + // ���������������������������������������������Date��������� + if (!uni.$u.test.array(this.defaultDate)) { + selected = dayjs(this.defaultDate).format("YYYY-MM") + } else { + selected = dayjs(this.defaultDate[0]).format("YYYY-MM"); + } + this.scrollIntoDefaultMonth(selected) + } + } +} +</script> + +<style lang="scss" scoped> +@import '../../libs/css/components.scss'; + +.u-calendar { + &__confirm { + padding: 7px 18px; + } +} +</style> diff --git a/uni_modules/uview-ui/components/u-calendar/util.js b/uni_modules/uview-ui/components/u-calendar/util.js new file mode 100644 index 0000000..ca4736b --- /dev/null +++ b/uni_modules/uview-ui/components/u-calendar/util.js @@ -0,0 +1,85 @@ +export default { + methods: { + // ������������������ + setMonth() { + // ��������������� + const day = dayjs(this.date).date(1).day() + const start = day == 0 ? 6 : day - 1 + + // ������������ + const days = dayjs(this.date).endOf('month').format('D') + + // ��������������� + const prevDays = dayjs(this.date).endOf('month').subtract(1, 'month').format('D') + + // ������������ + const arr = [] + // ������������ + this.month = [] + + // ������������������ + arr.push( + ...new Array(start).fill(1).map((e, i) => { + const day = prevDays - start + i + 1 + + return { + value: day, + disabled: true, + date: dayjs(this.date).subtract(1, 'month').date(day).format('YYYY-MM-DD') + } + }) + ) + + // ������������������ + arr.push( + ...new Array(days - 0).fill(1).map((e, i) => { + const day = i + 1 + + return { + value: day, + date: dayjs(this.date).date(day).format('YYYY-MM-DD') + } + }) + ) + + // ��������������� + arr.push( + ...new Array(42 - days - start).fill(1).map((e, i) => { + const day = i + 1 + + return { + value: day, + disabled: true, + date: dayjs(this.date).add(1, 'month').date(day).format('YYYY-MM-DD') + } + }) + ) + + // ������������ + for (let n = 0; n < arr.length; n += 7) { + this.month.push( + arr.slice(n, n + 7).map((e, i) => { + e.index = i + n + + // ��������������� + const custom = this.customList.find((c) => c.date == e.date) + + // ������ + if (this.lunar) { + const { + IDayCn, + IMonthCn + } = this.getLunar(e.date) + e.lunar = IDayCn == '������' ? IMonthCn : IDayCn + } + + return { + ...e, + ...custom + } + }) + ) + } + } + } +} diff --git a/uni_modules/uview-ui/components/u-car-keyboard/props.js b/uni_modules/uview-ui/components/u-car-keyboard/props.js new file mode 100644 index 0000000..3553647 --- /dev/null +++ b/uni_modules/uview-ui/components/u-car-keyboard/props.js @@ -0,0 +1,14 @@ +export default { + props: { + // ��������������������������������� + random: { + type: Boolean, + default: false + }, + // ��������������������������������������������������� + autoChange: { + type: Boolean, + default: false + } + } +} diff --git a/uni_modules/uview-ui/components/u-car-keyboard/u-car-keyboard.vue b/uni_modules/uview-ui/components/u-car-keyboard/u-car-keyboard.vue new file mode 100644 index 0000000..51175b5 --- /dev/null +++ b/uni_modules/uview-ui/components/u-car-keyboard/u-car-keyboard.vue @@ -0,0 +1,311 @@ +<template> + <view + class="u-keyboard" + @touchmove.stop.prevent="noop" + > + <view + v-for="(group, i) in abc ? engKeyBoardList : areaList" + :key="i" + class="u-keyboard__button" + :index="i" + :class="[i + 1 === 4 && 'u-keyboard__button--center']" + > + <view + v-if="i === 3" + class="u-keyboard__button__inner-wrapper" + > + <view + class="u-keyboard__button__inner-wrapper__left" + hover-class="u-hover-class" + :hover-stay-time="200" + @tap="changeCarInputMode" + > + <text + class="u-keyboard__button__inner-wrapper__left__lang" + :class="[!abc && 'u-keyboard__button__inner-wrapper__left__lang--active']" + >���</text> + <text class="u-keyboard__button__inner-wrapper__left__line">/</text> + <text + class="u-keyboard__button__inner-wrapper__left__lang" + :class="[abc && 'u-keyboard__button__inner-wrapper__left__lang--active']" + >���</text> + </view> + </view> + <view + class="u-keyboard__button__inner-wrapper" + v-for="(item, j) in group" + :key="j" + > + <view + class="u-keyboard__button__inner-wrapper__inner" + :hover-stay-time="200" + @tap="carInputClick(i, j)" + hover-class="u-hover-class" + > + <text class="u-keyboard__button__inner-wrapper__inner__text">{{ item }}</text> + </view> + </view> + <view + v-if="i === 3" + @touchstart="backspaceClick" + @touchend="clearTimer" + class="u-keyboard__button__inner-wrapper" + > + <view + class="u-keyboard__button__inner-wrapper__right" + hover-class="u-hover-class" + :hover-stay-time="200" + > + <u-icon + size="28" + name="backspace" + color="#303133" + ></u-icon> + </view> + </view> + </view> + </view> +</template> + +<script> + import props from './props.js'; + /** + * keyboard ������������ + * @description ������uView������������������������������������������������������������������������������������3������������������������������������������������������ + * @tutorial https://uviewui.com/components/keyboard.html + * @property {Boolean} random ��������������������������� + * @event {Function} change ������������������ + * @event {Function} backspace ��������������������� + * @example <u-keyboard ref="uKeyboard" mode="car" v-model="show"></u-keyboard> + */ + export default { + name: "u-keyboard", + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + // ������������������abc=true������������������������bac=false��������������������������� + abc: false + }; + }, + computed: { + areaList() { + let data = [ + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���', + '���' + ]; + let tmp = []; + // ������������ + if (this.random) data = uni.$u.randomArray(data); + // ��������������������� + tmp[0] = data.slice(0, 10); + tmp[1] = data.slice(10, 20); + tmp[2] = data.slice(20, 30); + tmp[3] = data.slice(30, 36); + return tmp; + }, + engKeyBoardList() { + let data = [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + 'Q', + 'W', + 'E', + 'R', + 'T', + 'Y', + 'U', + 'I', + 'O', + 'P', + 'A', + 'S', + 'D', + 'F', + 'G', + 'H', + 'J', + 'K', + 'L', + 'Z', + 'X', + 'C', + 'V', + 'B', + 'N', + 'M' + ]; + let tmp = []; + if (this.random) data = uni.$u.randomArray(data); + tmp[0] = data.slice(0, 10); + tmp[1] = data.slice(10, 20); + tmp[2] = data.slice(20, 30); + tmp[3] = data.slice(30, 36); + return tmp; + } + }, + methods: { + // ������������������ + carInputClick(i, j) { + let value = ''; + // ��������������������������������������� + if (this.abc) value = this.engKeyBoardList[i][j]; + else value = this.areaList[i][j]; + // ������������������������������������������������������������ + if (!this.abc && this.autoChange) uni.$u.sleep(200).then(() => this.abc = true) + this.$emit('change', value); + }, + // ���������������������������������������������|������ + changeCarInputMode() { + this.abc = !this.abc; + }, + // ��������������� + backspaceClick() { + this.$emit('backspace'); + clearInterval(this.timer); //��������������������������������������������������� + this.timer = null; + this.timer = setInterval(() => { + this.$emit('backspace'); + }, 250); + }, + clearTimer() { + clearInterval(this.timer); + this.timer = null; + }, + } + }; +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + $u-car-keyboard-background-color: rgb(224, 228, 230) !default; + $u-car-keyboard-padding:6px 0 6px !default; + $u-car-keyboard-button-inner-width:64rpx !default; + $u-car-keyboard-button-inner-background-color:#FFFFFF !default; + $u-car-keyboard-button-height:80rpx !default; + $u-car-keyboard-button-inner-box-shadow:0 1px 0px #999992 !default; + $u-car-keyboard-button-border-radius:4px !default; + $u-car-keyboard-button-inner-margin:8rpx 5rpx !default; + $u-car-keyboard-button-text-font-size:16px !default; + $u-car-keyboard-button-text-color:$u-main-color !default; + $u-car-keyboard-center-inner-margin: 0 4rpx !default; + $u-car-keyboard-special-button-width:134rpx !default; + $u-car-keyboard-lang-font-size:16px !default; + $u-car-keyboard-lang-color:$u-main-color !default; + $u-car-keyboard-active-color:$u-primary !default; + $u-car-keyboard-line-font-size:15px !default; + $u-car-keyboard-line-color:$u-main-color !default; + $u-car-keyboard-line-margin:0 1px !default; + $u-car-keyboard-u-hover-class-background-color:#BBBCC6 !default; + + .u-keyboard { + @include flex(column); + justify-content: space-around; + background-color: $u-car-keyboard-background-color; + align-items: stretch; + padding: $u-car-keyboard-padding; + + &__button { + @include flex; + justify-content: center; + flex: 1; + /* #ifndef APP-NVUE */ + /* #endif */ + + &__inner-wrapper { + box-shadow: $u-car-keyboard-button-inner-box-shadow; + margin: $u-car-keyboard-button-inner-margin; + border-radius: $u-car-keyboard-button-border-radius; + + &__inner { + @include flex; + justify-content: center; + align-items: center; + width: $u-car-keyboard-button-inner-width; + background-color: $u-car-keyboard-button-inner-background-color; + height: $u-car-keyboard-button-height; + border-radius: $u-car-keyboard-button-border-radius; + + &__text { + font-size: $u-car-keyboard-button-text-font-size; + color: $u-car-keyboard-button-text-color; + } + } + + &__left, + &__right { + border-radius: $u-car-keyboard-button-border-radius; + width: $u-car-keyboard-special-button-width; + height: $u-car-keyboard-button-height; + background-color: $u-car-keyboard-u-hover-class-background-color; + @include flex; + justify-content: center; + align-items: center; + box-shadow: $u-car-keyboard-button-inner-box-shadow; + } + + &__left { + &__line { + font-size: $u-car-keyboard-line-font-size; + color: $u-car-keyboard-line-color; + margin: $u-car-keyboard-line-margin; + } + + &__lang { + font-size: $u-car-keyboard-lang-font-size; + color: $u-car-keyboard-lang-color; + + &--active { + color: $u-car-keyboard-active-color; + } + } + } + } + } + } + + .u-hover-class { + background-color: $u-car-keyboard-u-hover-class-background-color; + } +</style> diff --git a/uni_modules/uview-ui/components/u-cell-group/props.js b/uni_modules/uview-ui/components/u-cell-group/props.js new file mode 100644 index 0000000..350ef40 --- /dev/null +++ b/uni_modules/uview-ui/components/u-cell-group/props.js @@ -0,0 +1,14 @@ +export default { + props: { + // ������������ + title: { + type: String, + default: uni.$u.props.cellGroup.title + }, + // ��������������������� + border: { + type: Boolean, + default: uni.$u.props.cellGroup.border + } + } +} diff --git a/uni_modules/uview-ui/components/u-cell-group/u-cell-group.vue b/uni_modules/uview-ui/components/u-cell-group/u-cell-group.vue new file mode 100644 index 0000000..a9508c0 --- /dev/null +++ b/uni_modules/uview-ui/components/u-cell-group/u-cell-group.vue @@ -0,0 +1,61 @@ +<template> + <view :style="[$u.addStyle(customStyle)]" :class="[customClass]" class="u-cell-group"> + <view v-if="title" class="u-cell-group__title"> + <slot name="title"> + <text class="u-cell-group__title__text">{{ title }}</text> + </slot> + </view> + <view class="u-cell-group__wrapper"> + <u-line v-if="border"></u-line> + <slot /> + </view> + </view> +</template> + +<script> + import props from './props.js'; + /** + * cellGroup ��������� + * @description cell������������������������������������������������������������������������������������ + * @tutorial https://uviewui.com/components/cell.html + * + * @property {String} title ������������ + * @property {Boolean} border ��������������������� (������ true ) + * @property {Object} customStyle ��������������������������������� + * + * @event {Function} click ������cell��������������� + * @example <u-cell-group title="������������"> + */ + export default { + name: 'u-cell-group', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + $u-cell-group-title-padding: 16px 16px 8px !default; + $u-cell-group-title-font-size: 15px !default; + $u-cell-group-title-line-height: 16px !default; + $u-cell-group-title-color: $u-main-color !default; + + .u-cell-group { + flex: 1; + + &__title { + padding: $u-cell-group-title-padding; + + &__text { + font-size: $u-cell-group-title-font-size; + line-height: $u-cell-group-title-line-height; + color: $u-cell-group-title-color; + } + } + + &__wrapper { + position: relative; + } + } +</style> + diff --git a/uni_modules/uview-ui/components/u-cell/props.js b/uni_modules/uview-ui/components/u-cell/props.js new file mode 100644 index 0000000..da03330 --- /dev/null +++ b/uni_modules/uview-ui/components/u-cell/props.js @@ -0,0 +1,110 @@ +export default { + props: { + // ������ + title: { + type: [String, Number], + default: uni.$u.props.cell.title + }, + // ��������������������������� + label: { + type: [String, Number], + default: uni.$u.props.cell.label + }, + // ��������������� + value: { + type: [String, Number], + default: uni.$u.props.cell.value + }, + // ���������������������������������������(������������������������������������) + icon: { + type: String, + default: uni.$u.props.cell.icon + }, + // ������������cell + disabled: { + type: Boolean, + default: uni.$u.props.cell.disabled + }, + // ��������������������� + border: { + type: Boolean, + default: uni.$u.props.cell.border + }, + // ������������������������(������������������������value������) + center: { + type: Boolean, + default: uni.$u.props.cell.center + }, + // ������������������URL������ + url: { + type: String, + default: uni.$u.props.cell.url + }, + // ������������������������������������������uView���������route������������������������������������ + linkType: { + type: String, + default: uni.$u.props.cell.linkType + }, + // ������������������������(������������������������������������) + clickable: { + type: Boolean, + default: uni.$u.props.cell.clickable + }, + // ��������������������������������������������� + isLink: { + type: Boolean, + default: uni.$u.props.cell.isLink + }, + // ������������������������������������������(���������������������������input������) + required: { + type: Boolean, + default: uni.$u.props.cell.required + }, + // ��������������������� + rightIcon: { + type: String, + default: uni.$u.props.cell.rightIcon + }, + // ���������������������������������������left���up���down + arrowDirection: { + type: String, + default: uni.$u.props.cell.arrowDirection + }, + // ������������������ + iconStyle: { + type: [Object, String], + default: () => { + return uni.$u.props.cell.iconStyle + } + }, + // ��������������������������� + rightIconStyle: { + type: [Object, String], + default: () => { + return uni.$u.props.cell.rightIconStyle + } + }, + // ��������������� + titleStyle: { + type: [Object, String], + default: () => { + return uni.$u.props.cell.titleStyle + } + }, + // ���������������������������������large + size: { + type: String, + default: uni.$u.props.cell.size + }, + // ������cell������������������������ + stop: { + type: Boolean, + default: uni.$u.props.cell.stop + }, + // ������������cell������������������ + name: { + type: [Number, String], + default: uni.$u.props.cell.name + } + } +} diff --git a/uni_modules/uview-ui/components/u-cell/u-cell.vue b/uni_modules/uview-ui/components/u-cell/u-cell.vue new file mode 100644 index 0000000..b099c90 --- /dev/null +++ b/uni_modules/uview-ui/components/u-cell/u-cell.vue @@ -0,0 +1,229 @@ +<template> + <view class="u-cell" :class="[customClass]" :style="[$u.addStyle(customStyle)]" + :hover-class="(!disabled && (clickable || isLink)) ? 'u-cell--clickable' : ''" :hover-stay-time="250" + @tap="clickHandler"> + <view class="u-cell__body" :class="[ center && 'u-cell--center', size === 'large' && 'u-cell__body--large']"> + <view class="u-cell__body__content"> + <view class="u-cell__left-icon-wrap" v-if="$slots.icon || icon"> + <slot name="icon" v-if="$slots.icon"> + </slot> + <u-icon v-else :name="icon" :custom-style="iconStyle" :size="size === 'large' ? 22 : 18"></u-icon> + </view> + <view class="u-cell__title"> + <slot name="title"> + <text v-if="title" class="u-cell__title-text" :style="[titleTextStyle]" + :class="[disabled && 'u-cell--disabled', size === 'large' && 'u-cell__title-text--large']">{{ title }}</text> + </slot> + <slot name="label"> + <text class="u-cell__label" v-if="label" + :class="[disabled && 'u-cell--disabled', size === 'large' && 'u-cell__label--large']">{{ label }}</text> + </slot> + </view> + </view> + <slot name="value"> + <text class="u-cell__value" + :class="[disabled && 'u-cell--disabled', size === 'large' && 'u-cell__value--large']" + v-if="!$u.test.empty(value)">{{ value }}</text> + </slot> + <view class="u-cell__right-icon-wrap" v-if="$slots['right-icon'] || isLink" + :class="[`u-cell__right-icon-wrap--${arrowDirection}`]"> + <slot name="right-icon" v-if="$slots['right-icon']"> + </slot> + <u-icon v-else :name="rightIcon" :custom-style="rightIconStyle" :color="disabled ? '#c8c9cc' : 'info'" + :size="size === 'large' ? 18 : 16"></u-icon> + </view> + </view> + <u-line v-if="border"></u-line> + </view> +</template> + +<script> + import props from './props.js'; + /** + * cell ��������� + * @description cell������������������������������������������������������������������������������������ + * @tutorial https://uviewui.com/components/cell.html + * @property {String | Number} title ������ + * @property {String | Number} label ��������������������������� + * @property {String | Number} value ��������������� + * @property {String} icon ���������������������������������������(������������������������������������) + * @property {Boolean} disabled ������������cell + * @property {Boolean} border ��������������������� (������ true ) + * @property {Boolean} center ������������������������(������������������������value������) (������ false ) + * @property {String} url ������������������URL������ + * @property {String} linkType ������������������������������������������uView���������route������������������������������������ (������ 'navigateTo' ) + * @property {Boolean} clickable ������������������������(������������������������������������) ��������� false ��� + * @property {Boolean} isLink ��������������������������������������������� ��������� false ��� + * @property {Boolean} required ������������������������������������������(���������������������������input������) ��������� false ��� + * @property {String} rightIcon ��������������������� ��������� 'arrow-right'��� + * @property {String} arrowDirection ���������������������������������������left���up���down + * @property {Object | String} rightIconStyle ��������������������������� + * @property {Object | String} titleStyle ��������������� + * @property {Object | String} iconStyle ������������������ + * @property {String} size ��������������������������������� large���normal���mini + * @property {Boolean} stop ������cell������������������������ (������ true ) + * @property {Object} customStyle ��������������������������������� + * + * @event {Function} click ������cell��������������� + * @example ���������������������cell-group������������������������������������ + */ + export default { + name: 'u-cell', + data() { + return { + + } + }, + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + computed: { + titleTextStyle() { + return uni.$u.addStyle(this.titleStyle) + } + }, + methods: { + // ������cell + clickHandler(e) { + if (this.disabled) return + this.$emit('click', { + name: this.name + }) + // ���������������url(���props������������mixin������)��������������������� + this.openPage() + // ������������������������ + this.stop && this.preventEvent(e) + }, + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + $u-cell-padding: 10px 15px !default; + $u-cell-font-size: 15px !default; + $u-cell-line-height: 24px !default; + $u-cell-color: $u-main-color !default; + $u-cell-icon-size: 16px !default; + $u-cell-title-font-size: 15px !default; + $u-cell-title-line-height: 22px !default; + $u-cell-title-color: $u-main-color !default; + $u-cell-label-font-size: 12px !default; + $u-cell-label-color: $u-tips-color !default; + $u-cell-label-line-height: 18px !default; + $u-cell-value-font-size: 14px !default; + $u-cell-value-color: $u-content-color !default; + $u-cell-clickable-color: $u-bg-color !default; + $u-cell-disabled-color: #c8c9cc !default; + $u-cell-padding-top-large: 13px !default; + $u-cell-padding-bottom-large: 13px !default; + $u-cell-value-font-size-large: 15px !default; + $u-cell-label-font-size-large: 14px !default; + $u-cell-title-font-size-large: 16px !default; + $u-cell-left-icon-wrap-margin-right: 4px !default; + $u-cell-right-icon-wrap-margin-left: 4px !default; + $u-cell-title-flex:1 !default; + $u-cell-label-margin-top:5px !default; + + + .u-cell { + &__body { + @include flex(); + /* #ifndef APP-NVUE */ + box-sizing: border-box; + /* #endif */ + padding: $u-cell-padding; + font-size: $u-cell-font-size; + color: $u-cell-color; + // line-height: $u-cell-line-height; + align-items: center; + + &__content { + @include flex(row); + align-items: center; + flex: 1; + } + + &--large { + padding-top: $u-cell-padding-top-large; + padding-bottom: $u-cell-padding-bottom-large; + } + } + + &__left-icon-wrap, + &__right-icon-wrap { + @include flex(); + align-items: center; + // height: $u-cell-line-height; + font-size: $u-cell-icon-size; + } + + &__left-icon-wrap { + margin-right: $u-cell-left-icon-wrap-margin-right; + } + + &__right-icon-wrap { + margin-left: $u-cell-right-icon-wrap-margin-left; + transition: transform 0.3s; + + &--up { + transform: rotate(-90deg); + } + + &--down { + transform: rotate(90deg); + } + } + + &__title { + flex: $u-cell-title-flex; + + &-text { + font-size: $u-cell-title-font-size; + line-height: $u-cell-title-line-height; + color: $u-cell-title-color; + + &--large { + font-size: $u-cell-title-font-size-large; + } + } + + } + + &__label { + margin-top: $u-cell-label-margin-top; + font-size: $u-cell-label-font-size; + color: $u-cell-label-color; + line-height: $u-cell-label-line-height; + + &--large { + font-size: $u-cell-label-font-size-large; + } + } + + &__value { + text-align: right; + font-size: $u-cell-value-font-size; + line-height: $u-cell-line-height; + color: $u-cell-value-color; + + &--large { + font-size: $u-cell-value-font-size-large; + } + } + + &--clickable { + background-color: $u-cell-clickable-color; + } + + &--disabled { + color: $u-cell-disabled-color; + /* #ifndef APP-NVUE */ + cursor: not-allowed; + /* #endif */ + } + + &--center { + align-items: center; + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-checkbox-group/props.js b/uni_modules/uview-ui/components/u-checkbox-group/props.js new file mode 100644 index 0000000..2f818a1 --- /dev/null +++ b/uni_modules/uview-ui/components/u-checkbox-group/props.js @@ -0,0 +1,82 @@ +export default { + props: { + // ��������� + name: { + type: String, + default: uni.$u.props.checkboxGroup.name + }, + // ������������ + value: { + type: Array, + default: uni.$u.props.checkboxGroup.value + }, + // ���������circle-���������square-������ + shape: { + type: String, + default: uni.$u.props.checkboxGroup.shape + }, + // ������������������checkbox + disabled: { + type: Boolean, + default: uni.$u.props.checkboxGroup.disabled + }, + + // ���������������������������������������������������������parent���activeColor��� + activeColor: { + type: String, + default: uni.$u.props.checkboxGroup.activeColor + }, + // ������������������ + inactiveColor: { + type: String, + default: uni.$u.props.checkboxGroup.inactiveColor + }, + + // ������������������������������px + size: { + type: [String, Number], + default: uni.$u.props.checkboxGroup.size + }, + // ���������������row-���������column-������ + placement: { + type: String, + default: uni.$u.props.checkboxGroup.placement + }, + // label������������������px������ + labelSize: { + type: [String, Number], + default: uni.$u.props.checkboxGroup.labelSize + }, + // label��������������� + labelColor: { + type: [String], + default: uni.$u.props.checkboxGroup.labelColor + }, + // ������������������������������ + labelDisabled: { + type: Boolean, + default: uni.$u.props.checkboxGroup.labelDisabled + }, + // ������������ + iconColor: { + type: String, + default: uni.$u.props.checkboxGroup.iconColor + }, + // ������������������������px + iconSize: { + type: [String, Number], + default: uni.$u.props.checkboxGroup.iconSize + }, + // ������������������������������left-���������right-������ + iconPlacement: { + type: String, + default: uni.$u.props.checkboxGroup.iconPlacement + }, + // ��������������������������������������� + borderBottom: { + type: Boolean, + default: uni.$u.props.checkboxGroup.borderBottom + } + + } +} diff --git a/uni_modules/uview-ui/components/u-checkbox-group/u-checkbox-group.vue b/uni_modules/uview-ui/components/u-checkbox-group/u-checkbox-group.vue new file mode 100644 index 0000000..7a6b4fa --- /dev/null +++ b/uni_modules/uview-ui/components/u-checkbox-group/u-checkbox-group.vue @@ -0,0 +1,103 @@ +<template> + <view + class="u-checkbox-group" + :class="bemClass" + > + <slot></slot> + </view> +</template> + +<script> + import props from './props.js'; + /** + * checkboxGroup ������������ + * @description ��������������������������������������������������������������������������������������������� + * @tutorial https://www.uviewui.com/components/checkbox.html + * @property {String} name ��������� + * @property {Array} value ������������ + * @property {String} shape ���������circle-���������square-������ ��������� 'square' ��� + * @property {Boolean} disabled ������������������checkbox ��������� false ��� + * @property {String} activeColor ���������������������������������������������������������parent���activeColor��� ��������� '#2979ff' ��� + * @property {String} inactiveColor ������������������ ��������� '#c8c9cc' ��� + * @property {String | Number} size ��������������������� ������px ��������� 18 ��� + * @property {String} placement ���������������row-���������column-������ ��������� 'row' ��� + * @property {String | Number} labelSize label������������������px������ ��������� 14 ��� + * @property {String} labelColor label��������������� ��������� '#303133' ��� + * @property {Boolean} labelDisabled ������������������������������ (������ false ) + * @property {String} iconColor ������������ ��������� '#ffffff' ��� + * @property {String | Number} iconSize ������������������������px ��������� 12 ��� + * @property {String} iconPlacement ������������������������������left-���������right-������ ��������� 'left' ��� + * @property {Boolean} borderBottom placement���row��������������������������� ��������� false ��� + * @event {Function} change ���������checkbox��������������������������������������������������� + * @event {Function} input ������������v-model��������������������������������������������� + * @example <u-checkbox-group></u-checkbox-group> + */ + export default { + name: 'u-checkbox-group', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + computed: { + // ������computed���������������������������u-checkbox��������������������������������������������������������������������������������������������������������������� + // ������������������������������������������������������parentData������������watch���������������������������������������������������������������(u-checkbox-group) + // ��������������������������������������� + parentData() { + return [this.value, this.disabled, this.inactiveColor, this.activeColor, this.size, this.labelDisabled, this.shape, + this.iconSize, this.borderBottom, this.placement + ] + }, + bemClass() { + // this.bem���������computed������������mixin��� + return this.bem('checkbox-group', ['placement']) + }, + }, + watch: { + // ��������������������������������������������������������������������������������������� + parentData() { + if (this.children.length) { + this.children.map(child => { + // ���������������(u-checkbox)���������init���������������������������(������������������������������������������������������������������) + typeof(child.init) === 'function' && child.init() + }) + } + }, + }, + data() { + return { + + } + }, + created() { + this.children = [] + }, + methods: { + // ������������checkbox��������������������������� + unCheckedOther(childInstance) { + const values = [] + this.children.map(child => { + // ���������������checkbox������������������������ + if (child.isChecked) { + values.push(child.name) + } + }) + // ������������ + this.$emit('change', values) + // ������������v-model������������ + this.$emit('input', values) + }, + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-checkbox-group { + + &--row { + @include flex; + } + + &--column { + @include flex(column); + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-checkbox/props.js b/uni_modules/uview-ui/components/u-checkbox/props.js new file mode 100644 index 0000000..93f4fd9 --- /dev/null +++ b/uni_modules/uview-ui/components/u-checkbox/props.js @@ -0,0 +1,69 @@ +export default { + props: { + // checkbox��������� + name: { + type: [String, Number, Boolean], + default: uni.$u.props.checkbox.name + }, + // ���������square������������circle��������� + shape: { + type: String, + default: uni.$u.props.checkbox.shape + }, + // ��������������� + size: { + type: [String, Number], + default: uni.$u.props.checkbox.size + }, + // ������������������ + checked: { + type: Boolean, + default: uni.$u.props.checkbox.checked + }, + // ������������ + disabled: { + type: [String, Boolean], + default: uni.$u.props.checkbox.disabled + }, + // ���������������������������������������������������������parent���activeColor��� + activeColor: { + type: String, + default: uni.$u.props.checkbox.activeColor + }, + // ������������������ + inactiveColor: { + type: String, + default: uni.$u.props.checkbox.inactiveColor + }, + // ������������������������px + iconSize: { + type: [String, Number], + default: uni.$u.props.checkbox.iconSize + }, + // ������������ + iconColor: { + type: String, + default: uni.$u.props.checkbox.iconColor + }, + // label���������������������nvue������������slot������������������������������������������������������������ + label: { + type: [String, Number], + default: uni.$u.props.checkbox.label + }, + // label������������������px������ + labelSize: { + type: [String, Number], + default: uni.$u.props.checkbox.labelSize + }, + // label��������� + labelColor: { + type: String, + default: uni.$u.props.checkbox.labelColor + }, + // ������������������������������������������ + labelDisabled: { + type: [String, Boolean], + default: uni.$u.props.checkbox.labelDisabled + } + } +} diff --git a/uni_modules/uview-ui/components/u-checkbox/u-checkbox.vue b/uni_modules/uview-ui/components/u-checkbox/u-checkbox.vue new file mode 100644 index 0000000..6429cca --- /dev/null +++ b/uni_modules/uview-ui/components/u-checkbox/u-checkbox.vue @@ -0,0 +1,344 @@ +<template> + <view + class="u-checkbox" + :style="[checkboxStyle]" + @tap.stop="wrapperClickHandler" + :class="[`u-checkbox-label--${parentData.iconPlacement}`, parentData.borderBottom && parentData.placement === 'column' && 'u-border-bottom']" + > + <view + class="u-checkbox__icon-wrap" + @tap.stop="iconClickHandler" + :class="iconClasses" + :style="[iconWrapStyle]" + > + <slot name="icon"> + <u-icon + class="u-checkbox__icon-wrap__icon" + name="checkbox-mark" + :size="elIconSize" + :color="elIconColor" + /> + </slot> + </view> + <text + @tap.stop="labelClickHandler" + :style="{ + color: elDisabled ? elInactiveColor : elLabelColor, + fontSize: elLabelSize, + lineHeight: elLabelSize + }" + >{{label}}</text> + </view> +</template> + +<script> + import props from './props.js'; + /** + * checkbox ��������� + * @description ��������������������������������������������������������������������������������������������� + * @tutorial https://uviewui.com/components/checkbox.html + * @property {String | Number | Boolean} name checkbox������������������ + * @property {String} shape ���������square������������circle��������� + * @property {String | Number} size ��������������� + * @property {Boolean} checked ������������������ + * @property {String | Boolean} disabled ������������ + * @property {String} activeColor ���������������������������������������������������������parent���activeColor��� + * @property {String} inactiveColor ������������������ + * @property {String | Number} iconSize ������������������������px + * @property {String} iconColor ������������ + * @property {String | Number} label label���������������������nvue������������slot������������������������������������������������������������ + * @property {String} labelColor label��������� + * @property {String | Number} labelSize label������������������px������ + * @property {String | Boolean} labelDisabled ������������������������������������������ + * @property {Object} customStyle ��������������������������������� + * + * @event {Function} change ���������checkbox��������������������������������������������������� + * @example <u-checkbox v-model="checked" :disabled="false">������</u-checkbox> + */ + export default { + name: "u-checkbox", + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + isChecked: false, + // ���������������������������������������������������������computed���������this.parent.shape��������� + // ��������������������������� + parentData: { + iconSize: 12, + labelDisabled: null, + disabled: null, + shape: 'square', + activeColor: null, + inactiveColor: null, + size: 18, + value: null, + iconColor: null, + placement: 'row', + borderBottom: false, + iconPlacement: 'left' + } + } + }, + computed: { + // ������������������������������u-raios-group��������������������������������������������� + elDisabled() { + return this.disabled !== '' ? this.disabled : this.parentData.disabled !== null ? this.parentData.disabled : false; + }, + // ������������label������ + elLabelDisabled() { + return this.labelDisabled !== '' ? this.labelDisabled : this.parentData.labelDisabled !== null ? this.parentData.labelDisabled : + false; + }, + // ���������������������size���������������������21px + elSize() { + return this.size ? this.size : (this.parentData.size ? this.parentData.size : 21); + }, + // ���������������������������������������12px + elIconSize() { + return this.iconSize ? this.iconSize : (this.parentData.iconSize ? this.parentData.iconSize : 12); + }, + // ������������������������������ + elActiveColor() { + return this.activeColor ? this.activeColor : (this.parentData.activeColor ? this.parentData.activeColor : '#2979ff'); + }, + // ��������������������������������� + elInactiveColor() { + return this.inactiveColor ? this.inactiveColor : (this.parentData.inactiveColor ? this.parentData.inactiveColor : + '#c8c9cc'); + }, + // label��������� + elLabelColor() { + return this.labelColor ? this.labelColor : (this.parentData.labelColor ? this.parentData.labelColor : '#606266') + }, + // ��������������� + elShape() { + return this.shape ? this.shape : (this.parentData.shape ? this.parentData.shape : 'circle'); + }, + // label������ + elLabelSize() { + return uni.$u.addUnit(this.labelSize ? this.labelSize : (this.parentData.labelSize ? this.parentData.labelSize : + '15')) + }, + elIconColor() { + const iconColor = this.iconColor ? this.iconColor : (this.parentData.iconColor ? this.parentData.iconColor : + '#ffffff'); + // ��������������� + if (this.elDisabled) { + // disabled������������������������checkbox������������elInactiveColor + return this.isChecked ? this.elInactiveColor : 'transparent' + } else { + return this.isChecked ? iconColor : 'transparent' + } + }, + iconClasses() { + let classes = [] + // ��������������� + classes.push('u-checkbox__icon-wrap--' + this.elShape) + if (this.elDisabled) { + classes.push('u-checkbox__icon-wrap--disabled') + } + if (this.isChecked && this.elDisabled) { + classes.push('u-checkbox__icon-wrap--disabled--checked') + } + // ������������������������������������������������������������������������������������������������������","������������������ + // #ifdef MP-ALIPAY || MP-TOUTIAO + classes = classes.join(' ') + // #endif + return classes + }, + iconWrapStyle() { + // checkbox��������������� + const style = {} + style.backgroundColor = this.isChecked && !this.elDisabled ? this.elActiveColor : '#ffffff' + style.borderColor = this.isChecked && !this.elDisabled ? this.elActiveColor : this.elInactiveColor + style.width = uni.$u.addUnit(this.elSize) + style.height = uni.$u.addUnit(this.elSize) + // ������������������������������������������������������ + if (this.parentData.iconPlacement === 'right') { + style.marginRight = 0 + } + return style + }, + checkboxStyle() { + const style = {} + if (this.parentData.borderBottom && this.parentData.placement === 'row') { + uni.$u.error('���������������borderBottom���������true������������������u-checkbox-group���placement���������column���������') + } + // ��������������������������������������������������������������������������������������������������������������� + if (this.parentData.borderBottom && this.parentData.placement === 'column') { + style.paddingBottom = '8px' + } + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) + } + }, + mounted() { + this.init() + }, + methods: { + init() { + // ���������������������������provide/inject������������������������������������������������������created��������������������������� + this.updateParentData() + if (!this.parent) { + uni.$u.error('u-checkbox������������u-checkbox-group������������') + } + // ������������������������������������������������������������u-checkbox-group���value���������array��������������������� + if (this.checked) { + this.isChecked = true + } else if (uni.$u.test.array(this.parentData.value)) { + // ���������������������������this.name��������� + this.isChecked = this.parentData.value.some(item => { + return item === this.name + }) + } + }, + updateParentData() { + this.getParentData('u-checkbox-group') + }, + // ������������������������������������������������������������ + wrapperClickHandler(e) { + this.parentData.iconPlacement === 'right' && this.iconClickHandler(e) + }, + // ������������ + iconClickHandler(e) { + this.preventEvent(e) + // ������������������������������������������ + if (!this.elDisabled) { + this.setRadioCheckedStatus() + } + }, + // ������label + labelClickHandler(e) { + this.preventEvent(e) + // ���������������������������������label������������������������������������������������ + if (!this.elLabelDisabled && !this.elDisabled) { + this.setRadioCheckedStatus() + } + }, + emitEvent() { + this.$emit('change', this.isChecked) + // ������������u-form������������������������������������������������������������������������������������ + this.$nextTick(() => { + uni.$u.formValidate(this, 'change') + }) + }, + // ������������������������ + // ������������������������������������������������checked������true������������������������������������u-checkbox������ + // ������������������������u-checkbox���checked������������false(������������������������)��������������������������������������� + setRadioCheckedStatus() { + // ��������������������������������������������� + this.isChecked = !this.isChecked + this.emitEvent() + typeof this.parent.unCheckedOther === 'function' && this.parent.unCheckedOther(this) + } + }, + watch:{ + checked(){ + this.isChecked = this.checked + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + $u-checkbox-icon-wrap-margin-right:6px !default; + $u-checkbox-icon-wrap-font-size:6px !default; + $u-checkbox-icon-wrap-border-width:1px !default; + $u-checkbox-icon-wrap-border-color:#c8c9cc !default; + $u-checkbox-icon-wrap-icon-line-height:0 !default; + $u-checkbox-icon-wrap-circle-border-radius:100% !default; + $u-checkbox-icon-wrap-square-border-radius:3px !default; + $u-checkbox-icon-wrap-checked-color:#fff !default; + $u-checkbox-icon-wrap-checked-background-color:red !default; + $u-checkbox-icon-wrap-checked-border-color:#2979ff !default; + $u-checkbox-icon-wrap-disabled-background-color:#ebedf0 !default; + $u-checkbox-icon-wrap-disabled-checked-color:#c8c9cc !default; + $u-checkbox-label-margin-left:5px !default; + $u-checkbox-label-margin-right:12px !default; + $u-checkbox-label-color:$u-content-color !default; + $u-checkbox-label-font-size:15px !default; + $u-checkbox-label-disabled-color:#c8c9cc !default; + + .u-checkbox { + /* #ifndef APP-NVUE */ + @include flex(row); + /* #endif */ + overflow: hidden; + flex-direction: row; + align-items: center; + + &-label--left { + flex-direction: row + } + + &-label--right { + flex-direction: row-reverse; + justify-content: space-between + } + + &__icon-wrap { + /* #ifndef APP-NVUE */ + box-sizing: border-box; + // nvue������border-color��������������� + transition-property: border-color, background-color, color; + transition-duration: 0.2s; + /* #endif */ + color: $u-content-color; + @include flex; + align-items: center; + justify-content: center; + color: transparent; + text-align: center; + margin-right: $u-checkbox-icon-wrap-margin-right; + + font-size: $u-checkbox-icon-wrap-font-size; + border-width: $u-checkbox-icon-wrap-border-width; + border-color: $u-checkbox-icon-wrap-border-color; + border-style: solid; + + /* #ifdef MP-TOUTIAO */ + // ������������������������������������������������������0��������������������� + &__icon { + line-height: $u-checkbox-icon-wrap-icon-line-height; + } + + /* #endif */ + + &--circle { + border-radius: $u-checkbox-icon-wrap-circle-border-radius; + } + + &--square { + border-radius: $u-checkbox-icon-wrap-square-border-radius; + } + + &--checked { + color: $u-checkbox-icon-wrap-checked-color; + background-color: $u-checkbox-icon-wrap-checked-background-color; + border-color: $u-checkbox-icon-wrap-checked-border-color; + } + + &--disabled { + background-color: $u-checkbox-icon-wrap-disabled-background-color !important; + } + + &--disabled--checked { + color: $u-checkbox-icon-wrap-disabled-checked-color !important; + } + } + + &__label { + /* #ifndef APP-NVUE */ + word-wrap: break-word; + /* #endif */ + margin-left: $u-checkbox-label-margin-left; + margin-right: $u-checkbox-label-margin-right; + color: $u-checkbox-label-color; + font-size: $u-checkbox-label-font-size; + + &--disabled { + color: $u-checkbox-label-disabled-color; + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-circle-progress/props.js b/uni_modules/uview-ui/components/u-circle-progress/props.js new file mode 100644 index 0000000..d776cfb --- /dev/null +++ b/uni_modules/uview-ui/components/u-circle-progress/props.js @@ -0,0 +1,8 @@ +export default { + props: { + percentage: { + type: [String, Number], + default: uni.$u.props.circleProgress.percentage + } + } +} diff --git a/uni_modules/uview-ui/components/u-circle-progress/u-circle-progress.vue b/uni_modules/uview-ui/components/u-circle-progress/u-circle-progress.vue new file mode 100644 index 0000000..d1ee286 --- /dev/null +++ b/uni_modules/uview-ui/components/u-circle-progress/u-circle-progress.vue @@ -0,0 +1,198 @@ +<template> + <view class="u-circle-progress"> + <view class="u-circle-progress__left"> + <view + class="u-circle-progress__left__circle" + :style="[leftSyle]" + ref="left-circle" + > + + </view> + </view> + <view + class="u-circle-progress__right" + > + <view + class="u-circle-progress__right__circle" + ref="right-circle" + :style="[rightSyle]" + > + + </view> + </view> + <view class="u-circle-progress__circle"> + + </view> + </view> +</template> + +<script> + import props from './props.js'; + // #ifdef APP-NVUE + const animation = uni.requireNativePlugin('animation') + // #endif + /** + * CircleProgress ��������������� TODO: ��������� + * @description ������������������������������������������������������������������������������������������ + * @tutorial https://www.uviewui.com/components/circleProgress.html + * @property {String | Number} percentage ���������������������������������������������0-100 (������ 30 ) + * @example + */ + export default { + name: 'u-circle-progress', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + leftBorderColor: 'rgb(200, 200, 200)', + rightBorderColor: 'rgb(200, 200, 200)', + } + }, + computed: { + leftSyle() { + const style = {} + style.borderTopColor = this.leftBorderColor + style.borderRightColor = this.leftBorderColor + return style + }, + rightSyle() { + const style = {} + style.borderLeftColor = this.rightBorderColor + style.borderBottomColor = this.rightBorderColor + return style + } + }, + mounted() { + uni.$u.sleep().then(() => { + this.rightBorderColor = 'rgb(66, 185, 131)' + // this.init() + }) + }, + methods: { + init() { + animation.transition(this.$refs['right-circle'].ref, { + styles: { + transform: 'rotate(45deg)', + transformOrigin: 'center center' + }, + }, () => { + this.rightBorderColor = 'rgb(66, 185, 131)' + // animation.transition(this.$refs['right-circle'].ref, { + // styles: { + // transform: 'rotate(225deg)', + // transformOrigin: 'center center' + // }, + // duration: 3000, + // }, () => { + // animation.transition(this.$refs['left-circle'].ref, { + // styles: { + // transform: 'rotate(45deg)', + // transformOrigin: 'center center' + // }, + // }, () => { + // this.leftBorderColor = 'rgb(66, 185, 131)' + // animation.transition(this.$refs['left-circle'].ref, { + // styles: { + // transform: 'rotate(225deg)', + // transformOrigin: 'center center' + // }, + // duration: 1500, + // }, () => { + + // }) + // }) + // }) + }) + + } + }, + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-circle-progress { + @include flex(row); + position: relative; + border-radius: 100px; + height: 100px; + width: 100px; + // transform: rotate(0deg); + // background-color: rgb(66, 185, 131); + background-color: rgb(200, 200, 200); + overflow: hidden; + justify-content: space-between; + + &__circle { + border-radius: 100px; + height: 90px; + width: 90px; + transform: translate(-50%, -50%); + background-color: rgb(255, 255, 255); + left: 50px; + top: 50px; + position: absolute; + } + + &__left { + position: absolute; + left: 0; + width: 50px; + height: 100px; + overflow: hidden; + box-sizing: border-box; + // background-color: rgb(66, 185, 131); + // background-color: rgb(200, 200, 200); + // transform-origin: left center; + + &__circle { + box-sizing: border-box; + // background-color: red; + border-left-color: transparent; + border-bottom-color: transparent; + border-top-left-radius: 50px; + border-top-right-radius: 50px; + border-bottom-right-radius: 50px; + // border-left-color: rgb(66, 185, 131); + // border-bottom-color: rgb(66, 185, 131); + border-top-color: rgb(66, 185, 131); + border-right-color: rgb(66, 185, 131); + border-width: 5px; + width: 100px; + height: 100px; + transform: rotate(225deg); + // border-radius: 100px; + } + } + + &__right { + position: absolute; + right: 0; + width: 50px; + height: 100px; + overflow: hidden; + + &__circle { + position: absolute; + right: 0; + box-sizing: border-box; + // background-color: red; + border-top-color: transparent; + border-right-color: transparent; + border-top-left-radius: 50px; + border-bottom-left-radius: 50px; + border-bottom-right-radius: 50px; + // border-left-color: rgb(66, 185, 131); + // border-bottom-color: rgb(66, 185, 131); + border-left-color: rgb(200, 200, 200); + border-bottom-color: rgb(200, 200, 200); + border-width: 5px; + width: 100px; + height: 100px; + transform: rotate(45deg); + transform-origin: center center; + // border-radius: 100px; + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-code-input/props.js b/uni_modules/uview-ui/components/u-code-input/props.js new file mode 100644 index 0000000..0f016ee --- /dev/null +++ b/uni_modules/uview-ui/components/u-code-input/props.js @@ -0,0 +1,79 @@ +export default { + props: { + // ������������������������������������������ + adjustPosition: { + type: Boolean, + default: uni.$u.props.codeInput.adjustPosition + }, + // ������������������ + maxlength: { + type: [String, Number], + default: uni.$u.props.codeInput.maxlength + }, + // ��������������������� + dot: { + type: Boolean, + default: uni.$u.props.codeInput.dot + }, + // ���������������box-���������������line-������������������ + mode: { + type: String, + default: uni.$u.props.codeInput.mode + }, + // ��������������� + hairline: { + type: Boolean, + default: uni.$u.props.codeInput.hairline + }, + // ������������������ + space: { + type: [String, Number], + default: uni.$u.props.codeInput.space + }, + // ��������� + value: { + type: [String, Number], + default: uni.$u.props.codeInput.value + }, + // ������������������������ + focus: { + type: Boolean, + default: uni.$u.props.codeInput.focus + }, + // ������������������ + bold: { + type: Boolean, + default: uni.$u.props.codeInput.bold + }, + // ������������ + color: { + type: String, + default: uni.$u.props.codeInput.color + }, + // ������������ + fontSize: { + type: [String, Number], + default: uni.$u.props.codeInput.fontSize + }, + // ��������������������������������� + size: { + type: [String, Number], + default: uni.$u.props.codeInput.size + }, + // ������������������������������������������������������������������������������������true + disabledKeyboard: { + type: Boolean, + default: uni.$u.props.codeInput.disabledKeyboard + }, + // ��������������������� + borderColor: { + type: String, + default: uni.$u.props.codeInput.borderColor + }, + // ������������������"."������ + disabledDot: { + type: Boolean, + default: uni.$u.props.codeInput.disabledDot + } + } +} diff --git a/uni_modules/uview-ui/components/u-code-input/u-code-input.vue b/uni_modules/uview-ui/components/u-code-input/u-code-input.vue new file mode 100644 index 0000000..96241cf --- /dev/null +++ b/uni_modules/uview-ui/components/u-code-input/u-code-input.vue @@ -0,0 +1,252 @@ +<template> + <view class="u-code-input"> + <view + class="u-code-input__item" + :style="[itemStyle(index)]" + v-for="(item, index) in codeLength" + :key="index" + > + <view + class="u-code-input__item__dot" + v-if="dot && codeArray.length > index" + ></view> + <text + v-else + :style="{ + fontSize: $u.addUnit(fontSize), + fontWeight: bold ? 'bold' : 'normal', + color: color + }" + >{{codeArray[index]}}</text> + <view + class="u-code-input__item__line" + v-if="mode === 'line'" + :style="[lineStyle]" + ></view> + <!-- #ifndef APP-PLUS --> + <view v-if="isFocus && codeArray.length === index" :style="{backgroundColor: color}" class="u-code-input__item__cursor"></view> + <!-- #endif --> + </view> + <input + :disabled="disabledKeyboard" + type="number" + :focus="focus" + :value="inputValue" + :maxlength="maxlength" + :adjustPosition="adjustPosition" + class="u-code-input__input" + @input="inputHandler" + :style="{ + height: $u.addUnit(size) + }" + @focus="isFocus = true" + @blur="isFocus = false" + /> + </view> +</template> + +<script> + import props from './props.js'; + /** + * CodeInput ��������������� + * @description ���������������������������������������������������������������������������uView��������������������� + * @tutorial https://www.uviewui.com/components/codeInput.html + * @property {String | Number} maxlength ������������������ ��������� 6 ��� + * @property {Boolean} dot ��������������������� ��������� false ��� + * @property {String} mode ���������������box-���������������line-������������������ ��������� 'box' ��� + * @property {Boolean} hairline ��������������� ��������� false ��� + * @property {String | Number} space ������������������ ��������� 10 ��� + * @property {String | Number} value ��������� + * @property {Boolean} focus ������������������������ ��������� false ��� + * @property {Boolean} bold ��������������������������������� ��������� false ��� + * @property {String} color ������������ ��������� '#606266' ��� + * @property {String | Number} fontSize ���������������������px ��������� 18 ��� + * @property {String | Number} size ��������������������������������� ��������� 35 ��� + * @property {Boolean} disabledKeyboard ������������������������������������������������������������������������������������true ��������� false ��� + * @property {String} borderColor ��������������������� ��������� '#c9cacc' ��� + * @property {Boolean} disabledDot ������������������"."������ ��������� true ��� + * + * @event {Function} change ��������������������������������������������������������� value��������������������� + * @event {Function} finish ���������������������maxlength������������������������������ value��������������������� + * @example <u-code-input v-model="value4" :focus="true"></u-code-input> + */ + export default { + name: 'u-code-input', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + inputValue: '', + isFocus: this.focus + } + }, + watch: { + value: { + immediate: true, + handler(val) { + // ������������������������������������ + this.inputValue = String(val).substring(0, this.maxlength) + } + }, + }, + computed: { + // ���������������������������������������������������������������������������������v-for + codeLength() { + return new Array(Number(this.maxlength)) + }, + // ������item��������� + itemStyle() { + return index => { + const addUnit = uni.$u.addUnit + const style = { + width: addUnit(this.size), + height: addUnit(this.size) + } + // ������������������������������������������ + if (this.mode === 'box') { + // ���������������������������������������������������������0.5px������ + style.border = `${this.hairline ? 0.5 : 1}px solid ${this.borderColor}` + // ���������������������0������ + if (uni.$u.getPx(this.space) === 0) { + // ������������������������������������������ + if (index === 0) { + style.borderTopLeftRadius = '3px' + style.borderBottomLeftRadius = '3px' + } + if (index === this.codeLength.length - 1) { + style.borderTopRightRadius = '3px' + style.borderBottomRightRadius = '3px' + } + // ������������������������������������������ + if (index !== this.codeLength.length - 1) { + style.borderRight = 'none' + } + } + } + if (index !== this.codeLength.length - 1) { + // ���������������������������������������������margin-right��������������������������������������������� + style.marginRight = addUnit(this.space) + } else { + // ������������������������������������������ + style.marginRight = 0 + } + + return style + } + }, + // ������������������������������������item������������������������������������������������������ + codeArray() { + return String(this.inputValue).split('') + }, + // ������������������������������������ + lineStyle() { + const style = {} + style.height = this.hairline ? '2px' : '4px' + style.width = uni.$u.addUnit(this.size) + // ��������������������������������������������� + style.backgroundColor = this.borderColor + return style + } + }, + methods: { + // ��������������������������������� + inputHandler(e) { + const value = e.detail.value + this.inputValue = value + // ���������������������.��������� + if(this.disabledDot) { + this.$nextTick(() => { + this.inputValue = value.replace('.', '') + }) + } + // ���������maxlength���������������change������������������������finish������ + this.$emit('change', value) + // ������������v-model������������������ + this.$emit('input', value) + // ������������������������������������������������������ + if (String(value).length >= Number(this.maxlength)) { + this.$emit('finish', value) + } + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + $u-code-input-cursor-width: 1px; + $u-code-input-cursor-height: 40%; + $u-code-input-cursor-animation-duration: 1s; + $u-code-input-cursor-animation-name: u-cursor-flicker; + + .u-code-input { + @include flex; + position: relative; + overflow: hidden; + + &__item { + @include flex; + justify-content: center; + align-items: center; + position: relative; + + &__text { + font-size: 15px; + color: $u-content-color; + } + + &__dot { + width: 7px; + height: 7px; + border-radius: 100px; + background-color: $u-content-color; + } + + &__line { + position: absolute; + bottom: 0; + height: 4px; + border-radius: 100px; + width: 40px; + background-color: $u-content-color; + } + /* #ifndef APP-PLUS */ + &__cursor { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%,-50%); + width: $u-code-input-cursor-width; + height: $u-code-input-cursor-height; + animation: $u-code-input-cursor-animation-duration u-cursor-flicker infinite; + } + /* #endif */ + + } + + &__input { + // ���������������input��������������������������������������������� + // ������������������������������������������������������������������������������������������������������������������������ + position: absolute; + left: -750rpx; + width: 1500rpx; + top: 0; + background-color: transparent; + text-align: left; + } + } + + /* #ifndef APP-PLUS */ + @keyframes u-cursor-flicker { + 0% { + opacity: 0; + } + 50% { + opacity: 1; + } + 100% { + opacity: 0; + } + } + /* #endif */ + +</style> diff --git a/uni_modules/uview-ui/components/u-code/props.js b/uni_modules/uview-ui/components/u-code/props.js new file mode 100644 index 0000000..eaf80d0 --- /dev/null +++ b/uni_modules/uview-ui/components/u-code/props.js @@ -0,0 +1,34 @@ +export default { + props: { + // ������������������ + seconds: { + type: [String, Number], + default: uni.$u.props.code.seconds + }, + // ��������������������� + startText: { + type: String, + default: uni.$u.props.code.startText + }, + // ��������������������������� + changeText: { + type: String, + default: uni.$u.props.code.changeText + }, + // ��������������������������� + endText: { + type: String, + default: uni.$u.props.code.endText + }, + // ���������H5������������������������������������������������ + keepRunning: { + type: Boolean, + default: uni.$u.props.code.keepRunning + }, + // ������������������������������������������������������������������������������������������������������ + uniqueKey: { + type: String, + default: uni.$u.props.code.uniqueKey + } + } +} diff --git a/uni_modules/uview-ui/components/u-code/u-code.vue b/uni_modules/uview-ui/components/u-code/u-code.vue new file mode 100644 index 0000000..f79a09a --- /dev/null +++ b/uni_modules/uview-ui/components/u-code/u-code.vue @@ -0,0 +1,129 @@ +<template> + <view class="u-code"> + <!-- ������������������js������������������html������ --> + </view> +</template> + +<script> + import props from './props.js'; + /** + * Code ������������������ + * @description ������������������������������������������������������������������������������������������������������������������������������������������ ������������������������������������������������������������������������������������������ + * @tutorial https://www.uviewui.com/components/code.html + * @property {String | Number} seconds ��������������������������������� 60 ��� + * @property {String} startText ������������������������������������������������ '���������������' ��� + * @property {String} changeText ������������������������������������������������"x"��������������������������� 'X���������������' ��� + * @property {String} endText ��������������������������������������������������� '������������' ��� + * @property {Boolean} keepRunning ���������H5��������������������������������������������������� ������false ��� + * @property {String} uniqueKey ������������������������������������������������������������������������������������������������������ + * + * @event {Function} change ������������������������������������ + * @event {Function} start ��������������������� + * @event {Function} end ��������������������� + * @example <u-code ref="uCode" @change="codeChange" seconds="20"></u-code> + */ + export default { + name: "u-code", + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + secNum: this.seconds, + timer: null, + canGetCode: true, // ��������������������������������� + } + }, + mounted() { + this.checkKeepRunning() + }, + watch: { + seconds: { + immediate: true, + handler(n) { + this.secNum = n + } + } + }, + methods: { + checkKeepRunning() { + // ���������������������������(H5���������������)������������������������������������������������������������������ + let lastTimestamp = Number(uni.getStorageSync(this.uniqueKey + '_$uCountDownTimestamp')) + if(!lastTimestamp) return this.changeEvent(this.startText) + // ��������������������� + let nowTimestamp = Math.floor((+ new Date()) / 1000) + // ������������������������������������������������������������������������������������������������������ + if(this.keepRunning && lastTimestamp && lastTimestamp > nowTimestamp) { + // ������������������������������������ + this.secNum = lastTimestamp - nowTimestamp + // ��������������������������� + uni.removeStorageSync(this.uniqueKey + '_$uCountDownTimestamp') + // ��������������� + this.start() + } else { + // ������������������������������������������������������������������������ + this.changeEvent(this.startText) + } + }, + // ��������������� + start() { + // ������������������������������������������������������������������������������������������ + if(this.timer) { + clearInterval(this.timer) + this.timer = null + } + this.$emit('start') + this.canGetCode = false + // ���������������������������������������������������������������setInterval���1��������������������� + this.changeEvent(this.changeText.replace(/x|X/, this.secNum)) + this.timer = setInterval(() => { + if (--this.secNum) { + // ������������������������������������������������������"x"������ + this.changeEvent(this.changeText.replace(/x|X/, this.secNum)) + } else { + clearInterval(this.timer) + this.timer = null + this.changeEvent(this.endText) + this.secNum = this.seconds + this.$emit('end') + this.canGetCode = true + } + }, 1000) + this.setTimeToStorage() + }, + // ��������������������������������������������� + reset() { + this.canGetCode = true + clearInterval(this.timer) + this.secNum = this.seconds + this.changeEvent(this.endText) + }, + changeEvent(text) { + this.$emit('change', text) + }, + // ������������������������������������������������������H5������������������������������������������������������ + setTimeToStorage() { + if(!this.keepRunning || !this.timer) return + // ������������������������������������������������������������������������������������������������������ + // ������������������������������������0��������������������������������������������������������������������������������������������������������������������� + if(this.secNum > 0 && this.secNum <= this.seconds) { + // ���������������������(+ new Date()���������������)���������1000��������������������������������� + let nowTimestamp = Math.floor((+ new Date()) / 1000) + // ��������������������������������������������� => ��������������� + ��������������� + uni.setStorage({ + key: this.uniqueKey + '_$uCountDownTimestamp', + data: nowTimestamp + Number(this.secNum) + }) + } + } + }, + // ��������������������������������������������������������������������������������������������������� + beforeDestroy() { + this.setTimeToStorage() + clearTimeout(this.timer) + this.timer = null + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; +</style> diff --git a/uni_modules/uview-ui/components/u-col/props.js b/uni_modules/uview-ui/components/u-col/props.js new file mode 100644 index 0000000..0622251 --- /dev/null +++ b/uni_modules/uview-ui/components/u-col/props.js @@ -0,0 +1,29 @@ +export default { + props: { + // ���������������������������������������������12��� + span: { + type: [String, Number], + default: uni.$u.props.col.span + }, + // ������������������������������(���12���) + offset: { + type: [String, Number], + default: uni.$u.props.col.offset + }, + // ���������������������������������`start`(���`flex-start`)���`end`(���`flex-end`)���`center`���`around`(���`space-around`)���`between`(���`space-between`) + justify: { + type: String, + default: uni.$u.props.col.justify + }, + // ���������������������������������top���center���bottom���stretch + align: { + type: String, + default: uni.$u.props.col.align + }, + // ������������������ + textAlign: { + type: String, + default: uni.$u.props.col.textAlign + } + } +} diff --git a/uni_modules/uview-ui/components/u-col/u-col.vue b/uni_modules/uview-ui/components/u-col/u-col.vue new file mode 100644 index 0000000..8be1517 --- /dev/null +++ b/uni_modules/uview-ui/components/u-col/u-col.vue @@ -0,0 +1,162 @@ +<template> + <view + class="u-col" + ref="u-col" + :class="[ + 'u-col-' + span + ]" + :style="[colStyle]" + @tap="clickHandler" + > + <slot></slot> + </view> +</template> + +<script> + import props from './props.js'; + /** + * CodeInput ������������������ + * @description ���������������������Layout ������ ��������������� 12 ������������������������������������ + * @tutorial https://www.uviewui.com/components/Layout.html + * @property {String | Number} span ���������������������������12������ (������ 12 ) + * @property {String | Number} offset ������������������������������������span������ (������ 0 ) + * @property {String} justify ���������������������������������`start`(���`flex-start`)���`end`(���`flex-end`)���`center`���`around`(���`space-around`)���`between`(���`space-between`) (������ 'start' ) + * @property {String} align ���������������������������������top���center���bottom���stretch (������ 'stretch' ) + * @property {String} textAlign ������������������������ (������ 'left' ) + * @property {Object} customStyle ��������������������������������� + * @event {Function} click col������������������������������������row + * @example <u-col span="3" offset="3" > <view class="demo-layout bg-purple"></view> </u-col> + */ + export default { + name: 'u-col', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + width: 0, + parentData: { + gutter: 0 + }, + gridNum: 12 + } + }, + computed: { + uJustify() { + if (this.justify == 'end' || this.justify == 'start') return 'flex-' + this.justify + else if (this.justify == 'around' || this.justify == 'between') return 'space-' + this.justify + else return this.justify + }, + uAlignItem() { + if (this.align == 'top') return 'flex-start' + if (this.align == 'bottom') return 'flex-end' + else return this.align + }, + colStyle() { + const style = { + // ������������"padding: 0 10px"������������������nvue��������� + paddingLeft: uni.$u.addUnit(uni.$u.getPx(this.parentData.gutter)/2), + paddingRight: uni.$u.addUnit(uni.$u.getPx(this.parentData.gutter)/2), + alignItems: this.uAlignItem, + justifyContent: this.uJustify, + textAlign: this.textAlign, + // #ifndef APP-NVUE + // ������nvue��������������������������� + flex: `0 0 ${100 / this.gridNum * this.span}%`, + marginLeft: 100 / 12 * this.offset + '%', + // #endif + // #ifdef APP-NVUE + // ���nvue������������������������������������������������������������������������������������������������������������������������������ + width: uni.$u.addUnit(Math.floor(this.width / this.gridNum * Number(this.span))), + marginLeft: uni.$u.addUnit(Math.floor(this.width / this.gridNum * Number(this.offset))), + // #endif + } + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) + } + }, + mounted() { + this.init() + }, + methods: { + async init() { + // ���������������������������provide/inject������������������������������������������������������created��������������������������� + this.updateParentData() + this.width = await this.parent.getComponentWidth() + }, + updateParentData() { + this.getParentData('u-row') + }, + clickHandler(e) { + this.$emit('click'); + } + }, + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-col { + padding: 0; + /* #ifndef APP-NVUE */ + box-sizing:border-box; + /* #endif */ + /* #ifdef MP */ + display: block; + /* #endif */ + } + + // nvue������������������ + /* #ifndef APP-NVUE */ + .u-col-0 { + width: 0; + } + + .u-col-1 { + width: calc(100%/12); + } + + .u-col-2 { + width: calc(100%/12 * 2); + } + + .u-col-3 { + width: calc(100%/12 * 3); + } + + .u-col-4 { + width: calc(100%/12 * 4); + } + + .u-col-5 { + width: calc(100%/12 * 5); + } + + .u-col-6 { + width: calc(100%/12 * 6); + } + + .u-col-7 { + width: calc(100%/12 * 7); + } + + .u-col-8 { + width: calc(100%/12 * 8); + } + + .u-col-9 { + width: calc(100%/12 * 9); + } + + .u-col-10 { + width: calc(100%/12 * 10); + } + + .u-col-11 { + width: calc(100%/12 * 11); + } + + .u-col-12 { + width: calc(100%/12 * 12); + } + + /* #endif */ +</style> diff --git a/uni_modules/uview-ui/components/u-collapse-item/props.js b/uni_modules/uview-ui/components/u-collapse-item/props.js new file mode 100644 index 0000000..bd5749b --- /dev/null +++ b/uni_modules/uview-ui/components/u-collapse-item/props.js @@ -0,0 +1,59 @@ +export default { + props: { + // ������ + title: { + type: String, + default: uni.$u.props.collapseItem.title + }, + // ������������������ + value: { + type: String, + default: uni.$u.props.collapseItem.value + }, + // ��������������������������� + label: { + type: String, + default: uni.$u.props.collapseItem.label + }, + // ������������������������ + disabled: { + type: Boolean, + default: uni.$u.props.collapseItem.disabled + }, + // ��������������������������������������������� + isLink: { + type: Boolean, + default: uni.$u.props.collapseItem.isLink + }, + // ������������������������ + clickable: { + type: Boolean, + default: uni.$u.props.collapseItem.clickable + }, + // ��������������������� + border: { + type: Boolean, + default: uni.$u.props.collapseItem.border + }, + // ��������������������� + align: { + type: String, + default: uni.$u.props.collapseItem.align + }, + // ��������������� + name: { + type: [String, Number], + default: uni.$u.props.collapseItem.name + }, + // ��������������������������������������������������������������� + icon: { + type: String, + default: uni.$u.props.collapseItem.icon + }, + // ������������������������������������������ms + duration: { + type: Number, + default: uni.$u.props.collapseItem.duration + } + } +} diff --git a/uni_modules/uview-ui/components/u-collapse-item/u-collapse-item.vue b/uni_modules/uview-ui/components/u-collapse-item/u-collapse-item.vue new file mode 100644 index 0000000..0e1b703 --- /dev/null +++ b/uni_modules/uview-ui/components/u-collapse-item/u-collapse-item.vue @@ -0,0 +1,225 @@ +<template> + <view class="u-collapse-item"> + <u-cell + :title="title" + :value="value" + :label="label" + :icon="icon" + :isLink="isLink" + :clickable="clickable" + :border="parentData.border && showBorder" + @click="clickHandler" + :arrowDirection="expanded ? 'up' : 'down'" + :disabled="disabled" + > + <!-- #ifndef MP-WEIXIN --> + <!-- ��������������������������������������������������� <slot name="title" slot="title" />��������� --> + <template slot="title"> + <slot name="title"></slot> + </template> + <template slot="icon"> + <slot name="icon"></slot> + </template> + <template slot="value"> + <slot name="value"></slot> + </template> + <template slot="right-icon"> + <slot name="right-icon"></slot> + </template> + <!-- #endif --> + </u-cell> + <view + class="u-collapse-item__content" + :animation="animationData" + ref="animation" + > + <view + class="u-collapse-item__content__text content-class" + :id="elId" + :ref="elId" + ><slot /></view> + </view> + <u-line v-if="parentData.border"></u-line> + </view> +</template> + +<script> + import props from './props.js'; + // #ifdef APP-NVUE + const animation = uni.requireNativePlugin('animation') + const dom = uni.requireNativePlugin('dom') + // #endif + /** + * collapseItem ������������Item + * @description ���������������������������������������������u-collapse��������� + * @tutorial https://www.uviewui.com/components/collapse.html + * @property {String} title ������ + * @property {String} value ������������������ + * @property {String} label ��������������������������� + * @property {Boolean} disbled ������������������������ ( ������ false ) + * @property {Boolean} isLink ��������������������������������������������� ( ������ true ) + * @property {Boolean} clickable ������������������������ ( ������ true ) + * @property {Boolean} border ��������������������� ( ������ true ) + * @property {String} align ��������������������� ( ������ 'left' ) + * @property {String | Number} name ��������������� + * @property {String} icon ��������������������������������������������������������������� + * @event {Function} change ������item������������������������������ + * @example <u-collapse-item :title="item.head" v-for="(item, index) in itemList" :key="index">{{item.body}}</u-collapse-item> + */ + export default { + name: "u-collapse-item", + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + elId: uni.$u.guid(), + // uni.createAnimation��������������� + animationData: {}, + // ������������������ + expanded: false, + // ������expanded������������������border���������������������������cell��������������������������������������������������������������� + showBorder: false, + // ��������������������������������������������������������� + animating: false, + // ���������u-collapse��������� + parentData: { + accordion: false, + border: false + } + }; + }, + watch: { + expanded(n) { + clearTimeout(this.timer) + this.timer = null + // ������������expanded������������������������������������������cell��������������������������������� + this.timer = setTimeout(() => { + this.showBorder = n + }, n ? 10 : 290) + } + }, + mounted() { + this.init() + }, + methods: { + // ��������������������������������������������������������������������������� + init() { + // ��������������� + this.updateParentData() + if (!this.parent) { + return uni.$u.error('u-collapse-item���������������u-collapse������������') + } + const { + value, + accordion, + children = [] + } = this.parent + + if (accordion) { + if (uni.$u.test.array(value)) { + return uni.$u.error('���������������������u-collapse���������value���������������������') + } + this.expanded = this.name == value + } else { + if (!uni.$u.test.array(value) && value !== null) { + return uni.$u.error('������������������������u-collapse���������value���������������������') + } + this.expanded = (value || []).some(item => item == this.name) + } + // ������������������������������������ + this.$nextTick(function() { + this.setContentAnimate() + }) + }, + updateParentData() { + // ������������mixin��� + this.getParentData('u-collapse') + }, + async setContentAnimate() { + // ��������������������������������������������������������� + // ��������������������������������������������������������������������������������������������������� + const rect = await this.queryRect() + const height = this.expanded ? rect.height : 0 + this.animating = true + // #ifdef APP-NVUE + const ref = this.$refs['animation'].ref + animation.transition(ref, { + styles: { + height: height + 'px' + }, + duration: this.duration, + // ���������������true��������������������������������������������������������������������������������������������� + needLayout: true, + timingFunction: 'ease-in-out', + }, () => { + this.animating = false + }) + // #endif + + // #ifndef APP-NVUE + const animation = uni.createAnimation({ + timingFunction: 'ease-in-out', + }); + animation + .height(height) + .step({ + duration: this.duration, + }) + .step() + // ������������������������������animationData��� + this.animationData = animation.export() + // ������������������ + uni.$u.sleep(this.duration).then(() => { + this.animating = false + }) + // #endif + }, + // ������collapsehead������ + clickHandler() { + if (this.disabled && this.animating) return + // ��������������������������������� + this.parent && this.parent.onChange(this) + }, + // ������������������ + queryRect() { + // #ifndef APP-NVUE + // $uGetRect���uView���������������������������������������������������������https://www.uviewui.com/js/getRect.html + // ���������������������this.$uGetRect���������������uni.$u.getRect������������������������������������ + return new Promise(resolve => { + this.$uGetRect(`#${this.elId}`).then(size => { + resolve(size) + }) + }) + // #endif + + // #ifdef APP-NVUE + // nvue������������dom������������������������ + // ������������promise���������������������������������������then������ + return new Promise(resolve => { + dom.getComponentRect(this.$refs[this.elId], res => { + resolve(res.size) + }) + }) + // #endif + } + }, + }; +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-collapse-item { + + &__content { + overflow: hidden; + height: 0; + + &__text { + padding: 12px 15px; + color: $u-content-color; + font-size: 14px; + line-height: 18px; + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-collapse/props.js b/uni_modules/uview-ui/components/u-collapse/props.js new file mode 100644 index 0000000..7ee6d31 --- /dev/null +++ b/uni_modules/uview-ui/components/u-collapse/props.js @@ -0,0 +1,19 @@ +export default { + props: { + // ���������������������name������������������������[<string | number>]���������������������string | number + value: { + type: [String, Number, Array, null], + default: uni.$u.props.collapse.value + }, + // ��������������������� + accordion: { + type: Boolean, + default: uni.$u.props.collapse.accordion + }, + // ��������������������� + border: { + type: Boolean, + default: uni.$u.props.collapse.border + } + } +} diff --git a/uni_modules/uview-ui/components/u-collapse/u-collapse.vue b/uni_modules/uview-ui/components/u-collapse/u-collapse.vue new file mode 100644 index 0000000..fc188a2 --- /dev/null +++ b/uni_modules/uview-ui/components/u-collapse/u-collapse.vue @@ -0,0 +1,90 @@ +<template> + <view class="u-collapse"> + <u-line v-if="border"></u-line> + <slot /> + </view> +</template> + +<script> + import props from './props.js'; + /** + * collapse ������������ + * @description ������������������������������������ + * @tutorial https://www.uviewui.com/components/collapse.html + * @property {String | Number | Array} value ���������������������name������������������������[<string | number>]���������������������string | number + * @property {Boolean} accordion ������������������������ ������ false ��� + * @property {Boolean} border ��������������������� ( ������ true ��� + * @event {Function} change ���������������������������������(���������������������������������activeNames���������String������������Array) + * @example <u-collapse></u-collapse> + */ + export default { + name: "u-collapse", + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + watch: { + needInit() { + this.init() + } + }, + created() { + this.children = [] + }, + computed: { + needInit() { + // ������computed���������������accordion���value������������ + // ���������watch���������init()������������������������������������ + return [this.accordion, this.value] + } + }, + watch: { + // ��������������������������������������������������������������������������������������� + parentData() { + if (this.children.length) { + this.children.map(child => { + // ���������������(u-checkbox)���������updateParentData���������������������������(������������������������������������������������������������������) + typeof(child.updateParentData) === 'function' && child.updateParentData() + }) + } + }, + }, + methods: { + // ��������������������������������������������� + init() { + this.children.map(child => { + child.init() + }) + }, + /** + * collapse-item������������������������collapse��������������������������������� + * @param {Object} target ��������������������������� + */ + onChange(target) { + let changeArr = [] + this.children.map((child, index) => { + // ������������������������������������������������������������ + if (this.accordion) { + child.expanded = child === target ? !target.expanded : false + child.setContentAnimate() + } else { + if(child === target) { + child.expanded = !child.expanded + child.setContentAnimate() + } + } + // ������change��������������������������������� + changeArr.push({ + // ������������������name���������������������������������index������ + name: child.name || index, + status: child.expanded ? 'open' : 'close' + }) + }) + + this.$emit('change', changeArr) + this.$emit(target.expanded ? 'open' : 'close', target.name) + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; +</style> diff --git a/uni_modules/uview-ui/components/u-column-notice/props.js b/uni_modules/uview-ui/components/u-column-notice/props.js new file mode 100644 index 0000000..4809154 --- /dev/null +++ b/uni_modules/uview-ui/components/u-column-notice/props.js @@ -0,0 +1,55 @@ +export default { + props: { + // ��������������������������� + text: { + type: [Array], + default: uni.$u.props.columnNotice.text + }, + // ��������������������������������� + icon: { + type: String, + default: uni.$u.props.columnNotice.icon + }, + // ���������������link-������������������closable-������������������������ + mode: { + type: String, + default: uni.$u.props.columnNotice.mode + }, + // ������������������������������������������������ + color: { + type: String, + default: uni.$u.props.columnNotice.color + }, + // ������������ + bgColor: { + type: String, + default: uni.$u.props.columnNotice.bgColor + }, + // ���������������������px + fontSize: { + type: [String, Number], + default: uni.$u.props.columnNotice.fontSize + }, + // ������������������������������������������������������px(px)��������������������������������������������������������������������������� + speed: { + type: [String, Number], + default: uni.$u.props.columnNotice.speed + }, + // direction = row������������������������������������ + step: { + type: Boolean, + default: uni.$u.props.columnNotice.step + }, + // ���������������������������������������ms + duration: { + type: [String, Number], + default: uni.$u.props.columnNotice.duration + }, + // ������������������������������ + // ������HX2.6.11������������App 2.5.5+���H5 2.5.5+��������������������������������������������� + disableTouch: { + type: Boolean, + default: uni.$u.props.columnNotice.disableTouch + } + } +} diff --git a/uni_modules/uview-ui/components/u-column-notice/u-column-notice.vue b/uni_modules/uview-ui/components/u-column-notice/u-column-notice.vue new file mode 100644 index 0000000..fc39532 --- /dev/null +++ b/uni_modules/uview-ui/components/u-column-notice/u-column-notice.vue @@ -0,0 +1,160 @@ +<template> + <view + class="u-notice" + @tap="clickHandler" + > + <slot name="icon"> + <view + class="u-notice__left-icon" + v-if="icon" + > + <u-icon + :name="icon" + :color="color" + size="19" + ></u-icon> + </view> + </slot> + <swiper + :disable-touch="disableTouch" + :vertical="step ? false : true" + circular + :interval="duration" + :autoplay="true" + class="u-notice__swiper" + @change="noticeChange" + > + <swiper-item + v-for="(item, index) in text" + :key="index" + class="u-notice__swiper__item" + > + <text + class="u-notice__swiper__item__text u-line-1" + :style="[textStyle]" + >{{ item }}</text> + </swiper-item> + </swiper> + <view + class="u-notice__right-icon" + v-if="['link', 'closable'].includes(mode)" + > + <u-icon + v-if="mode === 'link'" + name="arrow-right" + :size="17" + :color="color" + ></u-icon> + <u-icon + v-if="mode === 'closable'" + name="close" + :size="16" + :color="color" + @click="close" + ></u-icon> + </view> + </view> +</template> + +<script> + import props from './props.js'; + /** + * ColumnNotice ������������������������������ ������������ + * @description ������������������������������������������������������������������ + * @tutorial https://www.uviewui.com/components/noticeBar.html + * @property {Array} text ��������������������������� + * @property {String} icon ��������������������������������� ��� ������ 'volume' ��� + * @property {String} mode ���������������link-������������������closable-������������������������ + * @property {String} color ������������������������������������������������ ��� ������ '#f9ae3d' ��� + * @property {String} bgColor ������������ ��� ������ '#fdf6ec' ��� + * @property {String | Number} fontSize ���������������������px ��� ������ 14 ��� + * @property {String | Number} speed ������������������������������������������������������px(rpx)��������������������������������������������������������������������������� ��� ������ 80 ��� + * @property {Boolean} step direction = row������������������������������������ ��� ������ false ��� + * @property {String | Number} duration ���������������������������������������ms ��� ������ 1500 ��� + * @property {Boolean} disableTouch ������������������������������ ������HX2.6.11������������App 2.5.5+���H5 2.5.5+��������������������������������������������� ��� ������ true ��� + * @example + */ + export default { + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + watch: { + text: { + immediate: true, + handler(newValue, oldValue) { + if(!uni.$u.test.array(newValue)) { + uni.$u.error('noticebar������direction���column������������text���������������������') + } + } + } + }, + computed: { + // ��������������������� + textStyle() { + let style = {} + style.color = this.color + style.fontSize = uni.$u.addUnit(this.fontSize) + return style + }, + // ������������������������ + vertical() { + if (this.mode == 'horizontal') return false + else return true + }, + }, + data() { + return { + index:0 + } + }, + methods: { + noticeChange(e){ + this.index = e.detail.current + }, + // ��������������� + clickHandler() { + this.$emit('click', this.index) + }, + // ������������������ + close() { + this.$emit('close') + } + } + }; +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-notice { + @include flex; + align-items: center; + justify-content: space-between; + + &__left-icon { + align-items: center; + margin-right: 5px; + } + + &__right-icon { + margin-left: 5px; + align-items: center; + } + + &__swiper { + height: 16px; + @include flex; + align-items: center; + flex: 1; + + &__item { + @include flex; + align-items: center; + overflow: hidden; + + &__text { + font-size: 14px; + color: $u-warning; + } + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-count-down/props.js b/uni_modules/uview-ui/components/u-count-down/props.js new file mode 100644 index 0000000..d62f025 --- /dev/null +++ b/uni_modules/uview-ui/components/u-count-down/props.js @@ -0,0 +1,24 @@ +export default { + props: { + // ������������������������ms + time: { + type: [String, Number], + default: uni.$u.props.countDown.time + }, + // ���������������DD-������HH-������mm-������ss-������SSS-������ + format: { + type: String, + default: uni.$u.props.countDown.format + }, + // ��������������������������� + autoStart: { + type: Boolean, + default: uni.$u.props.countDown.autoStart + }, + // ��������������������������� + millisecond: { + type: Boolean, + default: uni.$u.props.countDown.millisecond + } + } +} diff --git a/uni_modules/uview-ui/components/u-count-down/u-count-down.vue b/uni_modules/uview-ui/components/u-count-down/u-count-down.vue new file mode 100644 index 0000000..b5e85a6 --- /dev/null +++ b/uni_modules/uview-ui/components/u-count-down/u-count-down.vue @@ -0,0 +1,163 @@ +<template> + <view class="u-count-down"> + <slot> + <text class="u-count-down__text">{{ formattedTime }}</text> + </slot> + </view> +</template> + +<script> + import props from './props.js'; + import { + isSameSecond, + parseFormat, + parseTimeData + } from './utils'; + /** + * u-count-down ��������� + * @description ������������������������������������������������������������������������������������������������������������������������������������������������������������ + * @tutorial https://uviewui.com/components/countDown.html + * @property {String | Number} time ������������������������ms ��������� 0 ��� + * @property {String} format ���������������DD-������HH-������mm-������ss-������SSS-������ ��������� 'HH:mm:ss' ��� + * @property {Boolean} autoStart ��������������������������� ��������� true ��� + * @property {Boolean} millisecond ��������������������������� ��������� false ��� + * @event {Function} finish ������������������������ + * @event {Function} change ������������������������ + * @event {Function} start ��������������� + * @event {Function} pause ��������������� + * @event {Function} reset ��������������������� auto-start ��� true������������������������������������ + * @example <u-count-down :time="time"></u-count-down> + */ + export default { + name: 'u-count-down', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + timer: null, + // ���������(������������������)������������ + timeData: parseTimeData(0), + // ���������������������������"03:23:21" + formattedTime: '0', + // ������������������������������ + runing: false, + endTime: 0, // ������������������������ + remainTime: 0, // ��������������������� + } + }, + watch: { + time(n) { + this.reset() + } + }, + mounted() { + this.init() + }, + methods: { + init() { + this.reset() + }, + // ��������������� + start() { + if (this.runing) return + // ������������������ + this.runing = true + // ��������������� = ��������������� + ��������������� + this.endTime = Date.now() + this.remainTime + this.toTick() + }, + // ��������������������������������������������������� + toTick() { + if (this.millisecond) { + this.microTick() + } else { + this.macroTick() + } + }, + macroTick() { + this.clearTimeout() + // ������������������������������������������������ + // ��������������������������������������������������������� + this.timer = setTimeout(() => { + // ������������������ + const remain = this.getRemainTime() + // ������������������ + if (!isSameSecond(remain, this.remainTime) || remain === 0) { + this.setRemainTime(remain) + } + // ������������������������0��������������������������������� + if (this.remainTime !== 0) { + this.macroTick() + } + }, 30) + }, + microTick() { + this.clearTimeout() + this.timer = setTimeout(() => { + this.setRemainTime(this.getRemainTime()) + if (this.remainTime !== 0) { + this.microTick() + } + }, 50) + }, + // ��������������������� + getRemainTime() { + // ���������������������������������0������������������ + return Math.max(this.endTime - Date.now(), 0) + }, + // ��������������������� + setRemainTime(remain) { + this.remainTime = remain + // ��������������������������������������������������������������������������������������������� + const timeData = parseTimeData(remain) + this.$emit('change', timeData) + // ��������������������������� + this.formattedTime = parseFormat(this.format, timeData) + // ������������������������������������ + if (remain <= 0) { + this.pause() + this.$emit('finish') + } + }, + // ��������������� + reset() { + this.pause() + this.remainTime = this.time + this.setRemainTime(this.remainTime) + if (this.autoStart) { + this.start() + } + }, + // ��������������� + pause() { + this.runing = false; + this.clearTimeout() + }, + // ��������������� + clearTimeout() { + clearTimeout(this.timer) + this.timer = null + } + }, + beforeDestroy() { + this.clearTimeout() + } + } +</script> + +<style + lang="scss" + scoped +> + @import "../../libs/css/components.scss"; + $u-count-down-text-color:$u-content-color !default; + $u-count-down-text-font-size:15px !default; + $u-count-down-text-line-height:22px !default; + + .u-count-down { + &__text { + color: $u-count-down-text-color; + font-size: $u-count-down-text-font-size; + line-height: $u-count-down-text-line-height; + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-count-down/utils.js b/uni_modules/uview-ui/components/u-count-down/utils.js new file mode 100644 index 0000000..8c75005 --- /dev/null +++ b/uni_modules/uview-ui/components/u-count-down/utils.js @@ -0,0 +1,62 @@ +// ���0������1 -> 01 +function padZero(num, targetLength = 2) { + let str = `${num}` + while (str.length < targetLength) { + str = `0${str}` + } + return str +} +const SECOND = 1000 +const MINUTE = 60 * SECOND +const HOUR = 60 * MINUTE +const DAY = 24 * HOUR +export function parseTimeData(time) { + const days = Math.floor(time / DAY) + const hours = Math.floor((time % DAY) / HOUR) + const minutes = Math.floor((time % HOUR) / MINUTE) + const seconds = Math.floor((time % MINUTE) / SECOND) + const milliseconds = Math.floor(time % SECOND) + return { + days, + hours, + minutes, + seconds, + milliseconds + } +} +export function parseFormat(format, timeData) { + let { + days, + hours, + minutes, + seconds, + milliseconds + } = timeData + // ������������������������������������DD(���)��������������������������������������� + if (format.indexOf('DD') === -1) { + hours += days * 24 + } else { + // ���������0 + format = format.replace('DD', padZero(days)) + } + // ���������������DD������������������������ + if (format.indexOf('HH') === -1) { + minutes += hours * 60 + } else { + format = format.replace('HH', padZero(hours)) + } + if (format.indexOf('mm') === -1) { + seconds += minutes * 60 + } else { + format = format.replace('mm', padZero(minutes)) + } + if (format.indexOf('ss') === -1) { + milliseconds += seconds * 1000 + } else { + format = format.replace('ss', padZero(seconds)) + } + return format.replace('SSS', padZero(milliseconds, 3)) +} +export function isSameSecond(time1, time2) { + return Math.floor(time1 / 1000) === Math.floor(time2 / 1000) +} diff --git a/uni_modules/uview-ui/components/u-count-to/props.js b/uni_modules/uview-ui/components/u-count-to/props.js new file mode 100644 index 0000000..86873c1 --- /dev/null +++ b/uni_modules/uview-ui/components/u-count-to/props.js @@ -0,0 +1,59 @@ +export default { + props: { + // ���������������������������0��������������������� + startVal: { + type: [String, Number], + default: uni.$u.props.countTo.startVal + }, + // ��������������������������������� + endVal: { + type: [String, Number], + default: uni.$u.props.countTo.endVal + }, + // ���������������������������������������������������������������ms��� + duration: { + type: [String, Number], + default: uni.$u.props.countTo.duration + }, + // ��������������������������������������� + autoplay: { + type: Boolean, + default: uni.$u.props.countTo.autoplay + }, + // ������������������������ + decimals: { + type: [String, Number], + default: uni.$u.props.countTo.decimals + }, + // ������������������������������������������������������������������������ + useEasing: { + type: Boolean, + default: uni.$u.props.countTo.useEasing + }, + // ��������������� + decimal: { + type: [String, Number], + default: uni.$u.props.countTo.decimal + }, + // ������������ + color: { + type: String, + default: uni.$u.props.countTo.color + }, + // ������������ + fontSize: { + type: [String, Number], + default: uni.$u.props.countTo.fontSize + }, + // ������������������ + bold: { + type: Boolean, + default: uni.$u.props.countTo.bold + }, + // ���������������������������������������(���23,321.05������",") + separator: { + type: String, + default: uni.$u.props.countTo.separator + } + } +} diff --git a/uni_modules/uview-ui/components/u-count-to/u-count-to.vue b/uni_modules/uview-ui/components/u-count-to/u-count-to.vue new file mode 100644 index 0000000..417b732 --- /dev/null +++ b/uni_modules/uview-ui/components/u-count-to/u-count-to.vue @@ -0,0 +1,184 @@ +<template> + <text + class="u-count-num" + :style="{ + fontSize: $u.addUnit(fontSize), + fontWeight: bold ? 'bold' : 'normal', + color: color + }" + >{{ displayValue }}</text> +</template> + +<script> + import props from './props.js'; +/** + * countTo ������������ + * @description ������������������������������������������������������������������������������������������������������ + * @tutorial https://www.uviewui.com/components/countTo.html + * @property {String | Number} startVal ���������������������������0������������������������������ 0 ��� + * @property {String | Number} endVal ��������������������������������� ��������� 0 ��� + * @property {String | Number} duration ���������������������������������������������������������������ms��� ��������� 2000 ��� + * @property {Boolean} autoplay ��������������������������������������� ��������� true ��� + * @property {String | Number} decimals ��������������������������������������������������� 0 ��� + * @property {Boolean} useEasing ��������������������������������������������������������������� true ��� + * @property {String} decimal ��������������� ��� ������ "." ��� + * @property {String} color ��������������� ������ '#606266' ) + * @property {String | Number} fontSize ���������������������px��� ������ 22 ��� + * @property {Boolean} bold ��������������������������� false ��� + * @property {String} separator ��������������������������������� + * @event {Function} end ��������������������������������� + * @example <u-count-to ref="uCountTo" :end-val="endVal" :autoplay="autoplay"></u-count-to> + */ +export default { + name: 'u-count-to', + data() { + return { + localStartVal: this.startVal, + displayValue: this.formatNumber(this.startVal), + printVal: null, + paused: false, // ������������ + localDuration: Number(this.duration), + startTime: null, // ��������������� + timestamp: null, // ��������� + remaining: null, // ��������������� + rAF: null, + lastTime: 0 // ������������������ + }; + }, + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + computed: { + countDown() { + return this.startVal > this.endVal; + } + }, + watch: { + startVal() { + this.autoplay && this.start(); + }, + endVal() { + this.autoplay && this.start(); + } + }, + mounted() { + this.autoplay && this.start(); + }, + methods: { + easingFn(t, b, c, d) { + return (c * (-Math.pow(2, (-10 * t) / d) + 1) * 1024) / 1023 + b; + }, + requestAnimationFrame(callback) { + const currTime = new Date().getTime(); + // ���������setTimteout���������������������������60������������ + const timeToCall = Math.max(0, 16 - (currTime - this.lastTime)); + const id = setTimeout(() => { + callback(currTime + timeToCall); + }, timeToCall); + this.lastTime = currTime + timeToCall; + return id; + }, + cancelAnimationFrame(id) { + clearTimeout(id); + }, + // ������������������ + start() { + this.localStartVal = this.startVal; + this.startTime = null; + this.localDuration = this.duration; + this.paused = false; + this.rAF = this.requestAnimationFrame(this.count); + }, + // ��������������������������������������������������������������������� + reStart() { + if (this.paused) { + this.resume(); + this.paused = false; + } else { + this.stop(); + this.paused = true; + } + }, + // ������ + stop() { + this.cancelAnimationFrame(this.rAF); + }, + // ������������(������������������) + resume() { + if (!this.remaining) return + this.startTime = 0; + this.localDuration = this.remaining; + this.localStartVal = this.printVal; + this.requestAnimationFrame(this.count); + }, + // ������ + reset() { + this.startTime = null; + this.cancelAnimationFrame(this.rAF); + this.displayValue = this.formatNumber(this.startVal); + }, + count(timestamp) { + if (!this.startTime) this.startTime = timestamp; + this.timestamp = timestamp; + const progress = timestamp - this.startTime; + this.remaining = this.localDuration - progress; + if (this.useEasing) { + if (this.countDown) { + this.printVal = this.localStartVal - this.easingFn(progress, 0, this.localStartVal - this.endVal, this.localDuration); + } else { + this.printVal = this.easingFn(progress, this.localStartVal, this.endVal - this.localStartVal, this.localDuration); + } + } else { + if (this.countDown) { + this.printVal = this.localStartVal - (this.localStartVal - this.endVal) * (progress / this.localDuration); + } else { + this.printVal = this.localStartVal + (this.endVal - this.localStartVal) * (progress / this.localDuration); + } + } + if (this.countDown) { + this.printVal = this.printVal < this.endVal ? this.endVal : this.printVal; + } else { + this.printVal = this.printVal > this.endVal ? this.endVal : this.printVal; + } + this.displayValue = this.formatNumber(this.printVal) || 0; + if (progress < this.localDuration) { + this.rAF = this.requestAnimationFrame(this.count); + } else { + this.$emit('end'); + } + }, + // ������������������ + isNumber(val) { + return !isNaN(parseFloat(val)); + }, + formatNumber(num) { + // ���num������Number������������������������������������������������������toFixed��������� + num = Number(num); + num = num.toFixed(Number(this.decimals)); + num += ''; + const x = num.split('.'); + let x1 = x[0]; + const x2 = x.length > 1 ? this.decimal + x[1] : ''; + const rgx = /(\d+)(\d{3})/; + if (this.separator && !this.isNumber(this.separator)) { + while (rgx.test(x1)) { + x1 = x1.replace(rgx, '$1' + this.separator + '$2'); + } + } + return x1 + x2; + }, + destroyed() { + this.cancelAnimationFrame(this.rAF); + } + } +}; +</script> + +<style lang="scss" scoped> +@import "../../libs/css/components.scss"; + +.u-count-num { + /* #ifndef APP-NVUE */ + display: inline-flex; + /* #endif */ + text-align: center; +} +</style> diff --git a/uni_modules/uview-ui/components/u-datetime-picker/props.js b/uni_modules/uview-ui/components/u-datetime-picker/props.js new file mode 100644 index 0000000..f44c0f9 --- /dev/null +++ b/uni_modules/uview-ui/components/u-datetime-picker/props.js @@ -0,0 +1,116 @@ +export default { + props: { + // ������������������ + show: { + type: Boolean, + default: uni.$u.props.datetimePicker.show + }, + // ������������������������������ + showToolbar: { + type: Boolean, + default: uni.$u.props.datetimePicker.showToolbar + }, + // ��������� + value: { + type: [String, Number], + default: uni.$u.props.datetimePicker.value + }, + // ������������ + title: { + type: String, + default: uni.$u.props.datetimePicker.title + }, + // ���������������mode=date������������������mode=time������������������mode=year-month������������������mode=datetime��������������������� + mode: { + type: String, + default: uni.$u.props.datetimePicker.mode + }, + // ��������������������� + maxDate: { + type: Number, + // ���������������������10��� + default: uni.$u.props.datetimePicker.maxDate + }, + // ��������������������� + minDate: { + type: Number, + // ���������������������10��� + default: uni.$u.props.datetimePicker.minDate + }, + // ���������������������������mode=time������ + minHour: { + type: Number, + default: uni.$u.props.datetimePicker.minHour + }, + // ���������������������������mode=time������ + maxHour: { + type: Number, + default: uni.$u.props.datetimePicker.maxHour + }, + // ���������������������������mode=time������ + minMinute: { + type: Number, + default: uni.$u.props.datetimePicker.minMinute + }, + // ���������������������������mode=time������ + maxMinute: { + type: Number, + default: uni.$u.props.datetimePicker.maxMinute + }, + // ������������������ + filter: { + type: [Function, null], + default: uni.$u.props.datetimePicker.filter + }, + // ��������������������� + formatter: { + type: [Function, null], + default: uni.$u.props.datetimePicker.formatter + }, + // ��������������������������� + loading: { + type: Boolean, + default: uni.$u.props.datetimePicker.loading + }, + // ��������������������������������� + itemHeight: { + type: [String, Number], + default: uni.$u.props.datetimePicker.itemHeight + }, + // ��������������������� + cancelText: { + type: String, + default: uni.$u.props.datetimePicker.cancelText + }, + // ��������������������� + confirmText: { + type: String, + default: uni.$u.props.datetimePicker.confirmText + }, + // ��������������������� + cancelColor: { + type: String, + default: uni.$u.props.datetimePicker.cancelColor + }, + // ��������������������� + confirmColor: { + type: String, + default: uni.$u.props.datetimePicker.confirmColor + }, + // ������������������������������ + visibleItemCount: { + type: [String, Number], + default: uni.$u.props.datetimePicker.visibleItemCount + }, + // ��������������������������������������� + closeOnClickOverlay: { + type: Boolean, + default: uni.$u.props.datetimePicker.closeOnClickOverlay + }, + // ��������������������� + defaultIndex: { + type: Array, + default: uni.$u.props.datetimePicker.defaultIndex + } + } +} diff --git a/uni_modules/uview-ui/components/u-datetime-picker/u-datetime-picker.vue b/uni_modules/uview-ui/components/u-datetime-picker/u-datetime-picker.vue new file mode 100644 index 0000000..18d8dcc --- /dev/null +++ b/uni_modules/uview-ui/components/u-datetime-picker/u-datetime-picker.vue @@ -0,0 +1,360 @@ +<template> + <u-picker + ref="picker" + :show="show" + :closeOnClickOverlay="closeOnClickOverlay" + :columns="columns" + :title="title" + :itemHeight="itemHeight" + :showToolbar="showToolbar" + :visibleItemCount="visibleItemCount" + :defaultIndex="innerDefaultIndex" + :cancelText="cancelText" + :confirmText="confirmText" + :cancelColor="cancelColor" + :confirmColor="confirmColor" + @close="close" + @cancel="cancel" + @confirm="confirm" + @change="change" + > + </u-picker> +</template> + +<script> + function times(n, iteratee) { + let index = -1 + const result = Array(n < 0 ? 0 : n) + while (++index < n) { + result[index] = iteratee(index) + } + return result + } + import props from './props.js'; + import dayjs from '../../libs/util/dayjs.js'; + /** + * DatetimePicker ��������������������� + * @description ������������������������������ + * @tutorial https://www.uviewui.com/components/datetimePicker.html + * @property {Boolean} show ��������������������������������������� ( ������ false ) + * @property {Boolean} showToolbar ������������������������������ ( ������ true ) + * @property {String | Number} value ��������� + * @property {String} title ������������ + * @property {String} mode ������������ mode=date������������������mode=time������������������mode=year-month������������������mode=datetime��������������������� ( ������ ���datetime ) + * @property {Number} maxDate ��������������������� ���������������10��� + * @property {Number} minDate ��������������������� ���������������10��� + * @property {Number} minHour ���������������������������mode=time������ ( ������ 0 ) + * @property {Number} maxHour ���������������������������mode=time������ ( ������ 23 ) + * @property {Number} minMinute ���������������������������mode=time������ ( ������ 0 ) + * @property {Number} maxMinute ���������������������������mode=time������ ( ������ 59 ) + * @property {Function} filter ������������������ + * @property {Function} formatter ��������������������� + * @property {Boolean} loading ��������������������������� ( ������ false ) + * @property {String | Number} itemHeight ��������������������������������� ( ������ 44 ) + * @property {String} cancelText ��������������������� ( ������ '������' ) + * @property {String} confirmText ��������������������� ( ������ '������' ) + * @property {String} cancelColor ��������������������� ( ������ '#909193' ) + * @property {String} confirmColor ��������������������� ( ������ '#3c9cff' ) + * @property {String | Number} visibleItemCount ������������������������������ ( ������ 5 ) + * @property {Boolean} closeOnClickOverlay ��������������������������������������� ( ������ false ) + * @property {Array} defaultIndex ��������������������� + * @event {Function} close ������������������������ + * @event {Function} confirm ��������������������������������������������� + * @event {Function} change ��������������������������� + * @event {Function} cancel ������������������ + * @example <u-datetime-picker :show="show" :value="value1" mode="datetime" ></u-datetime-picker> + */ + export default { + name: 'datetime-picker', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + columns: [], + innerDefaultIndex: [], + innerFormatter: (type, value) => value + } + }, + watch: { + show(newValue, oldValue) { + if (newValue) { + this.updateColumnValue(this.innerValue) + } + }, + propsChange() { + this.init() + } + }, + computed: { + // ������������������������������������������������������������������������������������ + propsChange() { + return [this.mode, this.maxDate, this.minDate, this.minHour, this.maxHour, this.minMinute, this.maxMinute, this.filter, ] + } + }, + mounted() { + this.init() + }, + methods: { + init() { + this.innerValue = this.correctValue(this.value) + this.updateColumnValue(this.innerValue) + }, + // ������������������������������������������������props������������������������ref������������ + setFormatter(e) { + this.innerFormatter = e + }, + // ��������������� + close() { + if (this.closeOnClickOverlay) { + this.$emit('close') + } + }, + // ������������������������������ + cancel() { + this.$emit('cancel') + }, + // ������������������������������ + confirm() { + this.$emit('confirm', { + value: this.innerValue, + mode: this.mode + }) + this.$emit('input', this.innerValue) + }, + //������������������������,������������������������,������������ + intercept(e,type){ + let judge = e.match(/\d+/g) + //������������������������ + if(judge.length>1){ + uni.$u.error("������������������������������������������������") + return 0 + }else if(type&&judge[0].length==4){//��������������������� + return judge[0] + }else if(judge[0].length>2){ + uni.$u.error("������������������������������������������������") + return 0 + }else{ + return judge[0] + } + }, + // ������������������������ + change(e) { + const { indexs, values } = e + let selectValue = '' + if(this.mode === 'time') { + // ������value������������������������������������������������������������������ + selectValue = `${this.intercept(values[0][indexs[0]])}:${this.intercept(values[1][indexs[1]])}` + } else { + // ������������������������������������'03'���������������3���'2019'���������������2019 + const year = parseInt(this.intercept(values[0][indexs[0]],'year')) + const month = parseInt(this.intercept(values[1][indexs[1]])) + let date = parseInt(values[2] ? this.intercept(values[2][indexs[2]]) : 1) + let hour = 0, minute = 0 + // ������������������������ + const maxDate = dayjs(`${year}-${month}`).daysInMonth() + // year-month������������date���������������������������������1������������������������������1��������� + if (this.mode === 'year-month') { + date = 1 + } + // ���������������maxDate��� + date = Math.min(maxDate, date) + if (this.mode === 'datetime') { + hour = parseInt(this.intercept(values[3][indexs[3]])) + minute = parseInt(this.intercept(values[4][indexs[4]])) + } + // ������������������ + selectValue = Number(new Date(year, month - 1, date, hour, minute)) + } + // ������������������������������������������������������ + selectValue = this.correctValue(selectValue) + this.innerValue = selectValue + this.updateColumnValue(selectValue) + // ������change���������value��������������������������� + this.$emit('change', { + value: selectValue, + // #ifndef MP-WEIXIN + // ���������������������������this��������������������������������������� + picker: this.$refs.picker, + // #endif + mode: this.mode + }) + }, + // ������������������������������0��������������������� + updateColumnValue(value) { + this.innerValue = value + this.updateColumns() + this.updateIndexs(value) + }, + // ������������ + updateIndexs(value) { + let values = [] + const formatter = this.formatter || this.innerFormatter + const padZero = uni.$u.padZero + if (this.mode === 'time') { + // ���time������������������:��������������� + const timeArr = value.split(':') + // ������formatter��������������������������������� + values = [formatter('hour', timeArr[0]), formatter('minute', timeArr[1])] + } else { + const date = new Date(value) + values = [ + formatter('year', `${dayjs(value).year()}`), + // ���������0 + formatter('month', padZero(dayjs(value).month() + 1)) + ] + if (this.mode === 'date') { + // date��������������������������� + values.push(formatter('day', padZero(dayjs(value).date()))) + } + if (this.mode === 'datetime') { + // ���������push��������������������������������� + values.push(formatter('day', padZero(dayjs(value).date())), formatter('hour', padZero(dayjs(value).hour())), formatter('minute', padZero(dayjs(value).minute()))) + } + } + + // ������������������������������������������������������������������������������������������ + const indexs = this.columns.map((column, index) => { + // ������������������������������������������������������������-1������ + return Math.max(0, column.findIndex(item => item === values[index])) + }) + this.innerDefaultIndex = indexs + }, + // ������������������ + updateColumns() { + const formatter = this.formatter || this.innerFormatter + // ���������������������������map������������������������������������0������ + const results = this.getOriginColumns().map((column) => column.values.map((value) => formatter(column.type, value))) + this.columns = results + }, + getOriginColumns() { + // ������������������ + const results = this.getRanges().map(({ type, range }) => { + let values = times(range[1] - range[0] + 1, (index) => { + let value = range[0] + index + value = type === 'year' ? `${value}` : uni.$u.padZero(value) + return value + }) + // ������������ + if (this.filter) { + values = this.filter(type, values) + } + return { type, values } + }) + return results + }, + // ��������������������������������������� + generateArray(start, end) { + return Array.from(new Array(end + 1).keys()).slice(start) + }, + // ��������������������� + correctValue(value) { + const isDateMode = this.mode !== 'time' + if (isDateMode && !uni.$u.test.date(value)) { + // ������������������������������������������������������������������������������������������������������������ + value = this.minDate + } else if (!isDateMode && !value) { + // ������������������������������������������������������������������������ + value = `${uni.$u.padZero(this.minHour)}:${uni.$u.padZero(this.minMinute)}` + } + // ������������ + if (!isDateMode) { + if (String(value).indexOf(':') === -1) return uni.$u.error('���������������������������12:24���������') + let [hour, minute] = value.split(':') + // ������������������������������������������������������������ + hour = uni.$u.padZero(uni.$u.range(this.minHour, this.maxHour, Number(hour))) + minute = uni.$u.padZero(uni.$u.range(this.minMinute, this.maxMinute, Number(minute))) + return `${ hour }:${ minute }` + } else { + // ������������������������������������������������������������������ + value = dayjs(value).isBefore(dayjs(this.minDate)) ? this.minDate : value + value = dayjs(value).isAfter(dayjs(this.maxDate)) ? this.maxDate : value + return value + } + }, + // ��������������������������������� + getRanges() { + if (this.mode === 'time') { + return [ + { + type: 'hour', + range: [this.minHour, this.maxHour], + }, + { + type: 'minute', + range: [this.minMinute, this.maxMinute], + }, + ]; + } + const { maxYear, maxDate, maxMonth, maxHour, maxMinute, } = this.getBoundary('max', this.innerValue); + const { minYear, minDate, minMonth, minHour, minMinute, } = this.getBoundary('min', this.innerValue); + const result = [ + { + type: 'year', + range: [minYear, maxYear], + }, + { + type: 'month', + range: [minMonth, maxMonth], + }, + { + type: 'day', + range: [minDate, maxDate], + }, + { + type: 'hour', + range: [minHour, maxHour], + }, + { + type: 'minute', + range: [minMinute, maxMinute], + }, + ]; + if (this.mode === 'date') + result.splice(3, 2); + if (this.mode === 'year-month') + result.splice(2, 3); + return result; + }, + // ������minDate���maxDate���minHour���maxHour������������������������������������������������������ + getBoundary(type, innerValue) { + const value = new Date(innerValue) + const boundary = new Date(this[`${type}Date`]) + const year = dayjs(boundary).year() + let month = 1 + let date = 1 + let hour = 0 + let minute = 0 + if (type === 'max') { + month = 12 + // ��������������� + date = dayjs(value).daysInMonth() + hour = 23 + minute = 59 + } + // ������������������������������������������������������(������������������)��������������������������������������������������������� + if (dayjs(value).year() === year) { + month = dayjs(boundary).month() + 1 + if (dayjs(value).month() + 1 === month) { + date = dayjs(boundary).date() + if (dayjs(value).date() === date) { + hour = dayjs(boundary).hour() + if (dayjs(value).hour() === hour) { + minute = dayjs(boundary).minute() + } + } + } + } + return { + [`${type}Year`]: year, + [`${type}Month`]: month, + [`${type}Date`]: date, + [`${type}Hour`]: hour, + [`${type}Minute`]: minute + } + }, + }, + } +</script> + +<style lang="scss" scoped> + @import '../../libs/css/components.scss'; +</style> diff --git a/uni_modules/uview-ui/components/u-divider/props.js b/uni_modules/uview-ui/components/u-divider/props.js new file mode 100644 index 0000000..1fa8359 --- /dev/null +++ b/uni_modules/uview-ui/components/u-divider/props.js @@ -0,0 +1,44 @@ +export default { + props: { + // ������������ + dashed: { + type: Boolean, + default: uni.$u.props.divider.dashed + }, + // ������������ + hairline: { + type: Boolean, + default: uni.$u.props.divider.hairline + }, + // ������������������������������������text��������������� + dot: { + type: Boolean, + default: uni.$u.props.divider.dot + }, + // ������������������������left-���������center-���������right-������ + textPosition: { + type: String, + default: uni.$u.props.divider.textPosition + }, + // ������������ + text: { + type: [String, Number], + default: uni.$u.props.divider.text + }, + // ������������ + textSize: { + type: [String, Number], + default: uni.$u.props.divider.textSize + }, + // ������������ + textColor: { + type: String, + default: uni.$u.props.divider.textColor + }, + // ������������ + lineColor: { + type: String, + default: uni.$u.props.divider.lineColor + } + } +} diff --git a/uni_modules/uview-ui/components/u-divider/u-divider.vue b/uni_modules/uview-ui/components/u-divider/u-divider.vue new file mode 100644 index 0000000..b629da6 --- /dev/null +++ b/uni_modules/uview-ui/components/u-divider/u-divider.vue @@ -0,0 +1,116 @@ +<template> + <view + class="u-divider" + :style="[$u.addStyle(customStyle)]" + @tap="click" + > + <u-line + :color="lineColor" + :customStyle="leftLineStyle" + :hairline="hairline" + :dashed="dashed" + ></u-line> + <text + v-if="dot" + class="u-divider__dot" + >���</text> + <text + v-else-if="text" + class="u-divider__text" + :style="[textStyle]" + >{{text}}</text> + <u-line + :color="lineColor" + :customStyle="rightLineStyle" + :hairline="hairline" + :dashed="dashed" + ></u-line> + </view> +</template> + +<script> + import props from './props.js'; + /** + * divider ��������� + * @description ���������������������������������������������������"������������"������������ + * @tutorial https://www.uviewui.com/components/divider.html + * @property {Boolean} dashed ������������ ��������� false ��� + * @property {Boolean} hairline ������������ ��������� true ��� + * @property {Boolean} dot ������������������������������������text��������������� ��������� false ��� + * @property {String} textPosition ������������������������left-���������center-���������right-������ ��������� 'center' ��� + * @property {String | Number} text ������������ + * @property {String | Number} textSize ������������ ��������� 14��� + * @property {String} textColor ������������ ��������� '#909399' ��� + * @property {String} lineColor ������������ ��������� '#dcdfe6' ��� + * @property {Object} customStyle ��������������������������������� + * + * @event {Function} click divider������������������������ + * @example <u-divider :color="color">���������������������</u-divider> + */ + export default { + name:'u-divider', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + computed: { + textStyle() { + const style = {} + style.fontSize = uni.$u.addUnit(this.textSize) + style.color = this.textColor + return style + }, + // ������������������������ + leftLineStyle() { + const style = {} + // ������������������������������������������������������ + if (this.textPosition === 'left') { + style.width = '80rpx' + } else { + style.flex = 1 + } + return style + }, + // ������������������������ + rightLineStyle() { + const style = {} + // ������������������������������������������������������ + if (this.textPosition === 'right') { + style.width = '80rpx' + } else { + style.flex = 1 + } + return style + } + }, + methods: { + // divider������������������������ + click() { + this.$emit('click'); + } + } + } +</script> + +<style lang="scss" scoped> + @import '../../libs/css/components.scss'; + $u-divider-margin:15px 0 !default; + $u-divider-text-margin:0 15px !default; + $u-divider-dot-font-size:12px !default; + $u-divider-dot-margin:0 12px !default; + $u-divider-dot-color: #c0c4cc !default; + + .u-divider { + @include flex; + flex-direction: row; + align-items: center; + margin: $u-divider-margin; + + &__text { + margin: $u-divider-text-margin; + } + + &__dot { + font-size: $u-divider-dot-font-size; + margin: $u-divider-dot-margin; + color: $u-divider-dot-color; + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-dropdown-item/props.js b/uni_modules/uview-ui/components/u-dropdown-item/props.js new file mode 100644 index 0000000..501a1f0 --- /dev/null +++ b/uni_modules/uview-ui/components/u-dropdown-item/props.js @@ -0,0 +1,36 @@ +export default { + props: { + // ������������������value��� + value: { + type: [Number, String, Array], + default: '' + }, + // ��������������� + title: { + type: [String, Number], + default: '' + }, + // ������������������������������������slot������������������ + options: { + type: Array, + default() { + return [] + } + }, + // ������������������������ + disabled: { + type: Boolean, + default: false + }, + // ��������������������� + height: { + type: [Number, String], + default: 'auto' + }, + // ������������������������������������ + closeOnClickOverlay: { + type: Boolean, + default: true + } + } +} diff --git a/uni_modules/uview-ui/components/u-dropdown-item/u-dropdown-item.vue b/uni_modules/uview-ui/components/u-dropdown-item/u-dropdown-item.vue new file mode 100644 index 0000000..f830291 --- /dev/null +++ b/uni_modules/uview-ui/components/u-dropdown-item/u-dropdown-item.vue @@ -0,0 +1,127 @@ +<template> + <view class="u-drawdown"> + <view + class="u-dropdown__menu" + :style="{ + height: $u.addUnit(height) + }" + ref="u-dropdown__menu" + > + <view + class="u-dropdown__menu__item" + v-for="(item, index) in menuList" + :key="index" + @tap.stop="clickHandler(item, index)" + > + <view class="u-dropdown__menu__item__content"> + <text + class="u-dropdown__menu__item__content__text" + :style="[index === current ? activeStyle : inactiveStyle]" + >{{item.title}}</text> + <view + class="u-dropdown__menu__item__content__arrow" + :class="[index === current && 'u-dropdown__menu__item__content__arrow--rotate']" + > + <u-icon + :name="menuIcon" + :size="$u.addUnit(menuIconSize)" + ></u-icon> + </view> + </view> + </view> + </view> + <view class="u-dropdown__content"> + <slot /> + </view> + </view> +</template> + +<script> +import props from './props.js'; +/** + * Dropdown + * @description + * @tutorial url + * @property {String} + * @event {Function} + * @example + */ +export default { + name: 'u-dropdown', + mixins: [uni.$u.mixin, props], + data() { + return { + // �������������������� + menuList: [], + current: 0 + } + }, + computed: { + + }, + created() { + // ���������������������������������������(u-dropdown-item)������this������������������������data�������������������������������������������������������������������������������������������������������������������������� + this.children = []; + }, + methods: { + clickHandler(item, index) { + this.children.map(child => { + if(child.title === item.title) { + // this.queryRect('u-dropdown__menu').then(size => { + child.$emit('click') + child.setContentAnimate(child.show ? 0 : 300) + child.show = !child.show + // }) + } else { + child.show = false + child.setContentAnimate(0) + } + }) + }, + // ���������������������������������� + queryRect(el) { + // #ifndef APP-NVUE + // $uGetRect��uView����������������������������������������������������������������������������https://www.uviewui.com/js/getRect.html + // �������������������������������this.$uGetRect�����������������������this.$u.getRect���������������������������������������������������� + return new Promise(resolve => { + this.$uGetRect(`.${el}`).then(size => { + resolve(size) + }) + }) + // #endif + + // #ifdef APP-NVUE + // nvue����������������dom������������������������� + // ��������������������promise��������������������������������������������������������������then�������� + return new Promise(resolve => { + dom.getComponentRect(this.$refs[el], res => { + resolve(res.size) + }) + }) + // #endif + }, + }, +} +</script> + +<style lang="scss"> +@import '../../libs/css/components.scss'; + +.u-dropdown { + + &__menu { + @include flex; + + &__item { + flex: 1; + @include flex; + justify-content: center; + + &__content { + @include flex; + align-items: center; + } + } + } +} +</style> diff --git a/uni_modules/uview-ui/components/u-dropdown/props.js b/uni_modules/uview-ui/components/u-dropdown/props.js new file mode 100644 index 0000000..5f8465e --- /dev/null +++ b/uni_modules/uview-ui/components/u-dropdown/props.js @@ -0,0 +1,65 @@ +export default { + props: { + // ������������������������ + activeStyle: { + type: [String, Object], + default: () => ({ + color: '#2979ff', + fontSize: '14px' + }) + }, + // ��������������������������� + inactiveStyle: { + type: [String, Object], + default: () => ({ + color: '#606266', + fontSize: '14px' + }) + }, + // ������������������������������ + closeOnClickMask: { + type: Boolean, + default: true + }, + // ��������������������������������������������� + closeOnClickSelf: { + type: Boolean, + default: true + }, + // ������������ + duration: { + type: [Number, String], + default: 300 + }, + // ��������������������� + height: { + type: [Number, String], + default: 40 + }, + // ��������������������� + borderBottom: { + type: Boolean, + default: false + }, + // ��������������������� + titleSize: { + type: [Number, String], + default: 14 + }, + // ��������������������������������������� + borderRadius: { + type: [Number, String], + default: 0 + }, + // ���������������icon������ + menuIcon: { + type: String, + default: 'arrow-down' + }, + // ��������������������������� + menuIconSize: { + type: [Number, String], + default: 14 + } + } +} diff --git a/uni_modules/uview-ui/components/u-dropdown/u-dropdown.vue b/uni_modules/uview-ui/components/u-dropdown/u-dropdown.vue new file mode 100644 index 0000000..f830291 --- /dev/null +++ b/uni_modules/uview-ui/components/u-dropdown/u-dropdown.vue @@ -0,0 +1,127 @@ +<template> + <view class="u-drawdown"> + <view + class="u-dropdown__menu" + :style="{ + height: $u.addUnit(height) + }" + ref="u-dropdown__menu" + > + <view + class="u-dropdown__menu__item" + v-for="(item, index) in menuList" + :key="index" + @tap.stop="clickHandler(item, index)" + > + <view class="u-dropdown__menu__item__content"> + <text + class="u-dropdown__menu__item__content__text" + :style="[index === current ? activeStyle : inactiveStyle]" + >{{item.title}}</text> + <view + class="u-dropdown__menu__item__content__arrow" + :class="[index === current && 'u-dropdown__menu__item__content__arrow--rotate']" + > + <u-icon + :name="menuIcon" + :size="$u.addUnit(menuIconSize)" + ></u-icon> + </view> + </view> + </view> + </view> + <view class="u-dropdown__content"> + <slot /> + </view> + </view> +</template> + +<script> +import props from './props.js'; +/** + * Dropdown + * @description + * @tutorial url + * @property {String} + * @event {Function} + * @example + */ +export default { + name: 'u-dropdown', + mixins: [uni.$u.mixin, props], + data() { + return { + // �������������������� + menuList: [], + current: 0 + } + }, + computed: { + + }, + created() { + // ���������������������������������������(u-dropdown-item)������this������������������������data�������������������������������������������������������������������������������������������������������������������������� + this.children = []; + }, + methods: { + clickHandler(item, index) { + this.children.map(child => { + if(child.title === item.title) { + // this.queryRect('u-dropdown__menu').then(size => { + child.$emit('click') + child.setContentAnimate(child.show ? 0 : 300) + child.show = !child.show + // }) + } else { + child.show = false + child.setContentAnimate(0) + } + }) + }, + // ���������������������������������� + queryRect(el) { + // #ifndef APP-NVUE + // $uGetRect��uView����������������������������������������������������������������������������https://www.uviewui.com/js/getRect.html + // �������������������������������this.$uGetRect�����������������������this.$u.getRect���������������������������������������������������� + return new Promise(resolve => { + this.$uGetRect(`.${el}`).then(size => { + resolve(size) + }) + }) + // #endif + + // #ifdef APP-NVUE + // nvue����������������dom������������������������� + // ��������������������promise��������������������������������������������������������������then�������� + return new Promise(resolve => { + dom.getComponentRect(this.$refs[el], res => { + resolve(res.size) + }) + }) + // #endif + }, + }, +} +</script> + +<style lang="scss"> +@import '../../libs/css/components.scss'; + +.u-dropdown { + + &__menu { + @include flex; + + &__item { + flex: 1; + @include flex; + justify-content: center; + + &__content { + @include flex; + align-items: center; + } + } + } +} +</style> diff --git a/uni_modules/uview-ui/components/u-empty/props.js b/uni_modules/uview-ui/components/u-empty/props.js new file mode 100644 index 0000000..78662f8 --- /dev/null +++ b/uni_modules/uview-ui/components/u-empty/props.js @@ -0,0 +1,59 @@ +export default { + props: { + // ��������������������������������������������������������� + icon: { + type: String, + default: uni.$u.props.empty.icon + }, + // ������������ + text: { + type: String, + default: uni.$u.props.empty.text + }, + // ������������ + textColor: { + type: String, + default: uni.$u.props.empty.textColor + }, + // ������������ + textSize: { + type: [String, Number], + default: uni.$u.props.empty.textSize + }, + // ��������������� + iconColor: { + type: String, + default: uni.$u.props.empty.iconColor + }, + // ��������������� + iconSize: { + type: [String, Number], + default: uni.$u.props.empty.iconSize + }, + // ��������������������������� + mode: { + type: String, + default: uni.$u.props.empty.mode + }, + // ���������������������px + width: { + type: [String, Number], + default: uni.$u.props.empty.width + }, + // ���������������������px + height: { + type: [String, Number], + default: uni.$u.props.empty.height + }, + // ������������������ + show: { + type: Boolean, + default: uni.$u.props.empty.show + }, + // ���������������������������������������������������px������ + marginTop: { + type: [String, Number], + default: uni.$u.props.empty.marginTop + } + } +} diff --git a/uni_modules/uview-ui/components/u-empty/u-empty.vue b/uni_modules/uview-ui/components/u-empty/u-empty.vue new file mode 100644 index 0000000..03d6a27 --- /dev/null +++ b/uni_modules/uview-ui/components/u-empty/u-empty.vue @@ -0,0 +1,128 @@ +<template> + <view + class="u-empty" + :style="[emptyStyle]" + v-if="show" + > + <u-icon + v-if="!isSrc" + :name="mode === 'message' ? 'chat' : `empty-${mode}`" + :size="iconSize" + :color="iconColor" + margin-top="14" + ></u-icon> + <image + v-else + :style="{ + width: $u.addUnit(width), + height: $u.addUnit(height), + }" + :src="icon" + mode="widthFix" + ></image> + <text + class="u-empty__text" + :style="[textStyle]" + >{{text ? text : icons[mode]}}</text> + <view class="u-empty__wrap" v-if="$slots.default || $slots.$default"> + <slot /> + </view> + </view> +</template> + +<script> + import props from './props.js'; + + /** + * empty ������������ + * @description ������������������������������������������������������������������������������������������"������������"������������ ������������������������������������������������������������������ + * @tutorial https://www.uviewui.com/components/empty.html + * @property {String} icon ��������������������������������������������������������� + * @property {String} text ������������ + * @property {String} textColor ������������ (������ '#c0c4cc' ) + * @property {String | Number} textSize ������������ ��������� 14 ��� + * @property {String} iconColor ��������������� ��������� '#c0c4cc' ��� + * @property {String | Number} iconSize ��������������� ��������� 90 ��� + * @property {String} mode ��������������������������� ��������� 'data' ��� + * @property {String | Number} width ���������������������px ��������� 160 ��� + * @property {String | Number} height ���������������������px ��������� 160 ��� + * @property {Boolean} show ������������������ ��������� true ��� + * @property {String | Number} marginTop ���������������������������������������������������px������ ��������� 0 ��� + * @property {Object} customStyle ��������������������������������� + * + * @event {Function} click ��������������������� + * @event {Function} close ��������������������������� + * @example <u-empty text="���������������������������" mode="list"></u-empty> + */ + export default { + name: "u-empty", + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + icons: { + car: '���������������', + page: '���������������', + search: '������������������', + address: '������������������', + wifi: '������WiFi', + order: '������������', + coupon: '���������������', + favor: '������������', + permission: '���������', + history: '���������������', + news: '���������������', + message: '������������������', + list: '������������', + data: '������������', + comment: '������������', + } + } + }, + computed: { + // ������������ + emptyStyle() { + const style = {} + style.marginTop = uni.$u.addUnit(this.marginTop) + // ������customStyle������������������������mixin������props������ + return uni.$u.deepMerge(uni.$u.addStyle(this.customStyle), style) + }, + // ������������ + textStyle() { + const style = {} + style.color = this.textColor + style.fontSize = uni.$u.addUnit(this.textSize) + return style + }, + // ������icon������������������ + isSrc() { + return this.icon.indexOf('/') >= 0 + } + } + } +</script> + +<style lang="scss" scoped> + @import '../../libs/css/components.scss'; + $u-empty-text-margin-top:20rpx !default; + $u-empty-slot-margin-top:20rpx !default; + + .u-empty { + @include flex; + flex-direction: column; + justify-content: center; + align-items: center; + + &__text { + @include flex; + justify-content: center; + align-items: center; + margin-top: $u-empty-text-margin-top; + } + } + .u-slot-wrap { + @include flex; + justify-content: center; + align-items: center; + margin-top:$u-empty-slot-margin-top; + } +</style> diff --git a/uni_modules/uview-ui/components/u-form-item/props.js b/uni_modules/uview-ui/components/u-form-item/props.js new file mode 100644 index 0000000..7b16655 --- /dev/null +++ b/uni_modules/uview-ui/components/u-form-item/props.js @@ -0,0 +1,48 @@ +export default { + props: { + // input���label��������� + label: { + type: String, + default: uni.$u.props.formItem.label + }, + // ������������ + prop: { + type: String, + default: uni.$u.props.formItem.prop + }, + // ��������������������������������������� + borderBottom: { + type: [String, Boolean], + default: uni.$u.props.formItem.borderBottom + }, + // label������������left-���������top-������ + labelPosition: { + type: String, + default: uni.$u.props.formItem.labelPosition + }, + // label������������������px + labelWidth: { + type: [String, Number], + default: uni.$u.props.formItem.labelWidth + }, + // ������������ + rightIcon: { + type: String, + default: uni.$u.props.formItem.rightIcon + }, + // ������������ + leftIcon: { + type: String, + default: uni.$u.props.formItem.leftIcon + }, + // ������������������������������������������������������������������������������������������rules��������� + required: { + type: Boolean, + default: uni.$u.props.formItem.required + }, + leftIconStyle: { + type: [String, Object], + default: uni.$u.props.formItem.leftIconStyle, + } + } +} diff --git a/uni_modules/uview-ui/components/u-form-item/u-form-item.vue b/uni_modules/uview-ui/components/u-form-item/u-form-item.vue new file mode 100644 index 0000000..6aa8d69 --- /dev/null +++ b/uni_modules/uview-ui/components/u-form-item/u-form-item.vue @@ -0,0 +1,235 @@ +<template> + <view class="u-form-item"> + <view + class="u-form-item__body" + @tap="clickHandler" + :style="[$u.addStyle(customStyle), { + flexDirection: (labelPosition || parentData.labelPosition) === 'left' ? 'row' : 'column' + }]" + > + <!-- ���������������������������������������������������������������������������������"true" --> + <slot name="label"> + <!-- {{required}} --> + <view + class="u-form-item__body__left" + v-if="required || leftIcon || label" + :style="{ + width: $u.addUnit(labelWidth || parentData.labelWidth), + marginBottom: parentData.labelPosition === 'left' ? 0 : '5px', + }" + > + <!-- ��������������� --> + <view class="u-form-item__body__left__content"> + <!-- nvue������������������before --> + <text + v-if="required" + class="u-form-item__body__left__content__required" + >*</text> + <view + class="u-form-item__body__left__content__icon" + v-if="leftIcon" + > + <u-icon + :name="leftIcon" + :custom-style="leftIconStyle" + ></u-icon> + </view> + <text + class="u-form-item__body__left__content__label" + :style="[parentData.labelStyle, { + justifyContent: parentData.labelAlign === 'left' ? 'flex-start' : parentData.labelAlign === 'center' ? 'center' : 'flex-end' + }]" + >{{ label }}</text> + </view> + </view> + </slot> + <view class="u-form-item__body__right"> + <view class="u-form-item__body__right__content"> + <view class="u-form-item__body__right__content__slot"> + <slot /> + </view> + <view + class="item__body__right__content__icon" + v-if="$slots.right" + > + <slot name="right" /> + </view> + </view> + </view> + </view> + <slot name="error"> + <text + v-if="!!message && parentData.errorType === 'message'" + class="u-form-item__body__right__message" + :style="{ + marginLeft: $u.addUnit(parentData.labelPosition === 'top' ? 0 : (labelWidth || parentData.labelWidth)) + }" + >{{ message }}</text> + </slot> + <u-line + v-if="borderBottom" + :color="message && parentData.errorType === 'border-bottom' ? $u.color.error : propsLine.color" + :customStyle="`margin-top: ${message && parentData.errorType === 'message' ? '5px' : 0}`" + ></u-line> + </view> +</template> + +<script> + import props from './props.js'; + /** + * Form ������ + * @description ������������������������������������������������Input������������Select������������������������������������ + * @tutorial https://www.uviewui.com/components/form.html + * @property {String} label input���label��������� + * @property {String} prop ������������ + * @property {String | Boolean} borderBottom ��������������������������������������� + * @property {String | Number} labelWidth label������������������px + * @property {String} rightIcon ������������ + * @property {String} leftIcon ������������ + * @property {String | Object} leftIconStyle ��������������������� + * @property {Boolean} required ������������������������������������������������������������������������������������������rules��������� (������ false ) + * + * @example <u-form-item label="������" prop="userInfo.name" borderBottom ref="item1"></u-form-item> + */ + export default { + name: 'u-form-item', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + // ��������������� + message: '', + parentData: { + // ��������������������� + labelPosition: 'left', + // ������������������������ + labelAlign: 'left', + // ��������������������� + labelStyle: {}, + // ��������������������� + labelWidth: 45, + // ������������������ + errorType: 'message' + } + } + }, + // ������������������������������������������������u-form��� + computed: { + propsLine() { + return uni.$u.props.line + } + }, + mounted() { + this.init() + }, + methods: { + init() { + // ������������������ + this.updateParentData() + if (!this.parent) { + uni.$u.error('u-form-item������������u-form������������') + } + }, + // ������������������������ + updateParentData() { + // ���������������mixin��� + this.getParentData('u-form'); + }, + // ������u-form-item��������������� + clearValidate() { + this.message = null + }, + // ������������������������������������������������������������ + resetField() { + // ��������������� + const value = uni.$u.getProperty(this.parent.originalModel, this.prop) + // ���u-form���model���prop������������������������ + uni.$u.setProperty(this.parent.model, this.prop, value) + // ������������������ + this.message = null + }, + // ������������ + clickHandler() { + this.$emit('click') + } + }, + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-form-item { + @include flex(column); + font-size: 14px; + color: $u-main-color; + + &__body { + @include flex; + padding: 10px 0; + + &__left { + @include flex; + align-items: center; + + &__content { + position: relative; + @include flex; + align-items: center; + padding-right: 10rpx; + flex: 1; + + &__icon { + margin-right: 8rpx; + } + + &__required { + position: absolute; + left: -9px; + color: $u-error; + line-height: 20px; + font-size: 20px; + top: 3px; + } + + &__label { + @include flex; + align-items: center; + flex: 1; + color: $u-main-color; + font-size: 15px; + } + } + } + + &__right { + flex: 1; + + &__content { + @include flex; + align-items: center; + flex: 1; + + &__slot { + flex: 1; + /* #ifndef MP */ + @include flex; + align-items: center; + /* #endif */ + } + + &__icon { + margin-left: 10rpx; + color: $u-light-color; + font-size: 30rpx; + } + } + + &__message { + font-size: 12px; + line-height: 12px; + color: $u-error; + } + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-form/props.js b/uni_modules/uview-ui/components/u-form/props.js new file mode 100644 index 0000000..f2a629c --- /dev/null +++ b/uni_modules/uview-ui/components/u-form/props.js @@ -0,0 +1,45 @@ +export default { + props: { + // ������form������������������������������ + model: { + type: Object, + default: uni.$u.props.form.model + }, + // ������������ + rules: { + type: [Object, Function, Array], + default: uni.$u.props.form.rules + }, + // ������������������������������message-���������������toast-������toast������ + // border-bottom-������������������������none-��������� + errorType: { + type: String, + default: uni.$u.props.form.errorType + }, + // ��������������������������������������� + borderBottom: { + type: Boolean, + default: uni.$u.props.form.borderBottom + }, + // label������������left-���������top-������ + labelPosition: { + type: String, + default: uni.$u.props.form.labelPosition + }, + // label������������������px + labelWidth: { + type: [String, Number], + default: uni.$u.props.form.labelWidth + }, + // lable��������������������� + labelAlign: { + type: String, + default: uni.$u.props.form.labelAlign + }, + // lable������������������������ + labelStyle: { + type: Object, + default: uni.$u.props.form.labelStyle + } + } +} diff --git a/uni_modules/uview-ui/components/u-form/u-form.vue b/uni_modules/uview-ui/components/u-form/u-form.vue new file mode 100644 index 0000000..fe2dde2 --- /dev/null +++ b/uni_modules/uview-ui/components/u-form/u-form.vue @@ -0,0 +1,214 @@ +<template> + <view class="u-form"> + <slot /> + </view> +</template> + +<script> + import props from "./props.js"; + import Schema from "../../libs/util/async-validator"; + // ������������������ + Schema.warning = function() {}; + /** + * Form ������ + * @description ������������������������������������������������Input������������Select������������������������������������ + * @tutorial https://www.uviewui.com/components/form.html + * @property {Object} model ������form������������������������������ + * @property {Object | Function | Array} rules ������������ + * @property {String} errorType ��������������������������������������� ( ������ message ) + * @property {Boolean} borderBottom ��������������������������������������� ( ������ true ��� + * @property {String} labelPosition ���������������������������������left-���������top-������ ( ������ 'left' ��� + * @property {String | Number} labelWidth ������������������������������px ( ������ 45 ��� + * @property {String} labelAlign lable��������������������� ( ������ ���left' ��� + * @property {Object} labelStyle lable������������������������ + * @example <u--formlabelPosition="left" :model="model1" :rules="rules" ref="form1"></u--form> + */ + export default { + name: "u-form", + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + provide() { + return { + uForm: this, + }; + }, + data() { + return { + formRules: {}, + // ��������������� + validator: {}, + // ���������model���������������resetFields��������������������������� + originalModel: null, + }; + }, + watch: { + // ��������������������� + rules: { + immediate: true, + handler(n) { + this.setRules(n); + }, + }, + // ���������������������������������������u-form-item������������������ + propsChange(n) { + if (this.children?.length) { + this.children.map((child) => { + // ���������������(u-form-item)���������updateParentData���������������������������(������������������������������������������������������������������) + typeof child.updateParentData == "function" && + child.updateParentData(); + }); + } + }, + // ������model��������������������������������������� + model: { + immediate: true, + handler(n) { + if (!this.originalModel) { + this.originalModel = uni.$u.deepClone(n); + } + }, + }, + }, + computed: { + propsChange() { + return [ + this.errorType, + this.borderBottom, + this.labelPosition, + this.labelWidth, + this.labelAlign, + this.labelStyle, + ]; + }, + }, + created() { + // ������������form������������u-form-item��������� + // ���������������data��������������������������������������������������������� + this.children = []; + }, + methods: { + // ������������������������������������������������������������������������������������������������������������������������������������ + setRules(rules) { + // ��������������������� + if (Object.keys(rules).length === 0) return; + if (process.env.NODE_ENV === 'development' && Object.keys(this.model).length === 0) { + uni.$u.error('������rules���model������������������������������������������������������'); + return; + }; + this.formRules = rules; + // ���������������������Validator + this.validator = new Schema(rules); + }, + // ������������u-form-item���������������������������������������u-form-item������������resetField()������ + resetFields() { + this.resetModel(); + }, + // ������model��������������������� + resetModel(obj) { + // ������������u-form-item������������prop���������������model��������������� + this.children.map((child) => { + const prop = child?.prop; + const value = uni.$u.getProperty(this.originalModel, prop); + uni.$u.setProperty(this.model, prop, value); + }); + }, + // ������������������ + clearValidate(props) { + props = [].concat(props); + this.children.map((child) => { + // ������u-form-item���prop���props������������������������������������������������ + if (props[0] === undefined || props.includes(child.prop)) { + child.message = null; + } + }); + }, + // ��������������������������������� + async validateField(value, callback, event = null) { + // $nextTick���������������������model������������������������������������������������ + this.$nextTick(() => { + // ���������������������������������������������������������������form-item��������������� + const errorsRes = []; + // ��������������������������������� + value = [].concat(value); + // ������children���������form-item + this.children.map((child) => { + // ������������form-item��������������� + const childErrors = []; + if (value.includes(child.prop)) { + // ������������������������������������'a.b.c'��������� + const propertyVal = uni.$u.getProperty( + this.model, + child.prop + ); + // ��������������� + const propertyChain = child.prop.split("."); + const propertyName = + propertyChain[propertyChain.length - 1]; + + const rule = this.formRules[child.prop]; + // ������������������������������������������������������������������������ + if (!rule) return; + // rule��������������������������������������������������������������������������� + const rules = [].concat(rule); + + // ���rules������������������ + for (let i = 0; i < rules.length; i++) { + const ruleItem = rules[i]; + // ���u-form-item������������������������������ + const trigger = [].concat(ruleItem?.trigger); + // ������������������������������������������form-item��������������������������������������������������������� + if (event && !trigger.includes(event)) continue; + // ������������������������������������������ + const validator = new Schema({ + [propertyName]: ruleItem, + }); + validator.validate({ + [propertyName]: propertyVal, + }, + (errors, fields) => { + if (uni.$u.test.array(errors)) { + errorsRes.push(...errors); + childErrors.push(...errors); + } + child.message = + childErrors[0]?.message ?? null; + } + ); + } + } + }); + // ������������������ + typeof callback === "function" && callback(errorsRes); + }); + }, + // ������������������ + validate(callback) { + // ������������������������������������������������ + if (process.env.NODE_ENV === 'development' && Object.keys(this.formRules).length === 0) { + uni.$u.error('���������rules���������������������������������������������������������������'); + return; + } + return new Promise((resolve, reject) => { + // $nextTick���������������������model������������������������������validate������ + this.$nextTick(() => { + // ������������form-item���prop���������validateField������������������ + const formItemProps = this.children.map( + (item) => item.prop + ); + this.validateField(formItemProps, (errors) => { + if(errors.length) { + // ���������������������������toast������������������ + this.errorType === 'toast' && uni.$u.toast(errors[0].message) + reject(errors) + } else { + resolve(true) + } + }); + }); + }); + }, + }, + }; +</script> + +<style lang="scss" scoped> +</style> diff --git a/uni_modules/uview-ui/components/u-gap/props.js b/uni_modules/uview-ui/components/u-gap/props.js new file mode 100644 index 0000000..89953e3 --- /dev/null +++ b/uni_modules/uview-ui/components/u-gap/props.js @@ -0,0 +1,24 @@ +export default { + props: { + // ���������������������transparent��� + bgColor: { + type: String, + default: uni.$u.props.gap.bgColor + }, + // ������������������������px���������30��� + height: { + type: [String, Number], + default: uni.$u.props.gap.height + }, + // ��������������������������� + marginTop: { + type: [String, Number], + default: uni.$u.props.gap.marginTop + }, + // ��������������������������� + marginBottom: { + type: [String, Number], + default: uni.$u.props.gap.marginBottom + } + } +} diff --git a/uni_modules/uview-ui/components/u-gap/u-gap.vue b/uni_modules/uview-ui/components/u-gap/u-gap.vue new file mode 100644 index 0000000..e4429f0 --- /dev/null +++ b/uni_modules/uview-ui/components/u-gap/u-gap.vue @@ -0,0 +1,38 @@ +<template> + <view class="u-gap" :style="[gapStyle]"></view> +</template> + +<script> + import props from './props.js'; + /** + * gap ��������� + * @description ��������������������������������������������������������������������������������������������������������������������� + * @tutorial https://www.uviewui.com/components/gap.html + * @property {String} bgColor ������������ ��������� 'transparent' ��� + * @property {String | Number} height ������������������������px ��������� 20 ��� + * @property {String | Number} marginTop ������������������������������������px��� ������ 0 ��� + * @property {String | Number} marginBottom ������������������������������������px ��������� 0 ��� + * @property {Object} customStyle ��������������������������������� + * + * @example <u-gap height="80" bg-color="#bbb"></u-gap> + */ + export default { + name: "u-gap", + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + computed: { + gapStyle() { + const style = { + backgroundColor: this.bgColor, + height: uni.$u.addUnit(this.height), + marginTop: uni.$u.addUnit(this.marginTop), + marginBottom: uni.$u.addUnit(this.marginBottom), + } + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) + } + } + }; +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; +</style> diff --git a/uni_modules/uview-ui/components/u-grid-item/props.js b/uni_modules/uview-ui/components/u-grid-item/props.js new file mode 100644 index 0000000..06c3c66 --- /dev/null +++ b/uni_modules/uview-ui/components/u-grid-item/props.js @@ -0,0 +1,14 @@ +export default { + props: { + // ���������name + name: { + type: [String, Number, null], + default: uni.$u.props.gridItem.name + }, + // ������������ + bgColor: { + type: String, + default: uni.$u.props.gridItem.bgColor + } + } +} diff --git a/uni_modules/uview-ui/components/u-grid-item/u-grid-item.vue b/uni_modules/uview-ui/components/u-grid-item/u-grid-item.vue new file mode 100644 index 0000000..fc0c7cf --- /dev/null +++ b/uni_modules/uview-ui/components/u-grid-item/u-grid-item.vue @@ -0,0 +1,209 @@ +<template> + <!-- #ifndef APP-NVUE --> + <view + class="u-grid-item" + hover-class="u-grid-item--hover-class" + :hover-stay-time="200" + @tap="clickHandler" + :class="classes" + :style="[itemStyle]" + > + <slot /> + </view> + <!-- #endif --> + <!-- #ifdef APP-NVUE --> + <view + class="u-grid-item" + :hover-stay-time="200" + @tap="clickHandler" + :class="classes" + :style="[itemStyle]" + > + <slot /> + </view> + <!-- #endif --> +</template> + +<script> + import props from './props.js'; + /** + * gridItem ������ + * @description ������������������������������������������������������������������������������������������������������������(badge)���������������������������������������������������������������������������u-grid������ + * @tutorial https://www.uviewui.com/components/grid.html + * @property {String | Number} name ���������name ( ������ null ) + * @property {String} bgColor ��������������������� ��������� 'transparent' ��� + * @property {Object} customStyle ������������������������������ + * @event {Function} click ������������������ + * @example <u-grid-item></u-grid-item> + */ + export default { + name: "u-grid-item", + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + parentData: { + col: 3, // ��������������������������� + border: true, // ������������������������������������������ + }, + // #ifdef APP-NVUE + width: 0, // nvue���������������������vue���������computed��������������������������������������� + // #endif + classes: [], // ��������������������������������������������������������� + }; + }, + mounted() { + this.init() + }, + computed: { + // #ifndef APP-NVUE + // vue���������computed��������������������������������������� + width() { + return 100 / Number(this.parentData.col) + '%' + }, + // #endif + itemStyle() { + const style = { + background: this.bgColor, + width: this.width + } + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) + } + }, + methods: { + init() { + // ������������������u-grid���children������������������������������ + // ������������item��������� + uni.$on('$uGridItem', () => { + this.gridItemClasses() + }) + // ������������������ + this.updateParentData() + // #ifdef APP-NVUE + // ������������������������������nvue��������������������� + this.$nextTick(function(){ + this.getItemWidth() + }) + // #endif + // ������������������������������grid-item������������������������������ + uni.$emit('$uGridItem') + this.gridItemClasses() + }, + // ������������������������ + updateParentData() { + // ���������������mixin��� + this.getParentData('u-grid'); + }, + clickHandler() { + let name = this.name + // ������������������name���������������������������children������������������������������������������������this������������������������������������ + const children = this.parent?.children + if(children && this.name === null) { + name = children.findIndex(child => child === this) + } + // ������������������������������������ + this.parent && this.parent.childClick(name) + this.$emit('click', name) + }, + async getItemWidth() { + // ���������nvue��������������������������������������������������� + let width = 0 + if(this.parent) { + // ���������������������������������������������������������item��������� + const parentWidth = await this.getParentWidth() + width = parentWidth / Number(this.parentData.col) + 'px' + } + this.width = width + }, + // ������������������������ + getParentWidth() { + // #ifdef APP-NVUE + // ������������promise������������������������await������������ + const dom = uni.requireNativePlugin('dom') + return new Promise(resolve => { + // ������������������ref + dom.getComponentRect(this.parent.$refs['u-grid'], res => { + resolve(res.size.width) + }) + }) + // #endif + }, + gridItemClasses() { + if(this.parentData.border) { + const classes = [] + this.parent.children.map((child, index) =>{ + if(this === child) { + const len = this.parent.children.length + // ���������������������������child������������������������������������������2��������������������������������� + if((index + 1) % this.parentData.col !== 0 && index + 1 !== len) { + classes.push('u-border-right') + } + // ��������������������������������������� + // ������������������������0������������������������������������������������������������������ + const lessNum = len % this.parentData.col === 0 ? this.parentData.col : len % this.parentData.col + // ������������������child������������������ + if(index < len - lessNum) { + classes.push('u-border-bottom') + } + } + }) + // ������������������������������������������������������������������������������������������������������","������������������ + // #ifdef MP-ALIPAY || MP-TOUTIAO + classes = classes.join(' ') + // #endif + this.classes = classes + } + } + }, + beforeDestroy() { + // ��������������������������������� + uni.$off('$uGridItem') + } + }; +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + $u-grid-item-hover-class-opcatiy:.5 !default; + $u-grid-item-margin-top:1rpx !default; + $u-grid-item-border-right-width:0.5px !default; + $u-grid-item-border-bottom-width:0.5px !default; + $u-grid-item-border-right-color:$u-border-color !default; + $u-grid-item-border-bottom-color:$u-border-color !default; + .u-grid-item { + align-items: center; + justify-content: center; + position: relative; + flex-direction: column; + /* #ifndef APP-NVUE */ + box-sizing: border-box; + display: flex; + /* #endif */ + + /* #ifdef MP */ + position: relative; + float: left; + /* #endif */ + + /* #ifdef MP-WEIXIN */ + margin-top:$u-grid-item-margin-top; + /* #endif */ + + &--hover-class { + opacity:$u-grid-item-hover-class-opcatiy; + } + } + + /* #ifdef APP-NVUE */ + // ������nvue������������������������app.vue������������������������������������������������ + .u-border-right { + border-right-width:$u-grid-item-border-right-width; + border-color: $u-grid-item-border-right-color; + } + + .u-border-bottom { + border-bottom-width:$u-grid-item-border-bottom-width; + border-color:$u-grid-item-border-bottom-color; + } + + /* #endif */ +</style> diff --git a/uni_modules/uview-ui/components/u-grid/props.js b/uni_modules/uview-ui/components/u-grid/props.js new file mode 100644 index 0000000..87b0f6a --- /dev/null +++ b/uni_modules/uview-ui/components/u-grid/props.js @@ -0,0 +1,19 @@ +export default { + props: { + // ������������ + col: { + type: [String, Number], + default: uni.$u.props.grid.col + }, + // ������������������ + border: { + type: Boolean, + default: uni.$u.props.grid.border + }, + // ��������������������������������������������������������������������������������� + align: { + type: String, + default: uni.$u.props.grid.align + } + } +} diff --git a/uni_modules/uview-ui/components/u-grid/u-grid.vue b/uni_modules/uview-ui/components/u-grid/u-grid.vue new file mode 100644 index 0000000..b43cc27 --- /dev/null +++ b/uni_modules/uview-ui/components/u-grid/u-grid.vue @@ -0,0 +1,97 @@ +<template> + <view + class="u-grid" + ref='u-grid' + :style="[gridStyle]" + > + <slot /> + </view> +</template> + +<script> + import props from './props.js'; + /** + * grid ������������ + * @description ������������������������������������������������������������������������������������������������������������(badge)��������������������������������������������������������������������� + * @tutorial https://www.uviewui.com/components/grid.html + * @property {String | Number} col ������������������������ 3 ��� + * @property {Boolean} border ������������������������������������ false ��� + * @property {String} align ��������������������������������������������������������������������������������� ��������� 'left' ��� + * @property {Object} customStyle ��������������������������������� + * @event {Function} click ������������������ + * @example <u-grid :col="3" @click="click"></u-grid> + */ + export default { + name: 'u-grid', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + index: 0, + width: 0 + } + }, + watch: { + // ��������������������������������������������������������������������������������������� + parentData() { + if (this.children.length) { + this.children.map(child => { + // ���������������(u-radio)���������updateParentData���������������������������(������������������������������������������������������������������) + typeof(child.updateParentData) == 'function' && child.updateParentData(); + }) + } + }, + }, + created() { + // ���������children���������data������������������������������������������������������ + this.children = [] + }, + computed: { + // ��������������������������������������� + parentData() { + return [this.hoverClass, this.col, this.size, this.border]; + }, + // ������������������ + gridStyle() { + let style = {}; + switch (this.align) { + case 'left': + style.justifyContent = 'flex-start'; + break; + case 'center': + style.justifyContent = 'center'; + break; + case 'right': + style.justifyContent = 'flex-end'; + break; + default: + style.justifyContent = 'flex-start'; + }; + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)); + } + }, + methods: { + // ������������u-grid-item������������������u-grid������������ + childClick(name) { + this.$emit('click', name) + } + } + }; +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + $u-grid-width:100% !default; + .u-grid { + /* #ifdef MP */ + width: $u-grid-width; + position: relative; + box-sizing: border-box; + overflow: hidden; + display: block; + /* #endif */ + justify-content: center; + @include flex; + flex-wrap: wrap; + align-items: center; + } +</style> diff --git a/uni_modules/uview-ui/components/u-icon/icons.js b/uni_modules/uview-ui/components/u-icon/icons.js new file mode 100644 index 0000000..f4d0fe2 --- /dev/null +++ b/uni_modules/uview-ui/components/u-icon/icons.js @@ -0,0 +1,214 @@ +export default { + 'uicon-level': '\ue693', + 'uicon-column-line': '\ue68e', + 'uicon-checkbox-mark': '\ue807', + 'uicon-folder': '\ue7f5', + 'uicon-movie': '\ue7f6', + 'uicon-star-fill': '\ue669', + 'uicon-star': '\ue65f', + 'uicon-phone-fill': '\ue64f', + 'uicon-phone': '\ue622', + 'uicon-apple-fill': '\ue881', + 'uicon-chrome-circle-fill': '\ue885', + 'uicon-backspace': '\ue67b', + 'uicon-attach': '\ue632', + 'uicon-cut': '\ue948', + 'uicon-empty-car': '\ue602', + 'uicon-empty-coupon': '\ue682', + 'uicon-empty-address': '\ue646', + 'uicon-empty-favor': '\ue67c', + 'uicon-empty-permission': '\ue686', + 'uicon-empty-news': '\ue687', + 'uicon-empty-search': '\ue664', + 'uicon-github-circle-fill': '\ue887', + 'uicon-rmb': '\ue608', + 'uicon-person-delete-fill': '\ue66a', + 'uicon-reload': '\ue788', + 'uicon-order': '\ue68f', + 'uicon-server-man': '\ue6bc', + 'uicon-search': '\ue62a', + 'uicon-fingerprint': '\ue955', + 'uicon-more-dot-fill': '\ue630', + 'uicon-scan': '\ue662', + 'uicon-share-square': '\ue60b', + 'uicon-map': '\ue61d', + 'uicon-map-fill': '\ue64e', + 'uicon-tags': '\ue629', + 'uicon-tags-fill': '\ue651', + 'uicon-bookmark-fill': '\ue63b', + 'uicon-bookmark': '\ue60a', + 'uicon-eye': '\ue613', + 'uicon-eye-fill': '\ue641', + 'uicon-mic': '\ue64a', + 'uicon-mic-off': '\ue649', + 'uicon-calendar': '\ue66e', + 'uicon-calendar-fill': '\ue634', + 'uicon-trash': '\ue623', + 'uicon-trash-fill': '\ue658', + 'uicon-play-left': '\ue66d', + 'uicon-play-right': '\ue610', + 'uicon-minus': '\ue618', + 'uicon-plus': '\ue62d', + 'uicon-info': '\ue653', + 'uicon-info-circle': '\ue7d2', + 'uicon-info-circle-fill': '\ue64b', + 'uicon-question': '\ue715', + 'uicon-error': '\ue6d3', + 'uicon-close': '\ue685', + 'uicon-checkmark': '\ue6a8', + 'uicon-android-circle-fill': '\ue67e', + 'uicon-android-fill': '\ue67d', + 'uicon-ie': '\ue87b', + 'uicon-IE-circle-fill': '\ue889', + 'uicon-google': '\ue87a', + 'uicon-google-circle-fill': '\ue88a', + 'uicon-setting-fill': '\ue872', + 'uicon-setting': '\ue61f', + 'uicon-minus-square-fill': '\ue855', + 'uicon-plus-square-fill': '\ue856', + 'uicon-heart': '\ue7df', + 'uicon-heart-fill': '\ue851', + 'uicon-camera': '\ue7d7', + 'uicon-camera-fill': '\ue870', + 'uicon-more-circle': '\ue63e', + 'uicon-more-circle-fill': '\ue645', + 'uicon-chat': '\ue620', + 'uicon-chat-fill': '\ue61e', + 'uicon-bag-fill': '\ue617', + 'uicon-bag': '\ue619', + 'uicon-error-circle-fill': '\ue62c', + 'uicon-error-circle': '\ue624', + 'uicon-close-circle': '\ue63f', + 'uicon-close-circle-fill': '\ue637', + 'uicon-checkmark-circle': '\ue63d', + 'uicon-checkmark-circle-fill': '\ue635', + 'uicon-question-circle-fill': '\ue666', + 'uicon-question-circle': '\ue625', + 'uicon-share': '\ue631', + 'uicon-share-fill': '\ue65e', + 'uicon-shopping-cart': '\ue621', + 'uicon-shopping-cart-fill': '\ue65d', + 'uicon-bell': '\ue609', + 'uicon-bell-fill': '\ue640', + 'uicon-list': '\ue650', + 'uicon-list-dot': '\ue616', + 'uicon-zhihu': '\ue6ba', + 'uicon-zhihu-circle-fill': '\ue709', + 'uicon-zhifubao': '\ue6b9', + 'uicon-zhifubao-circle-fill': '\ue6b8', + 'uicon-weixin-circle-fill': '\ue6b1', + 'uicon-weixin-fill': '\ue6b2', + 'uicon-twitter-circle-fill': '\ue6ab', + 'uicon-twitter': '\ue6aa', + 'uicon-taobao-circle-fill': '\ue6a7', + 'uicon-taobao': '\ue6a6', + 'uicon-weibo-circle-fill': '\ue6a5', + 'uicon-weibo': '\ue6a4', + 'uicon-qq-fill': '\ue6a1', + 'uicon-qq-circle-fill': '\ue6a0', + 'uicon-moments-circel-fill': '\ue69a', + 'uicon-moments': '\ue69b', + 'uicon-qzone': '\ue695', + 'uicon-qzone-circle-fill': '\ue696', + 'uicon-baidu-circle-fill': '\ue680', + 'uicon-baidu': '\ue681', + 'uicon-facebook-circle-fill': '\ue68a', + 'uicon-facebook': '\ue689', + 'uicon-car': '\ue60c', + 'uicon-car-fill': '\ue636', + 'uicon-warning-fill': '\ue64d', + 'uicon-warning': '\ue694', + 'uicon-clock-fill': '\ue638', + 'uicon-clock': '\ue60f', + 'uicon-edit-pen': '\ue612', + 'uicon-edit-pen-fill': '\ue66b', + 'uicon-email': '\ue611', + 'uicon-email-fill': '\ue642', + 'uicon-minus-circle': '\ue61b', + 'uicon-minus-circle-fill': '\ue652', + 'uicon-plus-circle': '\ue62e', + 'uicon-plus-circle-fill': '\ue661', + 'uicon-file-text': '\ue663', + 'uicon-file-text-fill': '\ue665', + 'uicon-pushpin': '\ue7e3', + 'uicon-pushpin-fill': '\ue86e', + 'uicon-grid': '\ue673', + 'uicon-grid-fill': '\ue678', + 'uicon-play-circle': '\ue647', + 'uicon-play-circle-fill': '\ue655', + 'uicon-pause-circle-fill': '\ue654', + 'uicon-pause': '\ue8fa', + 'uicon-pause-circle': '\ue643', + 'uicon-eye-off': '\ue648', + 'uicon-eye-off-outline': '\ue62b', + 'uicon-gift-fill': '\ue65c', + 'uicon-gift': '\ue65b', + 'uicon-rmb-circle-fill': '\ue657', + 'uicon-rmb-circle': '\ue677', + 'uicon-kefu-ermai': '\ue656', + 'uicon-server-fill': '\ue751', + 'uicon-coupon-fill': '\ue8c4', + 'uicon-coupon': '\ue8ae', + 'uicon-integral': '\ue704', + 'uicon-integral-fill': '\ue703', + 'uicon-home-fill': '\ue964', + 'uicon-home': '\ue965', + 'uicon-hourglass-half-fill': '\ue966', + 'uicon-hourglass': '\ue967', + 'uicon-account': '\ue628', + 'uicon-plus-people-fill': '\ue626', + 'uicon-minus-people-fill': '\ue615', + 'uicon-account-fill': '\ue614', + 'uicon-thumb-down-fill': '\ue726', + 'uicon-thumb-down': '\ue727', + 'uicon-thumb-up': '\ue733', + 'uicon-thumb-up-fill': '\ue72f', + 'uicon-lock-fill': '\ue979', + 'uicon-lock-open': '\ue973', + 'uicon-lock-opened-fill': '\ue974', + 'uicon-lock': '\ue97a', + 'uicon-red-packet-fill': '\ue690', + 'uicon-photo-fill': '\ue98b', + 'uicon-photo': '\ue98d', + 'uicon-volume-off-fill': '\ue659', + 'uicon-volume-off': '\ue644', + 'uicon-volume-fill': '\ue670', + 'uicon-volume': '\ue633', + 'uicon-red-packet': '\ue691', + 'uicon-download': '\ue63c', + 'uicon-arrow-up-fill': '\ue6b0', + 'uicon-arrow-down-fill': '\ue600', + 'uicon-play-left-fill': '\ue675', + 'uicon-play-right-fill': '\ue676', + 'uicon-rewind-left-fill': '\ue679', + 'uicon-rewind-right-fill': '\ue67a', + 'uicon-arrow-downward': '\ue604', + 'uicon-arrow-leftward': '\ue601', + 'uicon-arrow-rightward': '\ue603', + 'uicon-arrow-upward': '\ue607', + 'uicon-arrow-down': '\ue60d', + 'uicon-arrow-right': '\ue605', + 'uicon-arrow-left': '\ue60e', + 'uicon-arrow-up': '\ue606', + 'uicon-skip-back-left': '\ue674', + 'uicon-skip-forward-right': '\ue672', + 'uicon-rewind-right': '\ue66f', + 'uicon-rewind-left': '\ue671', + 'uicon-arrow-right-double': '\ue68d', + 'uicon-arrow-left-double': '\ue68c', + 'uicon-wifi-off': '\ue668', + 'uicon-wifi': '\ue667', + 'uicon-empty-data': '\ue62f', + 'uicon-empty-history': '\ue684', + 'uicon-empty-list': '\ue68b', + 'uicon-empty-page': '\ue627', + 'uicon-empty-order': '\ue639', + 'uicon-man': '\ue697', + 'uicon-woman': '\ue69c', + 'uicon-man-add': '\ue61c', + 'uicon-man-add-fill': '\ue64c', + 'uicon-man-delete': '\ue61a', + 'uicon-man-delete-fill': '\ue66a', + 'uicon-zh': '\ue70a', + 'uicon-en': '\ue692' +} diff --git a/uni_modules/uview-ui/components/u-icon/props.js b/uni_modules/uview-ui/components/u-icon/props.js new file mode 100644 index 0000000..71845b7 --- /dev/null +++ b/uni_modules/uview-ui/components/u-icon/props.js @@ -0,0 +1,89 @@ +export default { + props: { + // ������������ + name: { + type: String, + default: uni.$u.props.icon.name + }, + // ��������������������������������� + color: { + type: String, + default: uni.$u.props.icon.color + }, + // ���������������������px + size: { + type: [String, Number], + default: uni.$u.props.icon.size + }, + // ������������������ + bold: { + type: Boolean, + default: uni.$u.props.icon.bold + }, + // ������������������������������������������index������������������������������������ + index: { + type: [String, Number], + default: uni.$u.props.icon.index + }, + // ������������������������ + hoverClass: { + type: String, + default: uni.$u.props.icon.hoverClass + }, + // ������������������������������������������������������������ + customPrefix: { + type: String, + default: uni.$u.props.icon.customPrefix + }, + // ��������������������������������� + label: { + type: [String, Number], + default: uni.$u.props.icon.label + }, + // label������������������������������������ + labelPos: { + type: String, + default: uni.$u.props.icon.labelPos + }, + // label��������� + labelSize: { + type: [String, Number], + default: uni.$u.props.icon.labelSize + }, + // label��������� + labelColor: { + type: String, + default: uni.$u.props.icon.labelColor + }, + // label������������������ + space: { + type: [String, Number], + default: uni.$u.props.icon.space + }, + // ���������mode + imgMode: { + type: String, + default: uni.$u.props.icon.imgMode + }, + // ������������������������������������������������ + width: { + type: [String, Number], + default: uni.$u.props.icon.width + }, + // ������������������������������������������������ + height: { + type: [String, Number], + default: uni.$u.props.icon.height + }, + // ������������������������������������������������������������ + top: { + type: [String, Number], + default: uni.$u.props.icon.top + }, + // ������������������������ + stop: { + type: Boolean, + default: uni.$u.props.icon.stop + } + } +} diff --git a/uni_modules/uview-ui/components/u-icon/u-icon.vue b/uni_modules/uview-ui/components/u-icon/u-icon.vue new file mode 100644 index 0000000..9340328 --- /dev/null +++ b/uni_modules/uview-ui/components/u-icon/u-icon.vue @@ -0,0 +1,234 @@ +<template> + <view + class="u-icon" + @tap="clickHandler" + :class="['u-icon--' + labelPos]" + > + <image + class="u-icon__img" + v-if="isImg" + :src="name" + :mode="imgMode" + :style="[imgStyle, $u.addStyle(customStyle)]" + ></image> + <text + v-else + class="u-icon__icon" + :class="uClasses" + :style="[iconStyle, $u.addStyle(customStyle)]" + :hover-class="hoverClass" + >{{icon}}</text> + <!-- ������������������������������������������������v-if="label"������������������������0��������������������������������� --> + <text + v-if="label !== ''" + class="u-icon__label" + :style="{ + color: labelColor, + fontSize: $u.addUnit(labelSize), + marginLeft: labelPos == 'right' ? $u.addUnit(space) : 0, + marginTop: labelPos == 'bottom' ? $u.addUnit(space) : 0, + marginRight: labelPos == 'left' ? $u.addUnit(space) : 0, + marginBottom: labelPos == 'top' ? $u.addUnit(space) : 0, + }" + >{{ label }}</text> + </view> +</template> + +<script> + // #ifdef APP-NVUE + // nvue������weex���dom������������������������������������������������ + // https://weex.apache.org/zh/docs/modules/dom.html#addrule + const fontUrl = 'https://at.alicdn.com/t/font_2225171_8kdcwk4po24.ttf' + const domModule = weex.requireModule('dom') + domModule.addRule('fontFace', { + 'fontFamily': "uicon-iconfont", + 'src': `url('${fontUrl}')` + }) + // #endif + + // ������������������������������������unicode + import icons from './icons' + + import props from './props.js';; + + /** + * icon ������ + * @description ��������������������������������������������������������������������� + * @tutorial https://www.uviewui.com/components/icon.html + * @property {String} name ��������������������������������� + * @property {String} color ������������,������������������ ��������� color['u-content-color'] ��� + * @property {String | Number} size ���������������������������px ��������� '16px' ��� + * @property {Boolean} bold ������������������ ��������� false ��� + * @property {String | Number} index ������������������������������������������index������������������������������������ + * @property {String} hoverClass ���������������������������������������uni���view���������hoverClass������������������������ + * @property {String} customPrefix ������������������������������������������������������������ ��������� 'uicon' ��� + * @property {String | Number} label ���������������label������ + * @property {String} labelPos label���������������������������������right���bottom ��������� 'right' ��� + * @property {String | Number} labelSize label���������������������px ��������� '15px' ��� + * @property {String} labelColor ���������������label������������ ��� ������ color['u-content-color'] ��� + * @property {String | Number} space label���������������������������px ��������� '3px' ��� + * @property {String} imgMode ���������mode + * @property {String | Number} width ��������������������������������� + * @property {String | Number} height ��������������������������������� + * @property {String | Number} top ��������������������������������� ������������������������������������������������������������ ��������� 0 ��� + * @property {Boolean} stop ������������������������ ��������� false ��� + * @property {Object} customStyle icon������������������������ + * @event {Function} click ��������������������� + * @event {Function} touchstart ��������������������� + * @example <u-icon name="photo" color="#2979ff" size="28"></u-icon> + */ + export default { + name: 'u-icon', + data() { + return { + + } + }, + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + computed: { + uClasses() { + let classes = [] + classes.push(this.customPrefix + '-' + this.name) + // // uView���������������������������u-iconfont + // if (this.customPrefix == 'uicon') { + // classes.push('u-iconfont') + // } else { + // classes.push(this.customPrefix) + // } + // ��������������������������� + if (this.color && uni.$u.config.type.includes(this.color)) classes.push('u-icon__icon--' + this.color) + // ���������������������������������������������������������������������������������[a, b, c]������������������������������ + // ��������������������������������������������������������������������������� + //#ifdef MP-ALIPAY || MP-TOUTIAO || MP-BAIDU + classes = classes.join(' ') + //#endif + return classes + }, + iconStyle() { + let style = {} + style = { + fontSize: uni.$u.addUnit(this.size), + lineHeight: uni.$u.addUnit(this.size), + fontWeight: this.bold ? 'bold' : 'normal', + // ������������������������������������������������������������������������������������ + top: uni.$u.addUnit(this.top) + } + // ��������������������������������������� + if (this.color && !uni.$u.config.type.includes(this.color)) style.color = this.color + + return style + }, + // ���������������name������������������������������������������"/"������������������������ + isImg() { + return this.name.indexOf('/') !== -1 + }, + imgStyle() { + let style = {} + // ������������width���height���������������������������������������size������ + style.width = this.width ? uni.$u.addUnit(this.width) : uni.$u.addUnit(this.size) + style.height = this.height ? uni.$u.addUnit(this.height) : uni.$u.addUnit(this.size) + return style + }, + // ��������������������������������������� + icon() { + // ������������������������������������������������������������������name������������������������������������unicode������ + return icons['uicon-' + this.name] || this.name + } + }, + methods: { + clickHandler(e) { + this.$emit('click', this.index) + // ������������������������ + this.stop && this.preventEvent(e) + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + // ������������ + $u-icon-primary: $u-primary !default; + $u-icon-success: $u-success !default; + $u-icon-info: $u-info !default; + $u-icon-warning: $u-warning !default; + $u-icon-error: $u-error !default; + $u-icon-label-line-height:1 !default; + + /* #ifndef APP-NVUE */ + // ���nvue��������������� + @font-face { + font-family: 'uicon-iconfont'; + src: url('https://at.alicdn.com/t/font_2225171_8kdcwk4po24.ttf') format('truetype'); + } + + /* #endif */ + + .u-icon { + /* #ifndef APP-NVUE */ + display: flex; + /* #endif */ + align-items: center; + + &--left { + flex-direction: row-reverse; + align-items: center; + } + + &--right { + flex-direction: row; + align-items: center; + } + + &--top { + flex-direction: column-reverse; + justify-content: center; + } + + &--bottom { + flex-direction: column; + justify-content: center; + } + + &__icon { + font-family: uicon-iconfont; + position: relative; + @include flex; + align-items: center; + + &--primary { + color: $u-icon-primary; + } + + &--success { + color: $u-icon-success; + } + + &--error { + color: $u-icon-error; + } + + &--warning { + color: $u-icon-warning; + } + + &--info { + color: $u-icon-info; + } + } + + &__img { + /* #ifndef APP-NVUE */ + height: auto; + will-change: transform; + /* #endif */ + } + + &__label { + /* #ifndef APP-NVUE */ + line-height: $u-icon-label-line-height; + /* #endif */ + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-image/props.js b/uni_modules/uview-ui/components/u-image/props.js new file mode 100644 index 0000000..2eabb74 --- /dev/null +++ b/uni_modules/uview-ui/components/u-image/props.js @@ -0,0 +1,84 @@ +export default { + props: { + // ������������ + src: { + type: String, + default: uni.$u.props.image.src + }, + // ������������ + mode: { + type: String, + default: uni.$u.props.image.mode + }, + // ��������������������� + width: { + type: [String, Number], + default: uni.$u.props.image.width + }, + // ��������������������� + height: { + type: [String, Number], + default: uni.$u.props.image.height + }, + // ���������������circle-���������square-������ + shape: { + type: String, + default: uni.$u.props.image.shape + }, + // ��������������������� + radius: { + type: [String, Number], + default: uni.$u.props.image.radius + }, + // ������������������������������������App������������������������������������������ + lazyLoad: { + type: Boolean, + default: uni.$u.props.image.lazyLoad + }, + // ������������������������������������������������������ + showMenuByLongpress: { + type: Boolean, + default: uni.$u.props.image.showMenuByLongpress + }, + // ������������������������������������ + loadingIcon: { + type: String, + default: uni.$u.props.image.loadingIcon + }, + // ��������������������������������������� + errorIcon: { + type: String, + default: uni.$u.props.image.errorIcon + }, + // ������������������������������������������������slot + showLoading: { + type: Boolean, + default: uni.$u.props.image.showLoading + }, + // ���������������������������������������������������slot + showError: { + type: Boolean, + default: uni.$u.props.image.showError + }, + // ������������������������ + fade: { + type: Boolean, + default: uni.$u.props.image.fade + }, + // ��������������������������������������������������� + webp: { + type: Boolean, + default: uni.$u.props.image.webp + }, + // ���������������������ms + duration: { + type: [String, Number], + default: uni.$u.props.image.duration + }, + // ��������������������������������������������������������������������������� + bgColor: { + type: String, + default: uni.$u.props.image.bgColor + } + } +} diff --git a/uni_modules/uview-ui/components/u-image/u-image.vue b/uni_modules/uview-ui/components/u-image/u-image.vue new file mode 100644 index 0000000..473e35b --- /dev/null +++ b/uni_modules/uview-ui/components/u-image/u-image.vue @@ -0,0 +1,232 @@ +<template> + <u-transition + mode="fade" + :show="show" + :duration="fade ? 1000 : 0" + > + <view + class="u-image" + @tap="onClick" + :style="[wrapStyle, backgroundStyle]" + > + <image + v-if="!isError" + :src="src" + :mode="mode" + @error="onErrorHandler" + @load="onLoadHandler" + :show-menu-by-longpress="showMenuByLongpress" + :lazy-load="lazyLoad" + class="u-image__image" + :style="{ + borderRadius: shape == 'circle' ? '10000px' : $u.addUnit(radius), + width: $u.addUnit(width), + height: $u.addUnit(height) + }" + ></image> + <view + v-if="showLoading && loading" + class="u-image__loading" + :style="{ + borderRadius: shape == 'circle' ? '50%' : $u.addUnit(radius), + backgroundColor: this.bgColor, + width: $u.addUnit(width), + height: $u.addUnit(height) + }" + > + <slot name="loading"> + <u-icon + :name="loadingIcon" + :width="width" + :height="height" + ></u-icon> + </slot> + </view> + <view + v-if="showError && isError && !loading" + class="u-image__error" + :style="{ + borderRadius: shape == 'circle' ? '50%' : $u.addUnit(radius), + width: $u.addUnit(width), + height: $u.addUnit(height) + }" + > + <slot name="error"> + <u-icon + :name="errorIcon" + :width="width" + :height="height" + ></u-icon> + </slot> + </view> + </view> + </u-transition> +</template> + +<script> + import props from './props.js'; + /** + * Image ������ + * @description ������������uni-app���image������������������������������������������������������������������������������������������������������������������������������������ + * @tutorial https://uviewui.com/components/image.html + * @property {String} src ������������ + * @property {String} mode ������������������������������ ��������� 'aspectFill' ��� + * @property {String | Number} width ������������������������������������������������px������ ��������� '300' ��� + * @property {String | Number} height ������������������������������������������������px������ ��������� '225' ��� + * @property {String} shape ���������������circle-���������square-������ ��������� 'square' ��� + * @property {String | Number} radius ���������������������������������������������������px������ ��������� 0 ��� + * @property {Boolean} lazyLoad ���������������������������������������App������������������������������������������������ ��������� true ��� + * @property {Boolean} showMenuByLongpress ��������������������������������������������������������������������������������� ��������� true ��� + * @property {String} loadingIcon ������������������������������������ ��������� 'photo' ��� + * @property {String} errorIcon ��������������������������������������� ��������� 'error-circle' ��� + * @property {Boolean} showLoading ������������������������������������������������slot ��������� true ��� + * @property {Boolean} showError ���������������������������������������������������slot ��������� true ��� + * @property {Boolean} fade ������������������������ ��������� true ��� + * @property {Boolean} webp ��������������������������������������������������� ��������� false ��� + * @property {String | Number} duration ������fade������������������������������ms ��������� 500 ��� + * @property {String} bgColor ��������������������������������������������������������������������������� (������ '#f3f4f6' ) + * @property {Object} customStyle ��������������������������������� + * @event {Function} click ��������������������� + * @event {Function} error ��������������������������� + * @event {Function} load ��������������������������� + * @example <u-image width="100%" height="300px" :src="src"></u-image> + */ + export default { + name: 'u-image', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + // ��������������������������������������������������������������� + isError: false, + // ��������������������������������������������� + loading: true, + // ������������������������������������������������ + opacity: 1, + // ���������������������props��������������������������������������������� + durationTime: this.duration, + // ������������������������������������������������������������png������������������������������������ + backgroundStyle: {}, + // ������fade��������������������������������� + show: false + }; + }, + watch: { + src: { + immediate: true, + handler(n) { + if (!n) { + // ������������null������''���������false���������undefined������������������������ + this.isError = true + + } else { + this.isError = false; + this.loading = true; + } + } + } + }, + computed: { + wrapStyle() { + let style = {}; + // ������������addUnit()������������������������������������������px���������������������������������������������������������������rpx������ + style.width = this.$u.addUnit(this.width); + style.height = this.$u.addUnit(this.height); + // ������������������������������������������������������������ + style.borderRadius = this.shape == 'circle' ? '10000px' : uni.$u.addUnit(this.radius) + // ���������������������������������hidden��������������������������� + style.overflow = this.borderRadius > 0 ? 'hidden' : 'visible' + // if (this.fade) { + // style.opacity = this.opacity + // // nvue��������������������������������������� + // style.transitionDuration = `${this.durationTime}ms` + // style.transitionTimingFunction = 'ease-in-out' + // style.transitionProperty = 'opacity' + // } + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)); + + } + }, + mounted() { + this.show = true + }, + methods: { + // ������������ + onClick() { + this.$emit('click') + }, + // ������������������ + onErrorHandler(err) { + this.loading = false + this.isError = true + this.$emit('error', err) + }, + // ���������������������������loading������ + onLoadHandler(event) { + this.loading = false + this.isError = false + this.$emit('load', event) + this.removeBgColor() + // ��������������������������������������������������������������������������������������������� + // ������������fade������������png��������������������������������������� + // if (!this.fade) return this.removeBgColor(); + // // ������opacity���1(������������������������������������)���������0(���������������������������������������������������������������������)������������1������������������������������ + // this.opacity = 0; + // // ���������������0���������������������������������������������������������������0������������������������������������������duration������������������������������(������) + // // ������������������������������������������ + // this.durationTime = 0; + // // ������50ms���������������������H5��������������������� + // setTimeout(() => { + // this.durationTime = this.duration; + // this.opacity = 1; + // setTimeout(() => { + // this.removeBgColor(); + // }, this.durationTime); + // }, 50); + }, + // ������������������������ + removeBgColor() { + // ������������������������������������������������������������������png������������������������������ + this.backgroundStyle = { + backgroundColor: 'transparent' + }; + } + } + }; +</script> + +<style lang="scss" scoped> + @import '../../libs/css/components.scss'; + + $u-image-error-top:0px !default; + $u-image-error-left:0px !default; + $u-image-error-width:100% !default; + $u-image-error-hight:100% !default; + $u-image-error-background-color:$u-bg-color !default; + $u-image-error-color:$u-tips-color !default; + $u-image-error-font-size: 46rpx !default; + + .u-image { + position: relative; + transition: opacity 0.5s ease-in-out; + + &__image { + width: 100%; + height: 100%; + } + + &__loading, + &__error { + position: absolute; + top: $u-image-error-top; + left: $u-image-error-left; + width: $u-image-error-width; + height: $u-image-error-hight; + @include flex; + align-items: center; + justify-content: center; + background-color: $u-image-error-background-color; + color: $u-image-error-color; + font-size: $u-image-error-font-size; + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-index-anchor/props.js b/uni_modules/uview-ui/components/u-index-anchor/props.js new file mode 100644 index 0000000..6d8b59a --- /dev/null +++ b/uni_modules/uview-ui/components/u-index-anchor/props.js @@ -0,0 +1,29 @@ +export default { + props: { + // ������������������������ + text: { + type: [String, Number], + default: uni.$u.props.indexAnchor.text + }, + // ������������������������ + color: { + type: String, + default: uni.$u.props.indexAnchor.color + }, + // ���������������������������������������px + size: { + type: [String, Number], + default: uni.$u.props.indexAnchor.size + }, + // ������������������������ + bgColor: { + type: String, + default: uni.$u.props.indexAnchor.bgColor + }, + // ���������������������������������px + height: { + type: [String, Number], + default: uni.$u.props.indexAnchor.height + } + } +} diff --git a/uni_modules/uview-ui/components/u-index-anchor/u-index-anchor.vue b/uni_modules/uview-ui/components/u-index-anchor/u-index-anchor.vue new file mode 100644 index 0000000..b95ddef --- /dev/null +++ b/uni_modules/uview-ui/components/u-index-anchor/u-index-anchor.vue @@ -0,0 +1,91 @@ +<template> + <!-- #ifdef APP-NVUE --> + <header> + <!-- #endif --> + <view + class="u-index-anchor u-border-bottom" + :ref="`u-index-anchor-${text}`" + :style="{ + height: $u.addUnit(height), + backgroundColor: bgColor + }" + > + <text + class="u-index-anchor__text" + :style="{ + fontSize: $u.addUnit(size), + color: color + }" + >{{ text }}</text> + </view> + <!-- #ifdef APP-NVUE --> + </header> + <!-- #endif --> +</template> + +<script> + import props from './props.js'; + // #ifdef APP-NVUE + const dom = uni.requireNativePlugin('dom') + // #endif + /** + * IndexAnchor ������������ + * @description + * @tutorial https://uviewui.com/components/indexList.html + * @property {String | Number} text ������������������������ + * @property {String} color ������������������������ ( ������ '#606266' ) + * @property {String | Number} size ���������������������������������������px ( ������ 14 ) + * @property {String} bgColor ������������������������ ( ������ '#dedede' ) + * @property {String | Number} height ���������������������������������px ( ������ 32 ) + * @example <u-index-anchor :text="indexList[index]"></u-index-anchor> + */ + export default { + name: 'u-index-anchor', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + } + }, + mounted() { + this.init() + }, + methods: { + init() { + // ������������������������������������������������������parent������ + const indexList = uni.$u.$parent.call(this, 'u-index-list') + if (!indexList) { + return uni.$u.error('u-index-anchor���������������u-index-list������������') + } + // ������������������������u-index-list��� + indexList.anchors.push(this) + const indexListItem = uni.$u.$parent.call(this, 'u-index-item') + // #ifndef APP-NVUE + // ������������nvue������u-index-anchor���������������u-index-item������ + if (!indexListItem) { + return uni.$u.error('u-index-anchor���������������u-index-item������������') + } + // ������u-index-item���id���anchor���text���������������������nvue���������������������������scroll-view������������������������ + indexListItem.id = this.text.charCodeAt(0) + // #endif + } + }, + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-index-anchor { + position: sticky; + top: 0; + @include flex; + align-items: center; + padding-left: 15px; + z-index: 1; + + &__text { + @include flex; + align-items: center; + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-index-item/props.js b/uni_modules/uview-ui/components/u-index-item/props.js new file mode 100644 index 0000000..7c11331 --- /dev/null +++ b/uni_modules/uview-ui/components/u-index-item/props.js @@ -0,0 +1,5 @@ +export default { + props: { + + } +} diff --git a/uni_modules/uview-ui/components/u-index-item/u-index-item.vue b/uni_modules/uview-ui/components/u-index-item/u-index-item.vue new file mode 100644 index 0000000..0bc7fb3 --- /dev/null +++ b/uni_modules/uview-ui/components/u-index-item/u-index-item.vue @@ -0,0 +1,87 @@ +<template> + <!-- #ifdef APP-NVUE --> + <cell ref="u-index-item"> + <!-- #endif --> + <view + class="u-index-item" + :id="`u-index-item-${id}`" + :class="[`u-index-item-${id}`]" + > + <slot /> + </view> + <!-- #ifdef APP-NVUE --> + </cell> + <!-- #endif --> +</template> + +<script> + import props from './props.js'; + // #ifdef APP-NVUE + // ������weex������������KPI���������������������������������������������������������������������������dom��������������������� + const dom = uni.requireNativePlugin('dom') + // #endif + /** + * IndexItem + * @description + * @tutorial https://uviewui.com/components/indexList.html + * @property {String} + * @event {Function} + * @example + */ + export default { + name: 'u-index-item', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + // ������������������������������������ + top: 0, + height: 0, + id: '' + } + }, + created() { + // ���������u-index-anchor��������� + this.anchor = {} + }, + mounted() { + this.init() + }, + methods: { + init() { + // ������������������������������������������������������parent������ + this.getParentData('u-index-list') + if (!this.parent) { + return uni.$u.error('u-index-item���������������u-index-list������������') + } + uni.$u.sleep().then(() =>{ + this.getIndexItemRect().then(size => { + // ������������������������������������������������������������������children���������������������top������������������������������������ + this.top = Math.ceil(size.top) + this.height = Math.ceil(size.height) + }) + }) + }, + getIndexItemRect() { + return new Promise(resolve => { + // #ifndef APP-NVUE + this.$uGetRect('.u-index-item').then(size => { + resolve(size) + }) + // #endif + + // #ifdef APP-NVUE + const ref = this.$refs['u-index-item'] + dom.getComponentRect(ref, res => { + resolve(res.size) + }) + // #endif + }) + } + }, + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + +</style> diff --git a/uni_modules/uview-ui/components/u-index-list/props.js b/uni_modules/uview-ui/components/u-index-list/props.js new file mode 100644 index 0000000..354d459 --- /dev/null +++ b/uni_modules/uview-ui/components/u-index-list/props.js @@ -0,0 +1,29 @@ +export default { + props: { + // ������������������������������ + inactiveColor: { + type: String, + default: uni.$u.props.indexList.inactiveColor + }, + // ��������������������������� + activeColor: { + type: String, + default: uni.$u.props.indexList.activeColor + }, + // ��������������������������������� + indexList: { + type: Array, + default: uni.$u.props.indexList.indexList + }, + // ������������������������������ + sticky: { + type: Boolean, + default: uni.$u.props.indexList.sticky + }, + // ��������������������������� + customNavHeight: { + type: [String, Number], + default: uni.$u.props.indexList.customNavHeight + } + } +} diff --git a/uni_modules/uview-ui/components/u-index-list/u-index-list.vue b/uni_modules/uview-ui/components/u-index-list/u-index-list.vue new file mode 100644 index 0000000..d712618 --- /dev/null +++ b/uni_modules/uview-ui/components/u-index-list/u-index-list.vue @@ -0,0 +1,440 @@ +<template> + <view class="u-index-list"> + <!-- #ifdef APP-NVUE --> + <list + :scrollTop="scrollTop" + enable-back-to-top + :offset-accuracy="1" + :style="{ + maxHeight: $u.addUnit(scrollViewHeight) + }" + @scroll="scrollHandler" + ref="uList" + > + <cell + v-if="$slots.header" + ref="header" + > + <slot name="header" /> + </cell> + <slot /> + <cell v-if="$slots.footer"> + <slot name="footer" /> + </cell> + </list> + <!-- #endif --> + <!-- #ifndef APP-NVUE --> + <scroll-view + :scrollTop="scrollTop" + :scrollIntoView="scrollIntoView" + :offset-accuracy="1" + :style="{ + maxHeight: $u.addUnit(scrollViewHeight) + }" + scroll-y + @scroll="scrollHandler" + ref="uList" + > + <view v-if="$slots.header"> + <slot name="header" /> + </view> + <slot /> + <view v-if="$slots.footer"> + <slot name="footer" /> + </view> + </scroll-view> + <!-- #endif --> + <view + class="u-index-list__letter" + ref="u-index-list__letter" + :style="{ top: $u.addUnit(letterInfo.top || 100) }" + @touchstart="touchStart" + @touchmove.stop.prevent="touchMove" + @touchend.stop.prevent="touchEnd" + @touchcancel.stop.prevent="touchEnd" + > + <view + class="u-index-list__letter__item" + v-for="(item, index) in uIndexList" + :key="index" + :style="{ + backgroundColor: activeIndex === index ? activeColor : 'transparent' + }" + > + <text + class="u-index-list__letter__item__index" + :style="{color: activeIndex === index ? '#fff' : inactiveColor}" + >{{ item }}</text> + </view> + </view> + <u-transition + mode="fade" + :show="touching" + :customStyle="{ + position: 'fixed', + right: '50px', + top: $u.addUnit(indicatorTop), + zIndex: 2 + }" + > + <view + class="u-index-list__indicator" + :class="['u-index-list__indicator--show']" + :style="{ + height: $u.addUnit(indicatorHeight), + width: $u.addUnit(indicatorHeight) + }" + > + <text class="u-index-list__indicator__text">{{ uIndexList[activeIndex] }}</text> + </view> + </u-transition> + </view> +</template> + +<script> + const indexList = () => { + const indexList = []; + const charCodeOfA = 'A'.charCodeAt(0); + for (let i = 0; i < 26; i++) { + indexList.push(String.fromCharCode(charCodeOfA + i)); + } + return indexList; + } + import props from './props.js'; + // #ifdef APP-NVUE + // ������weex������������KPI���������������������������������������������������������������������������dom��������������������� + const dom = uni.requireNativePlugin('dom') + // #endif + /** + * IndexList ������������ + * @description ������������������������������������ + * @tutorial https://uviewui.com/components/indexList.html + * @property {String} inactiveColor ������������������������������ ( ������ '#606266' ) + * @property {String} activeColor ��������������������������� ( ������ '#5677fc' ) + * @property {Array} indexList ��������������������������������� + * @property {Boolean} sticky ������������������������������ ( ������ true ) + * @property {String | Number} customNavHeight ��������������������������� ( ������ 0 ) + * */ + export default { + name: 'u-index-list', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + // #ifdef MP-WEIXIN + // ���������������������������������������������������Vue������������������������������������flex������ + options: { + virtualHost: true + }, + // #endif + data() { + return { + // ������������������������������������ + activeIndex: -1, + touchmoveIndex: 1, + // ��������������������� + letterInfo: { + height: 0, + itemHeight: 0, + top: 0 + }, + // ������������������������������������������������������������������������������������������������������������������������������������ + indicatorHeight: 50, + // ������������������������top��������������������������������������������� + // indicatorTop: 0 + // ��������������������������������� + touching: false, + // ���������������top��� + scrollTop: 0, + // scroll-view��������� + scrollViewHeight: 0, + // ������������ + sys: uni.$u.sys(), + scrolling: false, + scrollIntoView: '', + } + }, + computed: { + // ������������������������indexList������������������������������������������������A-Z������ + uIndexList() { + return this.indexList.length ? this.indexList : indexList() + }, + // ������������������������top��������������������������������������������� + indicatorTop() { + const { + top, + itemHeight + } = this.letterInfo + return Math.floor(top + itemHeight * this.activeIndex + itemHeight / 2 - this.indicatorHeight / 2) + } + }, + watch: { + // ������������������������������������������������ + uIndexList: { + immediate: true, + handler() { + uni.$u.sleep().then(() => { + this.setIndexListLetterInfo() + }) + } + } + }, + created() { + this.children = [] + this.anchors = [] + this.init() + }, + mounted() { + this.setIndexListLetterInfo() + }, + methods: { + init() { + // ��������������������������������������������� + //������this.customNavHeight���������this.scrollViewHeight���������maxHeight + //���������u-index-list������������tabbar���������,scroll-view������������������������������ + this.scrollViewHeight = this.sys.windowHeight - this.customNavHeight + }, + // ��������������������� + touchStart(e) { + // ��������������������� + const touchStart = e.changedTouches[0] + if (!touchStart) return + this.touching = true + const { + pageY + } = touchStart + // ������������������������������������������������������������������������ + const currentIndex = this.getIndexListLetter(pageY) + this.setValueForTouch(currentIndex) + }, + // ������������������������������������ + touchMove(e) { + // ��������������������� + let touchMove = e.changedTouches[0] + if (!touchMove) return; + + // ������������������������������������������������ touching ��� false ��������������� indicator ������ + if (!this.touching) { + this.touching = true + } + const { + pageY + } = touchMove + const currentIndex = this.getIndexListLetter(pageY) + this.setValueForTouch(currentIndex) + }, + // ������������ + touchEnd(e) { + // ���������������������������������������������������������������������������������������������������������������u-transition���show��������������� + uni.$u.sleep(300).then(() => { + this.touching = false + }) + }, + // ������������������������������������������������������������ + getIndexListLetterRect() { + return new Promise(resolve => { + // ������������������������������dom������ + // #ifndef APP-NVUE + this.$uGetRect('.u-index-list__letter').then(size => { + resolve(size) + }) + // #endif + + // #ifdef APP-NVUE + const ref = this.$refs['u-index-list__letter'] + dom.getComponentRect(ref, res => { + resolve(res.size) + }) + // #endif + }) + }, + // ������indexList��������������������� + setIndexListLetterInfo() { + this.getIndexListLetterRect().then(size => { + const { + height + } = size + const sys = uni.$u.sys() + const windowHeight = sys.windowHeight + let customNavHeight = 0 + // ��������������������������������������������������������������������������������������������������� + if (this.customNavHeight == 0) { + // #ifdef H5 + customNavHeight = sys.windowTop + // #endif + // #ifndef H5 + // ������H5���������������������������������������������windowHeight��������������������������������������������������������������������������� + customNavHeight = -(sys.statusBarHeight + 44) + // #endif + } else { + customNavHeight = uni.$u.getPx(this.customNavHeight) + } + this.letterInfo = { + height, + // ������������������������������������������������������������������������������������������������������������������������ + top: (windowHeight - height) / 2 + customNavHeight / 2, + itemHeight: Math.floor(height / this.uIndexList.length) + } + }) + }, + // ������������������������������������ + getIndexListLetter(pageY) { + const { + top, + height, + itemHeight + } = this.letterInfo + // ���H5���pageY���������������������������uni-app���������������H5���������������������������H5��������������������������������� + // #ifdef H5 + pageY += uni.$u.sys().windowTop + // #endif + // ��������������������������������������������������������������������������������������������������������������������������������� + if (pageY < top) { + return 0 + } else if (pageY >= top + height) { + // ��������������������������������������� + return this.uIndexList.length - 1 + } else { + // ���������������Y������������������������������������top������������������������������������������������������������������������������������ + return Math.floor((pageY - top) / itemHeight); + } + }, + // ������������������������������������������ + setValueForTouch(currentIndex) { + // ������������������������������������������������������������������������������������������������ + if (currentIndex === this.activeIndex) return + this.activeIndex = currentIndex + // #ifndef APP-NVUE || MP-WEIXIN + // ������nvue������������anchor���item������u-index-item���������������������index-item������������ + this.scrollIntoView = `u-index-item-${this.uIndexList[currentIndex].charCodeAt(0)}` + // #endif + // #ifdef MP-WEIXIN + // ���������������������scroll-view���scroll-into-view���������������slot���������������id���������������������������scrollTop��������������������������� + this.scrollTop = this.children[currentIndex].top + // #endif + // #ifdef APP-NVUE + // ���nvue������������cell���header������������������������������������������header(anchor)������������ + const anchor = `u-index-anchor-${this.uIndexList[currentIndex]}` + dom.scrollToElement(this.anchors[currentIndex].$refs[anchor], { + offset: 0, + animated: false + }) + // #endif + }, + getHeaderRect() { + // ������header slot������������������list���������������������������������������top������ + return new Promise(resolve => { + dom.getComponentRect(this.$refs.header, res => { + resolve(res.size) + }) + }) + }, + // scroll-view��������������� + async scrollHandler(e) { + if (this.touching || this.scrolling) return + // ������������������������������������������������������������������������������ + this.scrolling = true + uni.$u.sleep(10).then(() => { + this.scrolling = false + }) + let scrollTop = 0 + const len = this.children.length + let children = this.children + const anchors = this.anchors + // #ifdef APP-NVUE + // nvue��������������������������������������������������������� + scrollTop = Math.abs(e.contentOffset.y) + // ������header slot��������������� + const header = await this.getHeaderRect() + // item���top���������nvue������������������anchor���top������������nvue������index-item���top + let top = header.height + // ������list������������������cell���top������������������header slot���������item���������height���������������������nvue������������������ + children = this.children.map((item, index) => { + const child = { + height: item.height, + top + } + // ���������������������������item������������������ + top += item.height + anchors[index].height + return child + }) + // #endif + // #ifndef APP-NVUE + // ���nvue������detail��������������������� + scrollTop = e.detail.scrollTop + // #endif + for (let i = 0; i < len; i++) { + const item = children[i], + nextItem = children[i + 1] + // ������������������������������������item���top��������������������������������������������� + if (scrollTop <= children[0].top || scrollTop >= children[len - 1].top + children[len - + 1].height) { + this.activeIndex = -1 + break + } else if (!nextItem) { + // ���������������������item��������������������������������������� + this.activeIndex = len - 1 + break + } else if (scrollTop > item.top && scrollTop < nextItem.top) { + this.activeIndex = i + break + } + } + }, + }, + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-index-list { + + &__letter { + position: fixed; + right: 0; + text-align: center; + z-index: 3; + padding: 0 6px; + + &__item { + width: 16px; + height: 16px; + border-radius: 100px; + margin: 1px 0; + @include flex; + align-items: center; + justify-content: center; + + &--active { + background-color: $u-primary; + } + + &__index { + font-size: 12px; + text-align: center; + line-height: 12px; + } + } + } + + &__indicator { + width: 50px; + height: 50px; + border-radius: 100px 100px 0 100px; + text-align: center; + color: #ffffff; + background-color: #c9c9c9; + transform: rotate(-45deg); + @include flex; + justify-content: center; + align-items: center; + + &__text { + font-size: 28px; + line-height: 28px; + font-weight: bold; + color: #fff; + transform: rotate(45deg); + text-align: center; + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-input/props.js b/uni_modules/uview-ui/components/u-input/props.js new file mode 100644 index 0000000..2c50870 --- /dev/null +++ b/uni_modules/uview-ui/components/u-input/props.js @@ -0,0 +1,187 @@ +export default { + props: { + // ������������ + value: { + type: [String, Number], + default: uni.$u.props.input.value + }, + // ��������������� + // number-���������������������app-vue���������������������������app-nvue��������������������������������������� + // idcard-������������������������������������������������������QQ��������� + // digit-������������������������������App���nvue������������������������������������������������QQ��������� + // text-������������������ + type: { + type: String, + default: uni.$u.props.input.type + }, + // ������ textarea ������������ position:fixed ������������������������������������ fixed ��� true��� + // ������������������������������������������������������������������������QQ��������� + fixed: { + type: Boolean, + default: uni.$u.props.input.fixed + }, + // ��������������������� + disabled: { + type: Boolean, + default: uni.$u.props.input.disabled + }, + // ��������������������������� + disabledColor: { + type: String, + default: uni.$u.props.input.disabledColor + }, + // ������������������������ + clearable: { + type: Boolean, + default: uni.$u.props.input.clearable + }, + // ������������������ + password: { + type: Boolean, + default: uni.$u.props.input.password + }, + // ������������������������������ -1 ������������������������������ + maxlength: { + type: [String, Number], + default: uni.$u.props.input.maxlength + }, + // ������������������������������ + placeholder: { + type: String, + default: uni.$u.props.input.placeholder + }, + // ������placeholder���������������������������������������style���������scoped���������������������������/deep/ + placeholderClass: { + type: String, + default: uni.$u.props.input.placeholderClass + }, + // ������placeholder��������� + placeholderStyle: { + type: [String, Object], + default: uni.$u.props.input.placeholderStyle + }, + // ��������������������������������������� type ="text"���type ="textarea"��������� + showWordLimit: { + type: Boolean, + default: uni.$u.props.input.showWordLimit + }, + // ���������������������������������������������send|search|next|go|done������������������uni-app������ + // https://uniapp.dcloud.io/component/input + // https://uniapp.dcloud.io/component/textarea + confirmType: { + type: String, + default: uni.$u.props.input.confirmType + }, + // ������������������������������������������������������������H5������ + confirmHold: { + type: Boolean, + default: uni.$u.props.input.confirmHold + }, + // focus������������������������������������������������������������������ + holdKeyboard: { + type: Boolean, + default: uni.$u.props.input.holdKeyboard + }, + // ������������������ + // ��� H5 ������������������������������������������������������������������������������������������������nvue ������������������������������������ focus()���blur() ������������������ + focus: { + type: Boolean, + default: uni.$u.props.input.focus + }, + // ������������������������������������������������������App3.0.0+������ + autoBlur: { + type: Boolean, + default: uni.$u.props.input.autoBlur + }, + // ������������ iOS ������������������������������������������������type=textarea��������� + disableDefaultPadding: { + type: Boolean, + default: uni.$u.props.input.disableDefaultPadding + }, + // ������focus������������������ + cursor: { + type: [String, Number], + default: uni.$u.props.input.cursor + }, + // ������������������������������������������ + cursorSpacing: { + type: [String, Number], + default: uni.$u.props.input.cursorSpacing + }, + // ���������������������������������������������������selection-end������������ + selectionStart: { + type: [String, Number], + default: uni.$u.props.input.selectionStart + }, + // ���������������������������������������������������selection-start������������ + selectionEnd: { + type: [String, Number], + default: uni.$u.props.input.selectionEnd + }, + // ������������������������������������������ + adjustPosition: { + type: Boolean, + default: uni.$u.props.input.adjustPosition + }, + // ���������������������������������������������left|center|right + inputAlign: { + type: String, + default: uni.$u.props.input.inputAlign + }, + // ������������������������ + fontSize: { + type: [String, Number], + default: uni.$u.props.input.fontSize + }, + // ��������������������� + color: { + type: String, + default: uni.$u.props.input.color + }, + // ��������������������� + prefixIcon: { + type: String, + default: uni.$u.props.input.prefixIcon + }, + // ��������������������������������������� + prefixIconStyle: { + type: [String, Object], + default: uni.$u.props.input.prefixIconStyle + }, + // ��������������������� + suffixIcon: { + type: String, + default: uni.$u.props.input.suffixIcon + }, + // ��������������������������������������� + suffixIconStyle: { + type: [String, Object], + default: uni.$u.props.input.suffixIconStyle + }, + // ���������������surround-���������������bottom-���������������none-��������� + border: { + type: String, + default: uni.$u.props.input.border + }, + // ������������������disabled������������������disabled���������������������readonly��������� + readonly: { + type: Boolean, + default: uni.$u.props.input.readonly + }, + // ������������������circle-���������square-������ + shape: { + type: String, + default: uni.$u.props.input.shape + }, + // ������������������������������������������������ + formatter: { + type: [Function, null], + default: uni.$u.props.input.formatter + }, + // ��������������������������������������������������������� + ignoreCompositionEvent: { + type: Boolean, + default: true + } + } +} diff --git a/uni_modules/uview-ui/components/u-input/u-input.vue b/uni_modules/uview-ui/components/u-input/u-input.vue new file mode 100644 index 0000000..30073eb --- /dev/null +++ b/uni_modules/uview-ui/components/u-input/u-input.vue @@ -0,0 +1,354 @@ +<template> + <view class="u-input" :class="inputClass" :style="[wrapperStyle]"> + <view class="u-input__content"> + <view + class="u-input__content__prefix-icon" + v-if="prefixIcon || $slots.prefix" + > + <slot name="prefix"> + <u-icon + :name="prefixIcon" + size="18" + :customStyle="prefixIconStyle" + ></u-icon> + </slot> + </view> + <view class="u-input__content__field-wrapper" @tap="clickHandler"> + <!-- ������uni-app���input���������������H5���APP������������������password������(������true������false)���type������������������ + ������������type=number���������������password���������type���������������������������password���undefined + --> + <input + class="u-input__content__field-wrapper__field" + :style="[inputStyle]" + :type="type" + :focus="focus" + :cursor="cursor" + :value="innerValue" + :auto-blur="autoBlur" + :disabled="disabled || readonly" + :maxlength="maxlength" + :placeholder="placeholder" + :placeholder-style="placeholderStyle" + :placeholder-class="placeholderClass" + :confirm-type="confirmType" + :confirm-hold="confirmHold" + :hold-keyboard="holdKeyboard" + :cursor-spacing="cursorSpacing" + :adjust-position="adjustPosition" + :selection-end="selectionEnd" + :selection-start="selectionStart" + :password="password || type === 'password' || undefined" + :ignoreCompositionEvent="ignoreCompositionEvent" + @input="onInput" + @blur="onBlur" + @focus="onFocus" + @confirm="onConfirm" + @keyboardheightchange="onkeyboardheightchange" + /> + </view> + <view + class="u-input__content__clear" + v-if="isShowClear" + @tap="onClear" + > + <u-icon + name="close" + size="11" + color="#ffffff" + customStyle="line-height: 12px" + ></u-icon> + </view> + <view + class="u-input__content__subfix-icon" + v-if="suffixIcon || $slots.suffix" + > + <slot name="suffix"> + <u-icon + :name="suffixIcon" + size="18" + :customStyle="suffixIconStyle" + ></u-icon> + </slot> + </view> + </view> + </view> +</template> + +<script> +import props from "./props.js"; +/** + * Input ��������� + * @description ������������������������������������������������������������������������������������������u-form������������������������������������������������������������������������������������������������ + * @tutorial https://uviewui.com/components/input.html + * @property {String | Number} value ������������ + * @property {String} type ��������������������������������� ��� ������ 'text' ��� + * @property {Boolean} fixed ������ textarea ������������ position:fixed ������������������������������������ fixed ��� true���������������������������������������������������������������������������QQ��������� ��� ������ false ��� + * @property {Boolean} disabled ��������������������� ��� ������ false ��� + * @property {String} disabledColor ������������������������������ ������ '#f5f7fa' ��� + * @property {Boolean} clearable ������������������������ ��� ������ false ��� + * @property {Boolean} password ������������������ ��� ������ false ��� + * @property {String | Number} maxlength ������������������������������ -1 ������������������������������ ��� ������ -1 ��� + * @property {String} placeholder ������������������������������ + * @property {String} placeholderClass ������placeholder���������������������������������������style���������scoped���������������������������/deep/ ��� ������ 'input-placeholder' ��� + * @property {String | Object} placeholderStyle ������placeholder���������������������/������������������"color: red;" + * @property {Boolean} showWordLimit ��������������������������������������� type ="text"���type ="textarea"��������� ��� ������ false ��� + * @property {String} confirmType ������������������������������������������������uni-app������ ��� ������ 'done' ��� + * @property {Boolean} confirmHold ������������������������������������������������������������H5������ ��� ������ false ��� + * @property {Boolean} holdKeyboard focus������������������������������������������������������������������ ��� ������ false ��� + * @property {Boolean} focus ������������������������ H5 ������������������������������������������������������������������������������������������������nvue ������������������������������������ focus()���blur() ������������������ ��� ������ false ��� + * @property {Boolean} autoBlur ������������������������������������������������������App3.0.0+������ ��� ������ false ��� + * @property {Boolean} disableDefaultPadding ������������ iOS ������������������������������������������������type=textarea��������� ��� ������ false ��� + * @property {String ��� Number} cursor ������focus��������������������� ������ -1 ��� + * @property {String ��� Number} cursorSpacing ������������������������������������������ ��� ������ 30 ��� + * @property {String ��� Number} selectionStart ���������������������������������������������������selection-end������������ ��� ������ -1 ��� + * @property {String ��� Number} selectionEnd ���������������������������������������������������selection-start������������ ��� ������ -1 ��� + * @property {Boolean} adjustPosition ������������������������������������������ ��� ������ true ��� + * @property {String} inputAlign ������������������������������ ������ 'left' ��� + * @property {String | Number} fontSize ������������������������ ��� ������ '15px' ��� + * @property {String} color ��������������������� ��� ������ '#303133' ��� + * @property {Function} formatter ������������������ + * @property {String} prefixIcon ��������������������� + * @property {String | Object} prefixIconStyle ��������������������������������������� + * @property {String} suffixIcon ��������������������� + * @property {String | Object} suffixIconStyle ��������������������������������������� + * @property {String} border ���������������surround-���������������bottom-���������������none-��������� ��� ������ 'surround' ��� + * @property {Boolean} readonly ������������������disabled������������������disabled���������������������readonly��������� ��� ������ false ��� + * @property {String} shape ������������������circle-���������square-������ ��� ������ 'square' ��� + * @property {Object} customStyle ��������������������������������� + * @property {Boolean} ignoreCompositionEvent ������������������������������������������������������������ + * @example <u-input v-model="value" :password="true" suffix-icon="lock-fill" /> + */ +export default { + name: "u-input", + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + // ��������������� + innerValue: "", + // ������������������������������ + focused: false, + // value���������������������������watch������������������immediate������������������������������������������������������value��������������� + firstChange: true, + // value��������������������������������������������������� + changeFromInner: false, + // ������������������ + innerFormatter: value => value + }; + }, + watch: { + value: { + immediate: true, + handler(newVal, oldVal) { + this.innerValue = newVal; + /* #ifdef H5 */ + // ���H5������������value������������������input������������������������@input������������������������������������������ + if ( + this.firstChange === false && + this.changeFromInner === false + ) { + this.valueChange(); + } + /* #endif */ + this.firstChange = false; + // ������changeFromInner���������false������������������������������������������������ + this.changeFromInner = false; + }, + }, + }, + computed: { + // ������������������������ + isShowClear() { + const { clearable, readonly, focused, innerValue } = this; + return !!clearable && !readonly && !!focused && innerValue !== ""; + }, + // ��������������� + inputClass() { + let classes = [], + { border, disabled, shape } = this; + border === "surround" && + (classes = classes.concat(["u-border", "u-input--radius"])); + classes.push(`u-input--${shape}`); + border === "bottom" && + (classes = classes.concat([ + "u-border-bottom", + "u-input--no-radius", + ])); + return classes.join(" "); + }, + // ��������������� + wrapperStyle() { + const style = {}; + // ��������������������������������������������������� + if (this.disabled) { + style.backgroundColor = this.disabledColor; + } + // ������������������������������ + if (this.border === "none") { + style.padding = "0"; + } else { + // ������uni-app���iOS������������������������������������������������������ + style.paddingTop = "6px"; + style.paddingBottom = "6px"; + style.paddingLeft = "9px"; + style.paddingRight = "9px"; + } + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)); + }, + // ������������������ + inputStyle() { + const style = { + color: this.color, + fontSize: uni.$u.addUnit(this.fontSize), + textAlign: this.inputAlign + }; + return style; + }, + }, + methods: { + // ������������������������������������������������props������������������������ref������������ + setFormatter(e) { + this.innerFormatter = e + }, + // ���������������������������input������ + onInput(e) { + let { value = "" } = e.detail || {}; + // ��������������������� + const formatter = this.formatter || this.innerFormatter + const formatValue = formatter(value) + // ������������props���������������������������������������innerValue������������������������������$nextTick��������������������������������������� + this.innerValue = value + this.$nextTick(() => { + this.innerValue = formatValue; + this.valueChange(); + }) + }, + // ������������������������������ + onBlur(event) { + this.$emit("blur", event.detail.value); + // H5������blur������������������������������������click���������������������focused + // ���������false��������������������������������������������������� + uni.$u.sleep(50).then(() => { + this.focused = false; + }); + // ������������u-form��������������� + uni.$u.formValidate(this, "blur"); + }, + // ������������������������ + onFocus(event) { + this.focused = true; + this.$emit("focus"); + }, + // ��������������������������� + onConfirm(event) { + this.$emit("confirm", this.innerValue); + }, + // ������������������������������������������������ + // ���������������������������2.7.0+���App 3.1.0+ + onkeyboardheightchange() { + this.$emit("keyboardheightchange"); + }, + // ��������������������������������� + valueChange() { + const value = this.innerValue; + this.$nextTick(() => { + this.$emit("input", value); + // ������value��������������������������������� + this.changeFromInner = true; + this.$emit("change", value); + // ������������u-form��������������� + uni.$u.formValidate(this, "change"); + }); + }, + // ������������������ + onClear() { + this.innerValue = ""; + this.$nextTick(() => { + this.valueChange(); + this.$emit("clear"); + }); + }, + /** + * ���������nvue������������������������ + * ������������������������������������u-from-item���������������������������������������u-form-item������u-input��� + * ������������u-form-item������������������������������������������u-form-item��������������������� + */ + clickHandler() { + // #ifdef APP-NVUE + if (uni.$u.os() === "android") { + const formItem = uni.$u.$parent.call(this, "u-form-item"); + if (formItem) { + formItem.clickHandler(); + } + } + // #endif + }, + }, +}; +</script> + +<style lang="scss" scoped> +@import "../../libs/css/components.scss"; + +.u-input { + @include flex(row); + align-items: center; + justify-content: space-between; + flex: 1; + + &--radius, + &--square { + border-radius: 4px; + } + + &--no-radius { + border-radius: 0; + } + + &--circle { + border-radius: 100px; + } + + &__content { + flex: 1; + @include flex(row); + align-items: center; + justify-content: space-between; + + &__field-wrapper { + position: relative; + @include flex(row); + margin: 0; + flex: 1; + + &__field { + line-height: 26px; + text-align: left; + color: $u-main-color; + height: 24px; + font-size: 15px; + flex: 1; + } + } + + &__clear { + width: 20px; + height: 20px; + border-radius: 100px; + background-color: #c6c7cb; + @include flex(row); + align-items: center; + justify-content: center; + transform: scale(0.82); + margin-left: 4px; + } + + &__subfix-icon { + margin-left: 4px; + } + + &__prefix-icon { + margin-right: 4px; + } + } +} +</style> diff --git a/uni_modules/uview-ui/components/u-keyboard/props.js b/uni_modules/uview-ui/components/u-keyboard/props.js new file mode 100644 index 0000000..cfdb00a --- /dev/null +++ b/uni_modules/uview-ui/components/u-keyboard/props.js @@ -0,0 +1,84 @@ +export default { + props: { + // ������������������number-���������������card-������������������car-��������������� + mode: { + type: String, + default: uni.$u.props.keyboard.mode + }, + // ���������������������"."������ + dotDisabled: { + type: Boolean, + default: uni.$u.props.keyboard.dotDisabled + }, + // ��������������������������� + tooltip: { + type: Boolean, + default: uni.$u.props.keyboard.tooltip + }, + // ������������������������������������ + showTips: { + type: Boolean, + default: uni.$u.props.keyboard.showTips + }, + // ������������������������������ + tips: { + type: String, + default: uni.$u.props.keyboard.tips + }, + // ������������������������������"������"������ + showCancel: { + type: Boolean, + default: uni.$u.props.keyboard.showCancel + }, + // ������������������������������"������"������ + showConfirm: { + type: Boolean, + default: uni.$u.props.keyboard.showConfirm + }, + // ��������������������������������� + random: { + type: Boolean, + default: uni.$u.props.keyboard.random + }, + // ���������������������������������������������������������iPhoneX������������������������������������ + safeAreaInsetBottom: { + type: Boolean, + default: uni.$u.props.keyboard.safeAreaInsetBottom + }, + // ������������������������������������������ + closeOnClickOverlay: { + type: Boolean, + default: uni.$u.props.keyboard.closeOnClickOverlay + }, + // ������������������������������ + show: { + type: Boolean, + default: uni.$u.props.keyboard.show + }, + // ������������������������������������������������������������������������������������������������������������������ + overlay: { + type: Boolean, + default: uni.$u.props.keyboard.overlay + }, + // z-index��� + zIndex: { + type: [String, Number], + default: uni.$u.props.keyboard.zIndex + }, + // ��������������������� + cancelText: { + type: String, + default: uni.$u.props.keyboard.cancelText + }, + // ��������������������� + confirmText: { + type: String, + default: uni.$u.props.keyboard.confirmText + }, + // ��������������������������������������������������� + autoChange: { + type: Boolean, + default: uni.$u.props.keyboard.autoChange + } + } +} diff --git a/uni_modules/uview-ui/components/u-keyboard/u-keyboard.vue b/uni_modules/uview-ui/components/u-keyboard/u-keyboard.vue new file mode 100644 index 0000000..14228cb --- /dev/null +++ b/uni_modules/uview-ui/components/u-keyboard/u-keyboard.vue @@ -0,0 +1,164 @@ +<template> + <u-popup + :overlay="overlay" + :closeOnClickOverlay="closeOnClickOverlay" + mode="bottom" + :popup="false" + :show="show" + :safeAreaInsetBottom="safeAreaInsetBottom" + @close="popupClose" + :zIndex="zIndex" + :customStyle="{ + backgroundColor: 'rgb(214, 218, 220)' + }" + > + <view class="u-keyboard"> + <slot /> + <view + class="u-keyboard__tooltip" + v-if="tooltip" + > + <view + hover-class="u-hover-class" + :hover-stay-time="100" + > + <text + class="u-keyboard__tooltip__item u-keyboard__tooltip__cancel" + v-if="showCancel" + @tap="onCancel" + >{{showCancel && cancelText}}</text> + </view> + <view> + <text + v-if="showTips" + class="u-keyboard__tooltip__item u-keyboard__tooltip__tips" + >{{tips ? tips : mode == 'number' ? '������������' : mode == 'card' ? '���������������' : '���������������'}}</text> + </view> + <view + hover-class="u-hover-class" + :hover-stay-time="100" + > + <text + v-if="showConfirm" + @tap="onConfirm" + class="u-keyboard__tooltip__item u-keyboard__tooltip__submit" + hover-class="u-hover-class" + >{{showConfirm && confirmText}}</text> + </view> + </view> + <template v-if="mode == 'number' || mode == 'card'"> + <u-number-keyboard + :random="random" + @backspace="backspace" + @change="change" + :mode="mode" + :dotDisabled="dotDisabled" + ></u-number-keyboard> + </template> + <template v-else> + <u-car-keyboard + :random="random" + :autoChange="autoChange" + @backspace="backspace" + @change="change" + ></u-car-keyboard> + </template> + </view> + </u-popup> +</template> + +<script> + import props from './props.js'; + + /** + * keyboard ������ + * @description ������uViw������������������������������������������������������������������������������������3������������������������������������������������������ + * @tutorial https://www.uviewui.com/components/keyboard.html + * @property {String} mode ��������������������������������������������� ��������� 'number' ��� + * @property {Boolean} dotDisabled ������������"."���������������mode=number��������� ��������� false ��� + * @property {Boolean} tooltip ��������������������������������� ��������� true ��� + * @property {Boolean} showTips ������������������������������������ ��������� true ��� + * @property {String} tips ���������������������������������������������������������������������������������������""��������� + * @property {Boolean} showCancel ������������������������������"������"������ ��������� true ��� + * @property {Boolean} showConfirm ������������������������������"������"��������� ������ true ��� + * @property {Boolean} random ��������������������������������� ��������� false ��� + * @property {Boolean} safeAreaInsetBottom ��������������������������������� ��������� true ��� + * @property {Boolean} closeOnClickOverlay ������������������������������������ ��������� true ��� + * @property {Boolean} show ��������������������������������������� false ��� + * @property {Boolean} overlay ������������������ ��������� true ��� + * @property {String | Number} zIndex ���������������z-index��� ��������� 1075 ��� + * @property {String} cancelText ��������������������� ��������� '������' ��� + * @property {String} confirmText ��������������������� ��������� '������' ��� + * @property {Object} customStyle ������������������������������ + * @event {Function} change ���������������(���������������������������) + * @event {Function} cancel ������������������������������"������"��������������� + * @event {Function} confirm ������������������������������"������"��������������� + * @event {Function} backspace ������������������������ + * @example <u-keyboard mode="number" v-model="show"></u-keyboard> + */ + export default { + name: "u-keyboard", + data() { + return { + + } + }, + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + methods: { + change(e) { + this.$emit('change', e); + }, + // ������������ + popupClose() { + this.$emit('close'); + }, + // ������������ + onConfirm() { + this.$emit('confirm'); + }, + // ������������ + onCancel() { + this.$emit('cancel'); + }, + // ��������� + backspace() { + this.$emit('backspace'); + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-keyboard { + + &__tooltip { + @include flex; + justify-content: space-between; + background-color: #FFFFFF; + padding: 14px 12px; + + &__item { + color: #333333; + flex: 1; + text-align: center; + font-size: 15px; + } + + &__submit { + text-align: right; + color: $u-primary; + } + + &__cancel { + text-align: left; + color: #888888; + } + + &__tips { + color: $u-tips-color; + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-line-progress/props.js b/uni_modules/uview-ui/components/u-line-progress/props.js new file mode 100644 index 0000000..a4210bd --- /dev/null +++ b/uni_modules/uview-ui/components/u-line-progress/props.js @@ -0,0 +1,28 @@ +export default { + props: { + // ��������������������� + activeColor: { + type: String, + default: uni.$u.props.lineProgress.activeColor + }, + inactiveColor: { + type: String, + default: uni.$u.props.lineProgress.color + }, + // ������������������������ + percentage: { + type: [String, Number], + default: uni.$u.props.lineProgress.inactiveColor + }, + // ��������������������������������������������� + showText: { + type: Boolean, + default: uni.$u.props.lineProgress.showText + }, + // ���������������������������px + height: { + type: [String, Number], + default: uni.$u.props.lineProgress.height + } + } +} diff --git a/uni_modules/uview-ui/components/u-line-progress/u-line-progress.vue b/uni_modules/uview-ui/components/u-line-progress/u-line-progress.vue new file mode 100644 index 0000000..4e27931 --- /dev/null +++ b/uni_modules/uview-ui/components/u-line-progress/u-line-progress.vue @@ -0,0 +1,144 @@ +<template> + <view + class="u-line-progress" + :style="[$u.addStyle(customStyle)]" + > + <view + class="u-line-progress__background" + ref="u-line-progress__background" + :style="[{ + backgroundColor: inactiveColor, + height: $u.addUnit(height), + }]" + > + </view> + <view + class="u-line-progress__line" + :style="[progressStyle]" + > + <slot> + <text v-if="showText && percentage >= 10" class="u-line-progress__text">{{innserPercentage + '%'}}</text> + </slot> + </view> + </view> +</template> + +<script> + import props from './props.js'; + // #ifdef APP-NVUE + const dom = uni.requireNativePlugin('dom') + // #endif + /** + * lineProgress ��������������� + * @description ������������������������������������������������������������������������������������������ + * @tutorial https://www.uviewui.com/components/lineProgress.html + * @property {String} activeColor ��������������������� ( ������ '#19be6b' ) + * @property {String} inactiveColor ��������� ( ������ '#ececec' ) + * @property {String | Number} percentage ������������������������ ( ������ 0 ) + * @property {Boolean} showText ��������������������������������������������� ( ������ true ) + * @property {String | Number} height ���������������������������px ( ������ 12 ) + * + * @example <u-line-progress :percent="70" :show-percent="true"></u-line-progress> + */ + export default { + name: "u-line-progress", + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + lineWidth: 0, + } + }, + watch: { + percentage(n) { + this.resizeProgressWidth() + } + }, + computed: { + progressStyle() { + let style = {} + style.width = this.lineWidth + style.backgroundColor = this.activeColor + style.height = uni.$u.addUnit(this.height) + return style + }, + innserPercentage() { + // ���������������0-100������ + return uni.$u.range(0, 100, this.percentage) + } + }, + mounted() { + this.init() + }, + methods: { + init() { + uni.$u.sleep(20).then(() => { + this.resizeProgressWidth() + }) + }, + getProgressWidth() { + // #ifndef APP-NVUE + return this.$uGetRect('.u-line-progress__background') + // #endif + + // #ifdef APP-NVUE + // ������������promise + return new Promise(resolve => { + dom.getComponentRect(this.$refs['u-line-progress__background'], (res) => { + resolve(res.size) + }) + }) + // #endif + }, + resizeProgressWidth() { + this.getProgressWidth().then(size => { + const { + width + } = size + // ���������������percentage������������������������������������������ + this.lineWidth = width * this.innserPercentage / 100 + 'px' + }) + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-line-progress { + align-items: stretch; + position: relative; + @include flex(row); + flex: 1; + overflow: hidden; + border-radius: 100px; + + &__background { + background-color: #ececec; + border-radius: 100px; + flex: 1; + } + + &__line { + position: absolute; + top: 0; + left: 0; + bottom: 0; + align-items: center; + @include flex(row); + color: #ffffff; + border-radius: 100px; + transition: width 0.5s ease; + justify-content: flex-end; + } + + &__text { + font-size: 10px; + align-items: center; + text-align: right; + color: #FFFFFF; + margin-right: 5px; + transform: scale(0.9); + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-line/props.js b/uni_modules/uview-ui/components/u-line/props.js new file mode 100644 index 0000000..2308cc3 --- /dev/null +++ b/uni_modules/uview-ui/components/u-line/props.js @@ -0,0 +1,33 @@ +export default { + props: { + color: { + type: String, + default: uni.$u.props.line.color + }, + // ���������������������������������������������������������������������������������������px��������������� + length: { + type: [String, Number], + default: uni.$u.props.line.length + }, + // ���������������col-���������row-������ + direction: { + type: String, + default: uni.$u.props.line.direction + }, + // ��������������������� + hairline: { + type: Boolean, + default: uni.$u.props.line.hairline + }, + // ������������������������������������������������������������"30px"���"20px 30px" + margin: { + type: [String, Number], + default: uni.$u.props.line.margin + }, + // ���������������true-���������false-������ + dashed: { + type: Boolean, + default: uni.$u.props.line.dashed + } + } +} diff --git a/uni_modules/uview-ui/components/u-line/u-line.vue b/uni_modules/uview-ui/components/u-line/u-line.vue new file mode 100644 index 0000000..e0a6d92 --- /dev/null +++ b/uni_modules/uview-ui/components/u-line/u-line.vue @@ -0,0 +1,62 @@ +<template> + <view + class="u-line" + :style="[lineStyle]" + > + + </view> +</template> + +<script> + import props from './props.js'; + /** + * line ������ + * @description ���������������������������������������������������������������������������������������������������������������0.5px��������������������������� + * @tutorial https://www.uviewui.com/components/line.html + * @property {String} color ��������������� ( ������ '#d6d7d9' ) + * @property {String | Number} length ���������������������������������������������������������������������������������������px��������������� ( ������ '100%' ) + * @property {String} direction ������������������row-���������col-������ (������ 'row' ) + * @property {Boolean} hairline ��������������������� (������ true ) + * @property {String | Number} margin ������������������������������������������������������������"30px" (������ 0 ) + * @property {Boolean} dashed ���������������true-���������false-������ (������ false ) + * @property {Object} customStyle ��������������������������������� + * @example <u-line color="red"></u-line> + */ + export default { + name: 'u-line', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + computed: { + lineStyle() { + const style = {} + style.margin = this.margin + // ���������������������������������������1px������������transform���������������������0.5px��� + if (this.direction === 'row') { + // ������������������������������������nvue��������� + style.borderBottomWidth = '1px' + style.borderBottomStyle = this.dashed ? 'dashed' : 'solid' + style.width = uni.$u.addUnit(this.length) + if (this.hairline) style.transform = 'scaleY(0.5)' + } else { + // ���������������������������������������1px������������transform���������������������0.5px��� + style.borderLeftWidth = '1px' + style.borderLeftStyle = this.dashed ? 'dashed' : 'solid' + style.height = uni.$u.addUnit(this.length) + if (this.hairline) style.transform = 'scaleX(0.5)' + } + + style.borderColor = this.color + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-line { + /* #ifndef APP-NVUE */ + vertical-align: middle; + /* #endif */ + } +</style> diff --git a/uni_modules/uview-ui/components/u-link/props.js b/uni_modules/uview-ui/components/u-link/props.js new file mode 100644 index 0000000..d39353f --- /dev/null +++ b/uni_modules/uview-ui/components/u-link/props.js @@ -0,0 +1,39 @@ +export default { + props: { + // ������������ + color: { + type: String, + default: uni.$u.props.link.color + }, + // ���������������������px + fontSize: { + type: [String, Number], + default: uni.$u.props.link.fontSize + }, + // ��������������������� + underLine: { + type: Boolean, + default: uni.$u.props.link.underLine + }, + // ������������������ + href: { + type: String, + default: uni.$u.props.link.href + }, + // ������������������������������������������ + mpTips: { + type: String, + default: uni.$u.props.link.mpTips + }, + // ��������������� + lineColor: { + type: String, + default: uni.$u.props.link.lineColor + }, + // ������������������������������slot������������������������nvue��������������������� + text: { + type: String, + default: uni.$u.props.link.text + } + } +} diff --git a/uni_modules/uview-ui/components/u-link/u-link.vue b/uni_modules/uview-ui/components/u-link/u-link.vue new file mode 100644 index 0000000..c6802a5 --- /dev/null +++ b/uni_modules/uview-ui/components/u-link/u-link.vue @@ -0,0 +1,83 @@ +<template> + <text + class="u-link" + @tap.stop="openLink" + :style="[linkStyle, $u.addStyle(customStyle)]" + >{{text}}</text> +</template> + +<script> + import props from './props.js'; + + /** + * link ��������� + * @description ������������������������������������������������������������������������APP���������������plus���������������������������������������������������������������������������������������������������H5���������window.open��������������� + * @tutorial https://www.uviewui.com/components/link.html + * @property {String} color ������������ ��������� color['u-primary'] ��� + * @property {String ��� Number} fontSize ���������������������px ��������� 15 ��� + * @property {Boolean} underLine ��������������������� ��������� false ��� + * @property {String} href ���������������������������http(s) + * @property {String} mpTips ������������������������������������������������������������������������������������������������������������������������ + * @property {String} lineColor ���������������������������color������������ + * @property {String} text ������������������������������slot������������������������nvue��������������������� + * @property {Object} customStyle ��������������������������������� + * + * @example <u-link href="http://www.uviewui.com">���������������������������</u-link> + */ + export default { + name: "u-link", + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + computed: { + linkStyle() { + const style = { + color: this.color, + fontSize: uni.$u.addUnit(this.fontSize), + // line-height���������������������������2px + lineHeight: uni.$u.addUnit(uni.$u.getPx(this.fontSize) + 2), + textDecoration: this.underLine ? 'underline' : 'none' + } + // if (this.underLine) { + // style.borderBottomColor = this.lineColor || this.color + // style.borderBottomWidth = '1px' + // } + return style + } + }, + methods: { + openLink() { + // #ifdef APP-PLUS + plus.runtime.openURL(this.href) + // #endif + // #ifdef H5 + window.open(this.href) + // #endif + // #ifdef MP + uni.setClipboardData({ + data: this.href, + success: () => { + uni.hideToast(); + this.$nextTick(() => { + uni.$u.toast(this.mpTips); + }) + } + }); + // #endif + this.$emit('click') + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + $u-link-line-height:1 !default; + + .u-link { + /* #ifndef APP-NVUE */ + line-height: $u-link-line-height; + /* #endif */ + @include flex; + flex-wrap: wrap; + flex: 1; + } +</style> diff --git a/uni_modules/uview-ui/components/u-list-item/props.js b/uni_modules/uview-ui/components/u-list-item/props.js new file mode 100644 index 0000000..58ddc49 --- /dev/null +++ b/uni_modules/uview-ui/components/u-list-item/props.js @@ -0,0 +1,9 @@ +export default { + props: { + // ���������������������item + anchor: { + type: [String, Number], + default: uni.$u.props.listItem.anchor + } + } +} diff --git a/uni_modules/uview-ui/components/u-list-item/u-list-item.vue b/uni_modules/uview-ui/components/u-list-item/u-list-item.vue new file mode 100644 index 0000000..1a25db6 --- /dev/null +++ b/uni_modules/uview-ui/components/u-list-item/u-list-item.vue @@ -0,0 +1,116 @@ +<template> + <!-- #ifdef APP-NVUE --> + <cell> + <!-- #endif --> + <view + class="u-list-item" + :ref="`u-list-item-${anchor}`" + :anchor="`u-list-item-${anchor}`" + :class="[`u-list-item-${anchor}`]" + > + <slot /> + </view> + <!-- #ifdef APP-NVUE --> + </cell> + <!-- #endif --> +</template> + +<script> + import props from './props.js'; + // #ifdef APP-NVUE + const dom = uni.requireNativePlugin('dom') + // #endif + /** + * List ������ + * @description ��������������������������������� + * @tutorial https://www.uviewui.com/components/list.html + * @property {String | Number} anchor ���������������������item + * @example <u-list-ite v-for="(item, index) in indexList" :key="index" ></u-list-item> + */ + export default { + name: 'u-list-item', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + // ������������ + rect: {}, + index: 0, + show: true, + sys: uni.$u.sys() + } + }, + computed: { + + }, + inject: ['uList'], + watch: { + // #ifndef APP-NVUE + 'uList.innerScrollTop'(n) { + const preLoadScreen = this.uList.preLoadScreen + const windowHeight = this.sys.windowHeight + if(n <= windowHeight * preLoadScreen) { + this.parent.updateOffsetFromChild(0) + } else if (this.rect.top <= n - windowHeight * preLoadScreen) { + this.parent.updateOffsetFromChild(this.rect.top) + } + } + // #endif + }, + created() { + this.parent = {} + }, + mounted() { + this.init() + }, + methods: { + init() { + // ��������������� + this.updateParentData() + this.index = this.parent.children.indexOf(this) + this.resize() + }, + updateParentData() { + // ������������mixin��� + this.getParentData('u-list') + }, + resize() { + this.queryRect(`u-list-item-${this.anchor}`).then(size => { + const lastChild = this.parent.children[this.index - 1] + this.rect = size + const preLoadScreen = this.uList.preLoadScreen + const windowHeight = this.sys.windowHeight + // #ifndef APP-NVUE + if (lastChild) { + this.rect.top = lastChild.rect.top + lastChild.rect.height + } + if (size.top >= this.uList.innerScrollTop + (1 + preLoadScreen) * windowHeight) this.show = + false + // #endif + }) + }, + // ������������������ + queryRect(el) { + return new Promise(resolve => { + // #ifndef APP-NVUE + this.$uGetRect(`.${el}`).then(size => { + resolve(size) + }) + // #endif + + // #ifdef APP-NVUE + const ref = this.$refs[el] + dom.getComponentRect(ref, res => { + resolve(res.size) + }) + // #endif + }) + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-list-item {} +</style> diff --git a/uni_modules/uview-ui/components/u-list/props.js b/uni_modules/uview-ui/components/u-list/props.js new file mode 100644 index 0000000..25406f4 --- /dev/null +++ b/uni_modules/uview-ui/components/u-list/props.js @@ -0,0 +1,76 @@ +export default { + props: { + // ���������������������������������nvue������ + showScrollbar: { + type: Boolean, + default: uni.$u.props.list.showScrollbar + }, + // ������������������������scrolltolower������ + lowerThreshold: { + type: [String, Number], + default: uni.$u.props.list.lowerThreshold + }, + // ������������������������scrolltoupper������������nvue������ + upperThreshold: { + type: [String, Number], + default: uni.$u.props.list.upperThreshold + }, + // ��������������������������� + scrollTop: { + type: [String, Number], + default: uni.$u.props.list.scrollTop + }, + // ������ onscroll ���������������������������nvue������ + offsetAccuracy: { + type: [String, Number], + default: uni.$u.props.list.offsetAccuracy + }, + // ������ flexbox ������������������������������������������display: flex������������flex container��������������������������������������������������������� + enableFlex: { + type: Boolean, + default: uni.$u.props.list.enableFlex + }, + // ���������������������������List������������false + pagingEnabled: { + type: Boolean, + default: uni.$u.props.list.pagingEnabled + }, + // ������������List������ + scrollable: { + type: Boolean, + default: uni.$u.props.list.scrollable + }, + // ���������������������id���id������������������������ + scrollIntoView: { + type: String, + default: uni.$u.props.list.scrollIntoView + }, + // ��������������������������������������������� + scrollWithAnimation: { + type: Boolean, + default: uni.$u.props.list.scrollWithAnimation + }, + // iOS������������������������������������������������������������������������������������������������������ + enableBackToTop: { + type: Boolean, + default: uni.$u.props.list.enableBackToTop + }, + // ��������������� + height: { + type: [String, Number], + default: uni.$u.props.list.height + }, + // ������������ + width: { + type: [String, Number], + default: uni.$u.props.list.width + }, + // ���������������������������������1������������������������������1.5������1������������������ + preLoadScreen: { + type: [String, Number], + default: uni.$u.props.list.preLoadScreen + } + // vue������������������������������ + + } +} diff --git a/uni_modules/uview-ui/components/u-list/u-list.vue b/uni_modules/uview-ui/components/u-list/u-list.vue new file mode 100644 index 0000000..4447cab --- /dev/null +++ b/uni_modules/uview-ui/components/u-list/u-list.vue @@ -0,0 +1,157 @@ +<template> + <!-- #ifdef APP-NVUE --> + <list + class="u-list" + :enableBackToTop="enableBackToTop" + :loadmoreoffset="lowerThreshold" + :showScrollbar="showScrollbar" + :style="[listStyle]" + :offset-accuracy="Number(offsetAccuracy)" + @scroll="onScroll" + @loadmore="scrolltolower" + > + <slot /> + </list> + <!-- #endif --> + <!-- #ifndef APP-NVUE --> + <scroll-view + class="u-list" + :scroll-into-view="scrollIntoView" + :style="[listStyle]" + scroll-y + :scroll-top="Number(scrollTop)" + :lower-threshold="Number(lowerThreshold)" + :upper-threshold="Number(upperThreshold)" + :show-scrollbar="showScrollbar" + :enable-back-to-top="enableBackToTop" + :scroll-with-animation="scrollWithAnimation" + @scroll="onScroll" + @scrolltolower="scrolltolower" + @scrolltoupper="scrolltoupper" + > + <view> + <slot /> + </view> + </scroll-view> + <!-- #endif --> +</template> + +<script> + import props from './props.js'; + // #ifdef APP-NVUE + const dom = uni.requireNativePlugin('dom') + // #endif + /** + * List ������ + * @description ��������������������������������� + * @tutorial https://www.uviewui.com/components/list.html + * @property {Boolean} showScrollbar ���������������������������������nvue������ ��������� false ��� + * @property {String ��� Number} lowerThreshold ������������������������scrolltolower������ ��������� 50 ��� + * @property {String ��� Number} upperThreshold ������������������������scrolltoupper������������nvue������ ��������� 0 ��� + * @property {String ��� Number} scrollTop ������������������������������������ 0 ��� + * @property {String ��� Number} offsetAccuracy ������ onscroll ���������������������������nvue��������������� 10 ��� + * @property {Boolean} enableFlex ������ flexbox ������������������������������������������display: flex������������flex container������������������������������������������������������������������ false ��� + * @property {Boolean} pagingEnabled ���������������������������List������������ false ��� + * @property {Boolean} scrollable ������������List��������������� true ��� + * @property {String} scrollIntoView ���������������������id���id������������������������ + * @property {Boolean} scrollWithAnimation ��������������������������������������������� ��������� false ��� + * @property {Boolean} enableBackToTop iOS������������������������������������������������������������������������������������������������������ ��������� false ��� + * @property {String ��� Number} height ��������������� ��������� 0 ��� + * @property {String ��� Number} width ������������ ��������� 0 ��� + * @property {String ��� Number} preLoadScreen ���������������������������������1������������������������������1.5������1������������������ ��������� 1 ��� + * @property {Object} customStyle ��������������������������������� + * + * @example <u-list @scrolltolower="scrolltolower"></u-list> + */ + export default { + name: 'u-list', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + watch: { + scrollIntoView(n) { + this.scrollIntoViewById(n) + } + }, + data() { + return { + // ��������������������������� + innerScrollTop: 0, + // vue������scroll-view������������������������������ + offset: 0, + sys: uni.$u.sys() + } + }, + computed: { + listStyle() { + const style = {}, + addUnit = uni.$u.addUnit + if (this.width != 0) style.width = addUnit(this.width) + if (this.height != 0) style.height = addUnit(this.height) + // ������������������������������������������������������������ + if (!style.height) style.height = addUnit(this.sys.windowHeight, 'px') + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) + } + }, + provide() { + return { + uList: this + } + }, + created() { + this.refs = [] + this.children = [] + this.anchors = [] + }, + mounted() {}, + methods: { + updateOffsetFromChild(top) { + this.offset = top + }, + onScroll(e) { + let scrollTop = 0 + // #ifdef APP-NVUE + scrollTop = e.contentOffset.y + // #endif + // #ifndef APP-NVUE + scrollTop = e.detail.scrollTop + // #endif + this.innerScrollTop = scrollTop + this.$emit('scroll', Math.abs(scrollTop)) + }, + scrollIntoViewById(id) { + // #ifdef APP-NVUE + // ������id���������������������u-list-item������������������������������dom������������������������������ + const item = this.refs.find(item => item.$refs[id] ? true : false) + dom.scrollToElement(item.$refs[id], { + // ������������������������ + animated: this.scrollWithAnimation + }) + // #endif + }, + // ��������������������������� + scrolltolower(e) { + uni.$u.sleep(30).then(() => { + this.$emit('scrolltolower') + }) + }, + // #ifndef APP-NVUE + // ������������������������������nvue������ + scrolltoupper(e) { + uni.$u.sleep(30).then(() => { + this.$emit('scrolltoupper') + // ���������������������������������������������������������webview��������������������������������������������������������� + this.offset = 0 + }) + } + // #endif + }, + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-list { + @include flex(column); + + } +</style> diff --git a/uni_modules/uview-ui/components/u-loading-icon/props.js b/uni_modules/uview-ui/components/u-loading-icon/props.js new file mode 100644 index 0000000..c35524e --- /dev/null +++ b/uni_modules/uview-ui/components/u-loading-icon/props.js @@ -0,0 +1,59 @@ +export default { + props: { + // ������������������ + show: { + type: Boolean, + default: uni.$u.props.loadingIcon.show + }, + // ������ + color: { + type: String, + default: uni.$u.props.loadingIcon.color + }, + // ������������������ + textColor: { + type: String, + default: uni.$u.props.loadingIcon.textColor + }, + // ��������������������������������� + vertical: { + type: Boolean, + default: uni.$u.props.loadingIcon.vertical + }, + // ���������������circle-���������spinner-������������semicircle-��������� + mode: { + type: String, + default: uni.$u.props.loadingIcon.mode + }, + // ���������������������������px + size: { + type: [String, Number], + default: uni.$u.props.loadingIcon.size + }, + // ������������ + textSize: { + type: [String, Number], + default: uni.$u.props.loadingIcon.textSize + }, + // ������������ + text: { + type: [String, Number], + default: uni.$u.props.loadingIcon.text + }, + // ������������ + timingFunction: { + type: String, + default: uni.$u.props.loadingIcon.timingFunction + }, + // ������������������������ + duration: { + type: [String, Number], + default: uni.$u.props.loadingIcon.duration + }, + // mode=circle������������������ + inactiveColor: { + type: String, + default: uni.$u.props.loadingIcon.inactiveColor + } + } +} diff --git a/uni_modules/uview-ui/components/u-loading-icon/u-loading-icon.vue b/uni_modules/uview-ui/components/u-loading-icon/u-loading-icon.vue new file mode 100644 index 0000000..2ede5c3 --- /dev/null +++ b/uni_modules/uview-ui/components/u-loading-icon/u-loading-icon.vue @@ -0,0 +1,343 @@ +<template> + <view + class="u-loading-icon" + :style="[$u.addStyle(customStyle)]" + :class="[vertical && 'u-loading-icon--vertical']" + v-if="show" + > + <view + v-if="!webviewHide" + class="u-loading-icon__spinner" + :class="[`u-loading-icon__spinner--${mode}`]" + ref="ani" + :style="{ + color: color, + width: $u.addUnit(size), + height: $u.addUnit(size), + borderTopColor: color, + borderBottomColor: otherBorderColor, + borderLeftColor: otherBorderColor, + borderRightColor: otherBorderColor, + 'animation-duration': `${duration}ms`, + 'animation-timing-function': mode === 'semicircle' || mode === 'circle' ? timingFunction : '' + }" + > + <block v-if="mode === 'spinner'"> + <!-- #ifndef APP-NVUE --> + <view + v-for="(item, index) in array12" + :key="index" + class="u-loading-icon__dot" + > + </view> + <!-- #endif --> + <!-- #ifdef APP-NVUE --> + <!-- ������������������������������������������������������������width���height������������������ --> + <loading-indicator + v-if="!webviewHide" + class="u-loading-indicator" + :animating="true" + :style="{ + color: color, + width: $u.addUnit(size), + height: $u.addUnit(size) + }" + /> + <!-- #endif --> + </block> + </view> + <text + v-if="text" + class="u-loading-icon__text" + :style="{ + fontSize: $u.addUnit(textSize), + color: textColor, + }" + >{{text}}</text> + </view> +</template> + +<script> + import props from './props.js'; + // #ifdef APP-NVUE + const animation = weex.requireModule('animation'); + // #endif + /** + * loading ������������ + * @description ���������������������������������������������uView���loadmore���������������switch��������������������������������������������� + * @tutorial https://www.uviewui.com/components/loading.html + * @property {Boolean} show ������������������ (������ true) + * @property {String} color ������������������������������������ mode = flower ���������������������color['u-tips-color']��� + * @property {String} textColor ������������������������������color['u-tips-color']��� + * @property {Boolean} vertical ��������������������������������� (������ false ) + * @property {String} mode ��������������������������������������� 'circle' ��� + * @property {String | Number} size ������������������������������px ��������� 24 ��� + * @property {String | Number} textSize ��������������������� 15 ��� + * @property {String | Number} text ������������ + * @property {String} timingFunction ������������ ��������� 'ease-in-out' ��� + * @property {String | Number} duration ��������������������������������� 1200��� + * @property {String} inactiveColor mode=circle������������������ + * @property {Object} customStyle ��������������������������������� + * @example <u-loading mode="circle"></u-loading> + */ + export default { + name: 'u-loading-icon', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + // Array.form������������������������������������������������������������ + // https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/from + array12: Array.from({ + length: 12 + }), + // ������������������������������360������������������nvue���������������������duration������������������ + // ���iOS nvue������������������������������������������������������ + aniAngel: 360, // ������������������ + webviewHide: false, // ������webview������������������������������������������������������������������������ + loading: false, // ������������������������nvue������ + } + }, + computed: { + // ������circle��������������������������������������������������������������� + // ������������������������������������������������������������color������������������������������������������������������ + // ������������������������������������������(������������������������������������������������������������������������������) + otherBorderColor() { + const lightColor = uni.$u.colorGradient(this.color, '#ffffff', 100)[80] + if (this.mode === 'circle') { + return this.inactiveColor ? this.inactiveColor : lightColor + } else { + return 'transparent' + } + // return this.mode === 'circle' ? this.inactiveColor ? this.inactiveColor : lightColor : 'transparent' + } + }, + watch: { + show(n) { + // nvue������show���true������������loading������������������������������������ + // #ifdef APP-NVUE + if (n && !this.loading) { + setTimeout(() => { + this.startAnimate() + }, 30) + } + // #endif + } + }, + mounted() { + this.init() + }, + methods: { + init() { + setTimeout(() => { + // #ifdef APP-NVUE + this.show && this.nvueAnimate() + // #endif + // #ifdef APP-PLUS + this.show && this.addEventListenerToWebview() + // #endif + }, 20) + }, + // ������webview������������������ + addEventListenerToWebview() { + // webview��������� + const pages = getCurrentPages() + // ������������ + const page = pages[pages.length - 1] + // ���������������webview������ + const currentWebview = page.$getAppWebview() + // ������webview���������������������������������������������������(������������) + currentWebview.addEventListener('hide', () => { + this.webviewHide = true + }) + currentWebview.addEventListener('show', () => { + this.webviewHide = false + }) + }, + // #ifdef APP-NVUE + nvueAnimate() { + // nvue���������spinner���������������������������������nvue���spinner������������������weex��� + // loading-indicator��������������������������� + this.mode !== 'spinner' && this.startAnimate() + }, + // ������nvue���animate������������ + startAnimate() { + this.loading = true + const ani = this.$refs.ani + if (!ani) return + animation.transition(ani, { + // ������������������ + styles: { + transform: `rotate(${this.aniAngel}deg)`, + transformOrigin: 'center center' + }, + duration: this.duration, + timingFunction: this.timingFunction, + // delay: 10 + }, () => { + // ������������360deg��������������������������������� + this.aniAngel += 360 + // ���������������������������������������������������������������webviewHide������ + // nvue���������������������������������������������startAnimate������ + this.show && !this.webviewHide ? this.startAnimate() : this.loading = false + }) + } + // #endif + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + $u-loading-icon-color: #c8c9cc !default; + $u-loading-icon-text-margin-left:4px !default; + $u-loading-icon-text-color:$u-content-color !default; + $u-loading-icon-text-font-size:14px !default; + $u-loading-icon-text-line-height:20px !default; + $u-loading-width:30px !default; + $u-loading-height:30px !default; + $u-loading-max-width:100% !default; + $u-loading-max-height:100% !default; + $u-loading-semicircle-border-width: 2px !default; + $u-loading-semicircle-border-color:transparent !default; + $u-loading-semicircle-border-top-right-radius: 100px !default; + $u-loading-semicircle-border-top-left-radius: 100px !default; + $u-loading-semicircle-border-bottom-left-radius: 100px !default; + $u-loading-semicircle-border-bottom-right-radiu: 100px !default; + $u-loading-semicircle-border-style: solid !default; + $u-loading-circle-border-top-right-radius: 100px !default; + $u-loading-circle-border-top-left-radius: 100px !default; + $u-loading-circle-border-bottom-left-radius: 100px !default; + $u-loading-circle-border-bottom-right-radiu: 100px !default; + $u-loading-circle-border-width:2px !default; + $u-loading-circle-border-top-color:#e5e5e5 !default; + $u-loading-circle-border-right-color:$u-loading-circle-border-top-color !default; + $u-loading-circle-border-bottom-color:$u-loading-circle-border-top-color !default; + $u-loading-circle-border-left-color:$u-loading-circle-border-top-color !default; + $u-loading-circle-border-style:solid !default; + $u-loading-icon-host-font-size:0px !default; + $u-loading-icon-host-line-height:1 !default; + $u-loading-icon-vertical-margin:6px 0 0 !default; + $u-loading-icon-dot-top:0 !default; + $u-loading-icon-dot-left:0 !default; + $u-loading-icon-dot-width:100% !default; + $u-loading-icon-dot-height:100% !default; + $u-loading-icon-dot-before-width:2px !default; + $u-loading-icon-dot-before-height:25% !default; + $u-loading-icon-dot-before-margin:0 auto !default; + $u-loading-icon-dot-before-background-color:currentColor !default; + $u-loading-icon-dot-before-border-radius:40% !default; + + .u-loading-icon { + /* #ifndef APP-NVUE */ + // display: inline-flex; + /* #endif */ + flex-direction: row; + align-items: center; + justify-content: center; + color: $u-loading-icon-color; + + &__text { + margin-left: $u-loading-icon-text-margin-left; + color: $u-loading-icon-text-color; + font-size: $u-loading-icon-text-font-size; + line-height: $u-loading-icon-text-line-height; + } + + &__spinner { + width: $u-loading-width; + height: $u-loading-height; + position: relative; + /* #ifndef APP-NVUE */ + box-sizing: border-box; + max-width: $u-loading-max-width; + max-height: $u-loading-max-height; + animation: u-rotate 1s linear infinite; + /* #endif */ + } + + &__spinner--semicircle { + border-width: $u-loading-semicircle-border-width; + border-color: $u-loading-semicircle-border-color; + border-top-right-radius: $u-loading-semicircle-border-top-right-radius; + border-top-left-radius: $u-loading-semicircle-border-top-left-radius; + border-bottom-left-radius: $u-loading-semicircle-border-bottom-left-radius; + border-bottom-right-radius: $u-loading-semicircle-border-bottom-right-radiu; + border-style: $u-loading-semicircle-border-style; + } + + &__spinner--circle { + border-top-right-radius: $u-loading-circle-border-top-right-radius; + border-top-left-radius: $u-loading-circle-border-top-left-radius; + border-bottom-left-radius: $u-loading-circle-border-bottom-left-radius; + border-bottom-right-radius: $u-loading-circle-border-bottom-right-radiu; + border-width: $u-loading-circle-border-width; + border-top-color: $u-loading-circle-border-top-color; + border-right-color: $u-loading-circle-border-right-color; + border-bottom-color: $u-loading-circle-border-bottom-color; + border-left-color: $u-loading-circle-border-left-color; + border-style: $u-loading-circle-border-style; + } + + &--vertical { + flex-direction: column + } + } + + /* #ifndef APP-NVUE */ + :host { + font-size: $u-loading-icon-host-font-size; + line-height: $u-loading-icon-host-line-height; + } + + .u-loading-icon { + &__spinner--spinner { + animation-timing-function: steps(12) + } + + &__text:empty { + display: none + } + + &--vertical &__text { + margin: $u-loading-icon-vertical-margin; + color: $u-content-color; + } + + &__dot { + position: absolute; + top: $u-loading-icon-dot-top; + left: $u-loading-icon-dot-left; + width: $u-loading-icon-dot-width; + height: $u-loading-icon-dot-height; + + &:before { + display: block; + width: $u-loading-icon-dot-before-width; + height: $u-loading-icon-dot-before-height; + margin: $u-loading-icon-dot-before-margin; + background-color: $u-loading-icon-dot-before-background-color; + border-radius: $u-loading-icon-dot-before-border-radius; + content: " " + } + } + } + + @for $i from 1 through 12 { + .u-loading-icon__dot:nth-of-type(#{$i}) { + transform: rotate($i * 30deg); + opacity: 1 - 0.0625 * ($i - 1); + } + } + + @keyframes u-rotate { + 0% { + transform: rotate(0deg) + } + + to { + transform: rotate(1turn) + } + } + + /* #endif */ +</style> diff --git a/uni_modules/uview-ui/components/u-loading-page/props.js b/uni_modules/uview-ui/components/u-loading-page/props.js new file mode 100644 index 0000000..e239b61 --- /dev/null +++ b/uni_modules/uview-ui/components/u-loading-page/props.js @@ -0,0 +1,49 @@ +export default { + props: { + // ������������ + loadingText: { + type: [String, Number], + default: uni.$u.props.loadingPage.loadingText + }, + // ������������������������loading��������������� + image: { + type: String, + default: uni.$u.props.loadingPage.image + }, + // ������������������������circle-���������spinner-������������semicircle-��������� + loadingMode: { + type: String, + default: uni.$u.props.loadingPage.loadingMode + }, + // ��������������� + loading: { + type: Boolean, + default: uni.$u.props.loadingPage.loading + }, + // ��������� + bgColor: { + type: String, + default: uni.$u.props.loadingPage.bgColor + }, + // ������������ + color: { + type: String, + default: uni.$u.props.loadingPage.color + }, + // ������������ + fontSize: { + type: [String, Number], + default: uni.$u.props.loadingPage.fontSize + }, + // ������������ + iconSize: { + type: [String, Number], + default: uni.$u.props.loadingPage.fontSize + }, + // ���������������������������������rgb��������������������������� + loadingColor: { + type: String, + default: uni.$u.props.loadingPage.loadingColor + } + } +} diff --git a/uni_modules/uview-ui/components/u-loading-page/u-loading-page.vue b/uni_modules/uview-ui/components/u-loading-page/u-loading-page.vue new file mode 100644 index 0000000..03a78ad --- /dev/null +++ b/uni_modules/uview-ui/components/u-loading-page/u-loading-page.vue @@ -0,0 +1,115 @@ +<template> + <u-transition + :show="loading" + :custom-style="{ + position: 'fixed', + top: 0, + left: 0, + right: 0, + bottom: 0, + backgroundColor: bgColor, + display: 'flex', + }" + > + <view class="u-loading-page"> + <view class="u-loading-page__warpper"> + <view class="u-loading-page__warpper__loading-icon"> + <image + v-if="image" + :src="image" + class="u-loading-page__warpper__loading-icon__img" + mode="widthFit" + :style="{ + width: $u.addUnit(iconSize), + height: $u.addUnit(iconSize) + }" + ></image> + <u-loading-icon + v-else + :mode="loadingMode" + :size="$u.addUnit(iconSize)" + :color="loadingColor" + ></u-loading-icon> + </view> + <slot> + <text + class="u-loading-page__warpper__text" + :style="{ + fontSize: $u.addUnit(fontSize), + color: color, + }" + >{{ loadingText }}</text + > + </slot> + </view> + </view> + </u-transition> +</template> + +<script> +import props from "./props.js"; +/** + * loadingPage ������������ + * @description ���������������������������������������������uView���loadmore���������������switch��������������������������������������������� + * @tutorial https://www.uviewui.com/components/loading.html + * @property {String | Number} loadingText ������������ (������ '������������' ) + * @property {String} image ������������������������loading��������������� + * @property {String} loadingMode ������������������������circle-���������spinner-������������semicircle-��������� ��������� 'circle' ��� + * @property {Boolean} loading ��������������� ��������� false ��� + * @property {String} bgColor ��������� ��������� '#ffffff' ��� + * @property {String} color ������������ ��������� '#C8C8C8' ��� + * @property {String | Number} fontSize ������������ ��������� 19 ��� + * @property {String | Number} iconSize ������������ ��������� 28 ��� + * @property {String} loadingColor ���������������������������������rgb��������������������������� ��������� '#C8C8C8' ��� + * @property {Object} customStyle ��������������� + * @example <u-loading mode="circle"></u-loading> + */ +export default { + name: "u-loading-page", + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return {}; + }, + methods: {}, +}; +</script> + +<style lang="scss" scoped> +@import "../../libs/css/components.scss"; + +$text-color: rgb(200, 200, 200) !default; +$text-size: 19px !default; +$u-loading-icon-margin-bottom: 10px !default; + +.u-loading-page { + @include flex(column); + flex: 1; + align-items: center; + justify-content: center; + + &__warpper { + margin-top: -150px; + justify-content: center; + align-items: center; + /* #ifndef APP-NVUE */ + color: $text-color; + font-size: $text-size; + /* #endif */ + @include flex(column); + + &__loading-icon { + margin-bottom: $u-loading-icon-margin-bottom; + + &__img { + width: 40px; + height: 40px; + } + } + + &__text { + font-size: $text-size; + color: $text-color; + } + } +} +</style> diff --git a/uni_modules/uview-ui/components/u-loadmore/props.js b/uni_modules/uview-ui/components/u-loadmore/props.js new file mode 100644 index 0000000..1e67d89 --- /dev/null +++ b/uni_modules/uview-ui/components/u-loadmore/props.js @@ -0,0 +1,94 @@ +export default { + props: { + // ���������������loadmore-���������������������loading-���������������������nomore-��������������������� + status: { + type: String, + default: uni.$u.props.loadmore.status + }, + // ��������������� + bgColor: { + type: String, + default: uni.$u.props.loadmore.bgColor + }, + // ������������������������������ + icon: { + type: Boolean, + default: uni.$u.props.loadmore.icon + }, + // ������������ + fontSize: { + type: [String, Number], + default: uni.$u.props.loadmore.fontSize + }, + // ������������ + iconSize: { + type: [String, Number], + default: uni.$u.props.loadmore.iconSize + }, + // ������������ + color: { + type: String, + default: uni.$u.props.loadmore.color + }, + // ���������������������������spinner-������������������circle-������������semicircle-������ + loadingIcon: { + type: String, + default: uni.$u.props.loadmore.loadingIcon + }, + // ��������������������� + loadmoreText: { + type: String, + default: uni.$u.props.loadmore.loadmoreText + }, + // ������������������ + loadingText: { + type: String, + default: uni.$u.props.loadmore.loadingText + }, + // ������������������������ + nomoreText: { + type: String, + default: uni.$u.props.loadmore.nomoreText + }, + // ��������������������������������������������������� + isDot: { + type: Boolean, + default: uni.$u.props.loadmore.isDot + }, + // ������������������������ + iconColor: { + type: String, + default: uni.$u.props.loadmore.iconColor + }, + // ��������� + marginTop: { + type: [String, Number], + default: uni.$u.props.loadmore.marginTop + }, + // ��������� + marginBottom: { + type: [String, Number], + default: uni.$u.props.loadmore.marginBottom + }, + // ���������������px + height: { + type: [String, Number], + default: uni.$u.props.loadmore.height + }, + // ��������������������������� + line: { + type: Boolean, + default: uni.$u.props.loadmore.line + }, + // ������������ + lineColor: { + type: String, + default: uni.$u.props.loadmore.lineColor + }, + // ���������������true-���������false-������ + dashed: { + type: Boolean, + default: uni.$u.props.loadmore.dashed + } + } +} diff --git a/uni_modules/uview-ui/components/u-loadmore/u-loadmore.vue b/uni_modules/uview-ui/components/u-loadmore/u-loadmore.vue new file mode 100644 index 0000000..73c79fe --- /dev/null +++ b/uni_modules/uview-ui/components/u-loadmore/u-loadmore.vue @@ -0,0 +1,150 @@ +<template> + <view + class="u-loadmore" + :style="[ + $u.addStyle(customStyle), + { + backgroundColor: bgColor, + marginBottom: $u.addUnit(marginBottom), + marginTop: $u.addUnit(marginTop), + height: $u.addUnit(height), + }, + ]" + > + <u-line + length="140rpx" + :color="lineColor" + :hairline="false" + :dashed="dashed" + v-if="line" + ></u-line> + <!-- ��������������������������������������������������������� --> + <view + :class="status == 'loadmore' || status == 'nomore' ? 'u-more' : ''" + class="u-loadmore__content" + > + <view + class="u-loadmore__content__icon-wrap" + v-if="status === 'loading' && icon" + > + <u-loading-icon + :color="iconColor" + :size="iconSize" + :mode="loadingIcon" + ></u-loading-icon> + </view> + <!-- ������������������������������������������������dot��������������������������������� --> + <text + class="u-line-1" + :style="[loadTextStyle]" + :class="[(status == 'nomore' && isDot == true) ? 'u-loadmore__content__dot-text' : 'u-loadmore__content__text']" + @tap="loadMore" + >{{ showText }}</text> + </view> + <u-line + length="140rpx" + :color="lineColor" + :hairline="false" + :dashed="dashed" + v-if="line" + ></u-line> + </view> +</template> + +<script> + import props from './props.js'; + + /** + * loadmore ������������ + * @description ������������������������������������������������������������������ + * @tutorial https://www.uviewui.com/components/loadMore.html + * @property {String} status ��������������������� 'loadmore' ��� + * @property {String} bgColor ��������������������������������������������������������������� 'transparent' ��� + * @property {Boolean} icon ��������������������������������������� true ��� + * @property {String | Number} fontSize ��������������������� 14 ��� + * @property {String | Number} iconSize ��������������������� 17 ��� + * @property {String} color ��������������������� '#606266' ��� + * @property {String} loadingIcon ��������������������� 'circle' ��� + * @property {String} loadmoreText ������������������������������ '������������' ��� + * @property {String} loadingText ��������������������������� '������������...' ��� + * @property {String} nomoreText ��������������������������������� '���������������' ��� + * @property {Boolean} isDot ��������������������������������� ��������� false ��� + * @property {String} iconColor ������������������������ ��������� '#b7b7b7' ��� + * @property {String} lineColor ��������������������� #E6E8EB ��� + * @property {String | Number} marginTop ��������� ��������� 10 ��� + * @property {String | Number} marginBottom ��������� ��������� 10 ��� + * @property {String | Number} height ���������������px ��������� 'auto' ��� + * @property {Boolean} line ��������������������������� ��������� false ��� + * @property {Boolean} dashed // ���������������true-���������false-������ ��������� false ��� + * @event {Function} loadmore status���loadmore������������������������������������ + * @example <u-loadmore :status="status" icon-type="iconType" load-text="loadText" /> + */ + export default { + name: "u-loadmore", + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + // ������ + dotText: "���" + } + }, + computed: { + // ������������������������������ + loadTextStyle() { + return { + color: this.color, + fontSize: uni.$u.addUnit(this.fontSize), + lineHeight: uni.$u.addUnit(this.fontSize), + backgroundColor: this.bgColor, + } + }, + // ��������������������� + showText() { + let text = ''; + if (this.status == 'loadmore') text = this.loadmoreText + else if (this.status == 'loading') text = this.loadingText + else if (this.status == 'nomore' && this.isDot) text = this.dotText; + else text = this.nomoreText; + return text; + } + }, + methods: { + loadMore() { + // ������������������������������������������������������������������������������������������������������������������������������������������������ + if (this.status == 'loadmore') this.$emit('loadmore'); + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-loadmore { + @include flex(row); + align-items: center; + justify-content: center; + flex: 1; + + &__content { + margin: 0 15px; + @include flex(row); + align-items: center; + justify-content: center; + + &__icon-wrap { + margin-right: 8px; + } + + &__text { + font-size: 14px; + color: $u-content-color; + } + + &__dot-text { + font-size: 15px; + color: $u-tips-color; + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-modal/props.js b/uni_modules/uview-ui/components/u-modal/props.js new file mode 100644 index 0000000..f76672c --- /dev/null +++ b/uni_modules/uview-ui/components/u-modal/props.js @@ -0,0 +1,84 @@ +export default { + props: { + // ������������modal + show: { + type: Boolean, + default: uni.$u.props.modal.show + }, + // ������ + title: { + type: [String], + default: uni.$u.props.modal.title + }, + // ������������ + content: { + type: String, + default: uni.$u.props.modal.content + }, + // ������������ + confirmText: { + type: String, + default: uni.$u.props.modal.confirmText + }, + // ������������ + cancelText: { + type: String, + default: uni.$u.props.modal.cancelText + }, + // ������������������������ + showConfirmButton: { + type: Boolean, + default: uni.$u.props.modal.showConfirmButton + }, + // ������������������������ + showCancelButton: { + type: Boolean, + default: uni.$u.props.modal.showCancelButton + }, + // ������������������ + confirmColor: { + type: String, + default: uni.$u.props.modal.confirmColor + }, + // ������������������ + cancelColor: { + type: String, + default: uni.$u.props.modal.cancelColor + }, + // ������������������������������ + buttonReverse: { + type: Boolean, + default: uni.$u.props.modal.buttonReverse + }, + // ������������������������ + zoom: { + type: Boolean, + default: uni.$u.props.modal.zoom + }, + // ��������������������������������������������� + asyncClose: { + type: Boolean, + default: uni.$u.props.modal.asyncClose + }, + // ������������������������������modal + closeOnClickOverlay: { + type: Boolean, + default: uni.$u.props.modal.closeOnClickOverlay + }, + // ���������������margin-top������������������������������������������������ + negativeTop: { + type: [String, Number], + default: uni.$u.props.modal.negativeTop + }, + // modal���������������������������������������������px���rpx������ + width: { + type: [String, Number], + default: uni.$u.props.modal.width + }, + // ������������������������circle-���������square-������������������������������������������������ + confirmButtonShape: { + type: String, + default: uni.$u.props.modal.confirmButtonShape + } + } +} diff --git a/uni_modules/uview-ui/components/u-modal/u-modal.vue b/uni_modules/uview-ui/components/u-modal/u-modal.vue new file mode 100644 index 0000000..2cbc737 --- /dev/null +++ b/uni_modules/uview-ui/components/u-modal/u-modal.vue @@ -0,0 +1,227 @@ +<template> + <u-popup + mode="center" + :zoom="zoom" + :show="show" + :customStyle="{ + borderRadius: '6px', + overflow: 'hidden', + marginTop: `-${$u.addUnit(negativeTop)}` + }" + :closeOnClickOverlay="closeOnClickOverlay" + :safeAreaInsetBottom="false" + :duration="400" + @click="clickHandler" + > + <view + class="u-modal" + :style="{ + width: $u.addUnit(width), + }" + > + <text + class="u-modal__title" + v-if="title" + >{{ title }}</text> + <view + class="u-modal__content" + :style="{ + paddingTop: `${title ? 12 : 25}px` + }" + > + <slot> + <text class="u-modal__content__text">{{ content }}</text> + </slot> + </view> + <view + class="u-modal__button-group--confirm-button" + v-if="$slots.confirmButton" + > + <slot name="confirmButton"></slot> + </view> + <template v-else> + <u-line></u-line> + <view + class="u-modal__button-group" + :style="{ + flexDirection: buttonReverse ? 'row-reverse' : 'row' + }" + > + <view + class="u-modal__button-group__wrapper u-modal__button-group__wrapper--cancel" + :hover-stay-time="150" + hover-class="u-modal__button-group__wrapper--hover" + :class="[showCancelButton && !showConfirmButton && 'u-modal__button-group__wrapper--only-cancel']" + v-if="showCancelButton" + @tap="cancelHandler" + > + <text + class="u-modal__button-group__wrapper__text" + :style="{ + color: cancelColor + }" + >{{ cancelText }}</text> + </view> + <u-line + direction="column" + v-if="showConfirmButton && showCancelButton" + ></u-line> + <view + class="u-modal__button-group__wrapper u-modal__button-group__wrapper--confirm" + :hover-stay-time="150" + hover-class="u-modal__button-group__wrapper--hover" + :class="[!showCancelButton && showConfirmButton && 'u-modal__button-group__wrapper--only-confirm']" + v-if="showConfirmButton" + @tap="confirmHandler" + > + <u-loading-icon v-if="loading"></u-loading-icon> + <text + v-else + class="u-modal__button-group__wrapper__text" + :style="{ + color: confirmColor + }" + >{{ confirmText }}</text> + </view> + </view> + </template> + </view> + </u-popup> +</template> + +<script> + import props from './props.js'; + /** + * Modal ��������� + * @description ��������������������������������������������������������������������������������������������������������� + * @tutorial https://www.uviewui.com/components/modul.html + * @property {Boolean} show ������������������������������������show ��������� false ��� + * @property {String} title ������������ + * @property {String} content ���������������������������slot��������������������������� + * @property {String} confirmText ��������������������� ��������� '������' ��� + * @property {String} cancelText ��������������������� ��������� '������' ��� + * @property {Boolean} showConfirmButton ������������������������ ��������� true ��� + * @property {Boolean} showCancelButton ������������������������ ��������� false ��� + * @property {String} confirmColor ��������������������� ��������� '#2979ff' ��� + * @property {String} cancelColor ��������������������� ��������� '#606266' ��� + * @property {Boolean} buttonReverse ������������������������������ ��������� false ��� + * @property {Boolean} zoom ������������������������ ��������� true ��� + * @property {Boolean} asyncClose ��������������������������������������������������������������� ��������� false ��� + * @property {Boolean} closeOnClickOverlay ������������������������������Modal ��������� false ��� + * @property {String | Number} negativeTop ������������������������������������margin-top������������������������������������������������������������������������������������px������ ��������� 0 ��� + * @property {String | Number} width modal���������������������������������������������px���rpx������ ��������� '650rpx' ��� + * @property {String} confirmButtonShape ���������������������,��������������������������������������� + * @event {Function} confirm ��������������������������� + * @event {Function} cancel ��������������������������� + * @event {Function} close ���������������������������closeOnClickOverlay���true������ + * @example <u-modal :show="true" title="title" content="content"></u-modal> + */ + export default { + name: 'u-modal', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + loading: false + } + }, + watch: { + show(n) { + // ���������������������������modal������������������������������loading + // ���������������modal������loading��������������������� + if (n && this.loading) this.loading = false + } + }, + methods: { + // ������������������ + confirmHandler() { + // ���������������������������������������������loading������ + if (this.asyncClose) { + this.loading = true; + } + this.$emit('confirm') + }, + // ������������������ + cancelHandler() { + this.$emit('cancel') + }, + // ������������ + // ���������������������modal��������������������������������������������������� + // ������modal���������popup���������������������������������������������������������������������������������������������������flex������ + // ���������������������������������������������������������������������������������������������������������������������������������popup��������� + // ������������������������������.stop��������������������������������������������������������� + clickHandler() { + if (this.closeOnClickOverlay) { + this.$emit('close') + } + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + $u-modal-border-radius: 6px; + + .u-modal { + width: 650rpx; + border-radius: $u-modal-border-radius; + overflow: hidden; + + &__title { + font-size: 16px; + font-weight: bold; + color: $u-content-color; + text-align: center; + padding-top: 25px; + } + + &__content { + padding: 12px 25px 25px 25px; + @include flex; + justify-content: center; + + &__text { + font-size: 15px; + color: $u-content-color; + flex: 1; + } + } + + &__button-group { + @include flex; + + &--confirm-button { + flex-direction: column; + padding: 0px 25px 15px 25px; + } + + &__wrapper { + flex: 1; + @include flex; + justify-content: center; + align-items: center; + height: 48px; + + &--confirm, + &--only-cancel { + border-bottom-right-radius: $u-modal-border-radius; + } + + &--cancel, + &--only-confirm { + border-bottom-left-radius: $u-modal-border-radius; + } + + &--hover { + background-color: $u-bg-color; + } + + &__text { + color: $u-content-color; + font-size: 16px; + text-align: center; + } + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-navbar/props.js b/uni_modules/uview-ui/components/u-navbar/props.js new file mode 100644 index 0000000..5398de2 --- /dev/null +++ b/uni_modules/uview-ui/components/u-navbar/props.js @@ -0,0 +1,84 @@ +export default { + props: { + // ��������������������������������� + safeAreaInsetTop: { + type: Boolean, + default: uni.$u.props.navbar.safeAreaInsetTop + }, + // ��������������������������������������������������������������������� + placeholder: { + type: Boolean, + default: uni.$u.props.navbar.placeholder + }, + // ��������������������� + fixed: { + type: Boolean, + default: uni.$u.props.navbar.fixed + }, + // ��������������������� + border: { + type: Boolean, + default: uni.$u.props.navbar.border + }, + // ��������������� + leftIcon: { + type: String, + default: uni.$u.props.navbar.leftIcon + }, + // ��������������������� + leftText: { + type: String, + default: uni.$u.props.navbar.leftText + }, + // ��������������������� + rightText: { + type: String, + default: uni.$u.props.navbar.rightText + }, + // ��������������� + rightIcon: { + type: String, + default: uni.$u.props.navbar.rightIcon + }, + // ������ + title: { + type: [String, Number], + default: uni.$u.props.navbar.title + }, + // ������������ + bgColor: { + type: String, + default: uni.$u.props.navbar.bgColor + }, + // ��������������� + titleWidth: { + type: [String, Number], + default: uni.$u.props.navbar.titleWidth + }, + // ��������������� + height: { + type: [String, Number], + default: uni.$u.props.navbar.height + }, + // ��������������������������� + leftIconSize: { + type: [String, Number], + default: uni.$u.props.navbar.leftIconSize + }, + // ��������������������������� + leftIconColor: { + type: String, + default: uni.$u.props.navbar.leftIconColor + }, + // ������������������(������������)������������������������������ + autoBack: { + type: Boolean, + default: uni.$u.props.navbar.autoBack + }, + // ������������������������������������ + titleStyle: { + type: [String, Object], + default: uni.$u.props.navbar.titleStyle + } + } +} diff --git a/uni_modules/uview-ui/components/u-navbar/u-navbar.vue b/uni_modules/uview-ui/components/u-navbar/u-navbar.vue new file mode 100644 index 0000000..2b206b7 --- /dev/null +++ b/uni_modules/uview-ui/components/u-navbar/u-navbar.vue @@ -0,0 +1,186 @@ +<template> + <view class="u-navbar"> + <view + class="u-navbar__placeholder" + v-if="fixed && placeholder" + :style="{ + height: $u.addUnit($u.getPx(height) + $u.sys().statusBarHeight,'px'), + }" + ></view> + <view :class="[fixed && 'u-navbar--fixed']"> + <u-status-bar + v-if="safeAreaInsetTop" + :bgColor="bgColor" + ></u-status-bar> + <view + class="u-navbar__content" + :class="[border && 'u-border-bottom']" + :style="{ + height: $u.addUnit(height), + backgroundColor: bgColor, + }" + > + <view + class="u-navbar__content__left" + hover-class="u-navbar__content__left--hover" + hover-start-time="150" + @tap="leftClick" + > + <slot name="left"> + <u-icon + v-if="leftIcon" + :name="leftIcon" + :size="leftIconSize" + :color="leftIconColor" + ></u-icon> + <text + v-if="leftText" + :style="{ + color: leftIconColor + }" + class="u-navbar__content__left__text" + >{{ leftText }}</text> + </slot> + </view> + <slot name="center"> + <text + class="u-line-1 u-navbar__content__title" + :style="[{ + width: $u.addUnit(titleWidth), + }, $u.addStyle(titleStyle)]" + >{{ title }}</text> + </slot> + <view + class="u-navbar__content__right" + v-if="$slots.right || rightIcon || rightText" + @tap="rightClick" + > + <slot name="right"> + <u-icon + v-if="rightIcon" + :name="rightIcon" + size="20" + ></u-icon> + <text + v-if="rightText" + class="u-navbar__content__right__text" + >{{ rightText }}</text> + </slot> + </view> + </view> + </view> + </view> +</template> + +<script> + import props from './props.js'; + /** + * Navbar ������������������ + * @description ������������������������������������������������������������������������������������������������������uni-app������������������ + * @tutorial https://www.uviewui.com/components/navbar.html + * @property {Boolean} safeAreaInsetTop ��������������������������������� ��������� true ��� + * @property {Boolean} placeholder ��������������������������������������������������������������������� ��������� false ��� + * @property {Boolean} fixed ������������������������������ ��������� false ��� + * @property {Boolean} border ������������������������������������ ��������� false ��� + * @property {String} leftIcon ���������������������������������������uView��������������� ��������� 'arrow-left' ��� + * @property {String} leftText ��������������������� + * @property {String} rightText ��������������������� + * @property {String} rightIcon ���������������������������������������uView��������������� + * @property {String} title ������������������������������������������������������������������������ + * @property {String} bgColor ��������������������� ��������� '#ffffff' ��� + * @property {String | Number} titleWidth ������������������������������������������������������������������ ��������� '400rpx' ��� + * @property {String | Number} height ���������������(���������������������������������������������������)��������� '44px' ��� + * @property {String | Number} leftIconSize ������������������������������������ 20px ��� + * @property {String | Number} leftIconColor ������������������������������������ #303133 ��� + * @property {Boolean} autoBack ������������������(������������)��������������������������������������� false ��� + * @property {Object | String} titleStyle ������������������������������������ + * @event {Function} leftClick ������������������ + * @event {Function} rightClick ������������������ + * @example <u-navbar title="���������������������������������" left-text="������" right-text="������" @click-left="onClickBack" @click-right="onClickRight"></u-navbar> + */ + export default { + name: 'u-navbar', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + + } + }, + methods: { + // ������������������ + leftClick() { + // ���������������autoBack������������������������ + this.$emit('leftClick') + if(this.autoBack) { + uni.navigateBack() + } + }, + // ������������������ + rightClick() { + this.$emit('rightClick') + }, + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-navbar { + + &--fixed { + position: fixed; + left: 0; + right: 0; + top: 0; + z-index: 11; + } + + &__content { + @include flex(row); + align-items: center; + height: 44px; + background-color: #9acafc; + position: relative; + justify-content: center; + + &__left, + &__right { + padding: 0 13px; + position: absolute; + top: 0; + bottom: 0; + @include flex(row); + align-items: center; + } + + &__left { + left: 0; + + &--hover { + opacity: 0.7; + } + + &__text { + font-size: 15px; + margin-left: 3px; + } + } + + &__title { + text-align: center; + font-size: 16px; + color: $u-main-color; + } + + &__right { + right: 0; + + &__text { + font-size: 15px; + margin-left: 3px; + } + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-no-network/props.js b/uni_modules/uview-ui/components/u-no-network/props.js new file mode 100644 index 0000000..9f3af62 --- /dev/null +++ b/uni_modules/uview-ui/components/u-no-network/props.js @@ -0,0 +1,19 @@ +export default { + props: { + // ������������������ + tips: { + type: String, + default: uni.$u.props.noNetwork.tips + }, + // ������z-index������������������������������������������������������������������������������������������������������������������������������������������ + zIndex: { + type: [String, Number], + default: uni.$u.props.noNetwork.zIndex + }, + // image ��������������������������� + image: { + type: String, + default: uni.$u.props.noNetwork.image + } + } +} diff --git a/uni_modules/uview-ui/components/u-no-network/u-no-network.vue b/uni_modules/uview-ui/components/u-no-network/u-no-network.vue new file mode 100644 index 0000000..9710729 --- /dev/null +++ b/uni_modules/uview-ui/components/u-no-network/u-no-network.vue @@ -0,0 +1,220 @@ +<template> + <u-overlay + :show="!isConnected" + :zIndex="zIndex" + @touchmove.stop.prevent="noop" + :customStyle="{ + backgroundColor: '#fff', + display: 'flex', + justifyContent: 'center', + }" + > + <view + class="u-no-network" + > + <u-icon + :name="image" + size="150" + imgMode="widthFit" + class="u-no-network__error-icon" + ></u-icon> + <text class="u-no-network__tips">{{tips}}</text> + <!-- ������APP���������������������������������������������������plus������ --> + <!-- #ifdef APP-PLUS --> + <view class="u-no-network__app"> + <text class="u-no-network__app__setting">���������������������������</text> + <text + class="u-no-network__app__to-setting" + @tap="openSettings" + >������</text> + </view> + <!-- #endif --> + <view class="u-no-network__retry"> + <u-button + size="mini" + text="������" + type="primary" + plain + @click="retry" + ></u-button> + </view> + </view> + </u-overlay> +</template> + +<script> + import props from './props.js'; + + /** + * noNetwork ��������������� + * @description ��������������������������������������������������������������������������������������� + * @tutorial https://www.uviewui.com/components/noNetwork.html + * @property {String} tips ��������������������������� ������������'���������������������������' ��� + * @property {String | Number} zIndex ���������z-index��� + * @property {String} image ������������������������������������src���������base64������ + * @event {Function} retry ���������������������"������"��������������� + * @example <u-no-network></u-no-network> + */ + export default { + name: "u-no-network", + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + isConnected: true, // ��������������������� + networkType: "none", // ������������ + } + }, + mounted() { + this.isIOS = (uni.getSystemInfoSync().platform === 'ios') + uni.onNetworkStatusChange((res) => { + this.isConnected = res.isConnected + this.networkType = res.networkType + this.emitEvent(this.networkType) + }) + uni.getNetworkType({ + success: (res) => { + this.networkType = res.networkType + this.emitEvent(this.networkType) + if (res.networkType == 'none') { + this.isConnected = false + } else { + this.isConnected = true + } + } + }) + }, + methods: { + retry() { + // ������������������ + uni.getNetworkType({ + success: (res) => { + this.networkType = res.networkType + this.emitEvent(this.networkType) + if (res.networkType == 'none') { + uni.$u.toast('���������������') + this.isConnected = false + } else { + uni.$u.toast('���������������') + this.isConnected = true + } + } + }) + this.$emit('retry') + }, + // ������������������������ + emitEvent(networkType) { + this.$emit(networkType === 'none' ? 'disconnected' : 'connected') + }, + async openSettings() { + if (this.networkType == "none") { + this.openSystemSettings() + return + } + }, + openAppSettings() { + this.gotoAppSetting() + }, + openSystemSettings() { + // ������������������5+��������������������������������������������������� + // https://ask.dcloud.net.cn/docs/ + if (this.isIOS) { + this.gotoiOSSetting() + } else { + this.gotoAndroidSetting() + } + }, + network() { + var result = null + var cellularData = plus.ios.newObject("CTCellularData") + var state = cellularData.plusGetAttribute("restrictedState") + if (state == 0) { + result = null + } else if (state == 2) { + result = 1 + } else if (state == 1) { + result = 2 + } + plus.ios.deleteObject(cellularData) + return result + }, + gotoAppSetting() { + if (this.isIOS) { + var UIApplication = plus.ios.import("UIApplication") + var application2 = UIApplication.sharedApplication() + var NSURL2 = plus.ios.import("NSURL") + var setting2 = NSURL2.URLWithString("app-settings:") + application2.openURL(setting2) + plus.ios.deleteObject(setting2) + plus.ios.deleteObject(NSURL2) + plus.ios.deleteObject(application2) + } else { + var Intent = plus.android.importClass("android.content.Intent") + var Settings = plus.android.importClass("android.provider.Settings") + var Uri = plus.android.importClass("android.net.Uri") + var mainActivity = plus.android.runtimeMainActivity() + var intent = new Intent() + intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) + var uri = Uri.fromParts("package", mainActivity.getPackageName(), null) + intent.setData(uri) + mainActivity.startActivity(intent) + } + }, + gotoiOSSetting() { + var UIApplication = plus.ios.import("UIApplication") + var application2 = UIApplication.sharedApplication() + var NSURL2 = plus.ios.import("NSURL") + var setting2 = NSURL2.URLWithString("App-prefs:root=General") + application2.openURL(setting2) + plus.ios.deleteObject(setting2) + plus.ios.deleteObject(NSURL2) + plus.ios.deleteObject(application2) + }, + gotoAndroidSetting() { + var Intent = plus.android.importClass("android.content.Intent") + var Settings = plus.android.importClass("android.provider.Settings") + var mainActivity = plus.android.runtimeMainActivity() + var intent = new Intent(Settings.ACTION_SETTINGS) + mainActivity.startActivity(intent) + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-no-network { + @include flex(column); + justify-content: center; + align-items: center; + margin-top: -100px; + + &__tips { + color: $u-tips-color; + font-size: 14px; + margin-top: 15px; + } + + &__app { + @include flex(row); + margin-top: 6px; + + &__setting { + color: $u-light-color; + font-size: 13px; + } + + &__to-setting { + font-size: 13px; + color: $u-primary; + margin-left: 3px; + } + } + + &__retry { + @include flex(row); + justify-content: center; + margin-top: 15px; + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-notice-bar/props.js b/uni_modules/uview-ui/components/u-notice-bar/props.js new file mode 100644 index 0000000..7040c29 --- /dev/null +++ b/uni_modules/uview-ui/components/u-notice-bar/props.js @@ -0,0 +1,70 @@ +export default { + props: { + // ������������������������ + text: { + type: [Array, String], + default: uni.$u.props.noticeBar.text + }, + // ���������������������row-���������������column-������������ + direction: { + type: String, + default: uni.$u.props.noticeBar.direction + }, + // direction = row������������������������������������ + step: { + type: Boolean, + default: uni.$u.props.noticeBar.step + }, + // ��������������������������������� + icon: { + type: String, + default: uni.$u.props.noticeBar.icon + }, + // ���������������link-������������������closable-������������������������ + mode: { + type: String, + default: uni.$u.props.noticeBar.mode + }, + // ������������������������������������������������ + color: { + type: String, + default: uni.$u.props.noticeBar.color + }, + // ������������ + bgColor: { + type: String, + default: uni.$u.props.noticeBar.bgColor + }, + // ������������������������������������������������������px(px)��������������������������������������������������������������������������� + speed: { + type: [String, Number], + default: uni.$u.props.noticeBar.speed + }, + // ������������ + fontSize: { + type: [String, Number], + default: uni.$u.props.noticeBar.fontSize + }, + // ���������������������������������������ms + duration: { + type: [String, Number], + default: uni.$u.props.noticeBar.duration + }, + // ������������������������������ + // ������HX2.6.11������������App 2.5.5+���H5 2.5.5+��������������������������������������������� + disableTouch: { + type: Boolean, + default: uni.$u.props.noticeBar.disableTouch + }, + // ��������������������� + url: { + type: String, + default: uni.$u.props.noticeBar.url + }, + // ��������������������� + linkType: { + type: String, + default: uni.$u.props.noticeBar.linkType + } + } +} diff --git a/uni_modules/uview-ui/components/u-notice-bar/u-notice-bar.vue b/uni_modules/uview-ui/components/u-notice-bar/u-notice-bar.vue new file mode 100644 index 0000000..a06eb39 --- /dev/null +++ b/uni_modules/uview-ui/components/u-notice-bar/u-notice-bar.vue @@ -0,0 +1,101 @@ +<template> + <view + class="u-notice-bar" + v-if="show" + :style="[{ + backgroundColor: bgColor + }, $u.addStyle(customStyle)]" + > + <template v-if="direction === 'column' || (direction === 'row' && step)"> + <u-column-notice + :color="color" + :bgColor="bgColor" + :text="text" + :mode="mode" + :step="step" + :icon="icon" + :disable-touch="disableTouch" + :fontSize="fontSize" + :duration="duration" + @close="close" + @click="click" + ></u-column-notice> + </template> + <template v-else> + <u-row-notice + :color="color" + :bgColor="bgColor" + :text="text" + :mode="mode" + :fontSize="fontSize" + :speed="speed" + :url="url" + :linkType="linkType" + :icon="icon" + @close="close" + @click="click" + ></u-row-notice> + </template> + </view> +</template> +<script> + import props from './props.js'; + + /** + * noticeBar ������������ + * @description ��������������������������������������������������������������� + * @tutorial https://www.uviewui.com/components/noticeBar.html + * @property {Array | String} text ������������������������ + * @property {String} direction ���������������������row-���������������column-������������ ( ������ 'row' ) + * @property {Boolean} step direction = row������������������������������������ ( ������ false ) + * @property {String} icon ��������������������������������� ( ������ 'volume' ) + * @property {String} mode ���������������link-������������������closable-������������������������ + * @property {String} color ������������������������������������������������ ( ������ '#f9ae3d' ) + * @property {String} bgColor ������������ ( ������ '#fdf6ec' ) + * @property {String | Number} speed ������������������������������������������������������px(px)��������������������������������������������������������������������������� ( ������ 80 ) + * @property {String | Number} fontSize ������������ ( ������ 14 ) + * @property {String | Number} duration ���������������������������������������ms ( ������ 2000 ) + * @property {Boolean} disableTouch ������������������������������ ������HX2.6.11������������App 2.5.5+���H5 2.5.5+������������������������������������������������������34��� ( ������ true ) + * @property {String} url ��������������������� + * @property {String} linkType ��������������������� ( ������ navigateTo ) + * @property {Object} customStyle ��������������������������������� + * + * @event {Function} click ������������������������ + * @event {Function} close ������������������������������ + * @example <u-notice-bar :more-icon="true" :list="list"></u-notice-bar> + */ + export default { + name: "u-notice-bar", + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + show: true + } + }, + methods: { + // ��������������� + click(index) { + this.$emit('click', index) + if (this.url && this.linkType) { + // ���������������mixin���������������������url���linkType������������mixin���props��� + this.openPage() + } + }, + // ������������������ + close() { + this.show = false + this.$emit('close') + } + } + }; +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-notice-bar { + overflow: hidden; + padding: 9px 12px; + flex: 1; + } +</style> diff --git a/uni_modules/uview-ui/components/u-notify/props.js b/uni_modules/uview-ui/components/u-notify/props.js new file mode 100644 index 0000000..57a9d71 --- /dev/null +++ b/uni_modules/uview-ui/components/u-notify/props.js @@ -0,0 +1,49 @@ +export default { + props: { + // ������������������ + top: { + type: [String, Number], + default: uni.$u.props.notify.top + }, + // ������������������ + // show: { + // type: Boolean, + // default: uni.$u.props.notify.show + // }, + // type���������primary���success���warning���error + type: { + type: String, + default: uni.$u.props.notify.type + }, + // ������������ + color: { + type: String, + default: uni.$u.props.notify.color + }, + // ������������ + bgColor: { + type: String, + default: uni.$u.props.notify.bgColor + }, + // ��������������������� + message: { + type: String, + default: uni.$u.props.notify.message + }, + // ������������������0���������������������ms + duration: { + type: [String, Number], + default: uni.$u.props.notify.duration + }, + // ������������ + fontSize: { + type: [String, Number], + default: uni.$u.props.notify.fontSize + }, + // ��������������������������������������������������� + safeAreaInsetTop: { + type: Boolean, + default: uni.$u.props.notify.safeAreaInsetTop + } + } +} diff --git a/uni_modules/uview-ui/components/u-notify/u-notify.vue b/uni_modules/uview-ui/components/u-notify/u-notify.vue new file mode 100644 index 0000000..30adb72 --- /dev/null +++ b/uni_modules/uview-ui/components/u-notify/u-notify.vue @@ -0,0 +1,211 @@ +<template> + <u-transition + mode="slide-down" + :customStyle="containerStyle" + :show="open" + > + <view + class="u-notify" + :class="[`u-notify--${tmpConfig.type}`]" + :style="[backgroundColor, $u.addStyle(customStyle)]" + > + <u-status-bar v-if="tmpConfig.safeAreaInsetTop"></u-status-bar> + <view class="u-notify__warpper"> + <slot name="icon"> + <u-icon + v-if="['success', 'warning', 'error'].includes(tmpConfig.type)" + :name="tmpConfig.icon" + :color="tmpConfig.color" + :size="1.3 * tmpConfig.fontSize" + :customStyle="{marginRight: '4px'}" + ></u-icon> + </slot> + <text + class="u-notify__warpper__text" + :style="{ + fontSize: $u.addUnit(tmpConfig.fontSize), + color: tmpConfig.color + }" + >{{ tmpConfig.message }}</text> + </view> + </view> + </u-transition> +</template> + +<script> + import props from './props.js'; + /** + * notify ������������ + * @description ��������������������������������������������������������������������������������������� + * @tutorial + * @property {String | Number} top ������������������ ( ������ 0 ) + * @property {String} type ���������primary���success���warning���error ( ������ 'primary' ) + * @property {String} color ������������ ( ������ '#ffffff' ) + * @property {String} bgColor ������������ + * @property {String} message ��������������������� + * @property {String | Number} duration ������������������0���������������������ms ( ������ 3000 ) + * @property {String | Number} fontSize ������������ ( ������ 15 ) + * @property {Boolean} safeAreaInsetTop ��������������������������������������������������� ( ������ false ) + * @property {Object} customStyle ������������������������������ + * @event {Function} open ������������������������������ + * @event {Function} close ������������������������������ + * @example <u-notify message="Hi uView"></u-notify> + */ + export default { + name: 'u-notify', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + // ������������������ + open: false, + timer: null, + config: { + // ������������������ + top: uni.$u.props.notify.top, + // type���������primary���success���warning���error + type: uni.$u.props.notify.type, + // ������������ + color: uni.$u.props.notify.color, + // ������������ + bgColor: uni.$u.props.notify.bgColor, + // ��������������������� + message: uni.$u.props.notify.message, + // ������������������0���������������������ms + duration: uni.$u.props.notify.duration, + // ������������ + fontSize: uni.$u.props.notify.fontSize, + // ��������������������������������������������������� + safeAreaInsetTop: uni.$u.props.notify.safeAreaInsetTop + }, + // ��������������������������������������������������������������������������������������������� + tmpConfig: {} + } + }, + computed: { + containerStyle() { + let top = 0 + if (this.tmpConfig.top === 0) { + // #ifdef H5 + // H5������������������������������������������������������������������������������ + // H5���������������������44px + top = 44 + // #endif + } + const style = { + top: uni.$u.addUnit(this.tmpConfig.top === 0 ? top : this.tmpConfig.top), + // ���������������������u-transition������������������������������fixed������ + // ������������������������������ + position: 'fixed', + left: 0, + right: 0, + zIndex: 10076 + } + return style + }, + // ������������������ + backgroundColor() { + const style = {} + if (this.tmpConfig.bgColor) { + style.backgroundColor = this.tmpConfig.bgColor + } + return style + }, + // ������������������������ + icon() { + let icon + if (this.tmpConfig.type === 'success') { + icon = 'checkmark-circle' + } else if (this.tmpConfig.type === 'error') { + icon = 'close-circle' + } else if (this.tmpConfig.type === 'warning') { + icon = 'error-circle' + } + return icon + } + }, + created() { + // ���������������������������toast��������������������������� + ['primary', 'success', 'error', 'warning'].map(item => { + this[item] = message => this.show({ + type: item, + message + }) + }) + }, + methods: { + show(options) { + // ���������������������this.config���������������������������u-toast������������������������������ + this.tmpConfig = uni.$u.deepMerge(this.config, options) + // ��������������������������������������������������������������������������������������� + this.clearTimer() + this.open = true + if (this.tmpConfig.duration > 0) { + this.timer = setTimeout(() => { + this.open = false + // ������������������������������������������toast������ + this.clearTimer() + // ������������������callback������������������������������ + typeof(this.tmpConfig.complete) === 'function' && this.tmpConfig.complete() + }, this.tmpConfig.duration) + } + }, + // ������notify + close() { + this.clearTimer() + }, + clearTimer() { + this.open = false + // ��������������� + clearTimeout(this.timer) + this.timer = null + } + }, + beforeDestroy() { + this.clearTimer() + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + $u-notify-padding: 8px 10px !default; + $u-notify-text-font-size: 15px !default; + $u-notify-primary-bgColor: $u-primary !default; + $u-notify-success-bgColor: $u-success !default; + $u-notify-error-bgColor: $u-error !default; + $u-notify-warning-bgColor: $u-warning !default; + + + .u-notify { + padding: $u-notify-padding; + + &__warpper { + @include flex; + align-items: center; + text-align: center; + justify-content: center; + + &__text { + font-size: $u-notify-text-font-size; + text-align: center; + } + } + + &--primary { + background-color: $u-notify-primary-bgColor; + } + + &--success { + background-color: $u-notify-success-bgColor; + } + + &--error { + background-color: $u-notify-error-bgColor; + } + + &--warning { + background-color: $u-notify-warning-bgColor; + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-number-box/props.js b/uni_modules/uview-ui/components/u-number-box/props.js new file mode 100644 index 0000000..fb0fa94 --- /dev/null +++ b/uni_modules/uview-ui/components/u-number-box/props.js @@ -0,0 +1,109 @@ +export default { + props: { + // ������������������������change������������ + name: { + type: [String, Number], + default: uni.$u.props.numberBox.name + }, + // ���������������������������������������������������������min���(���������) + value: { + type: [String, Number], + default: uni.$u.props.numberBox.value + }, + // ��������� + min: { + type: [String, Number], + default: uni.$u.props.numberBox.min + }, + // ��������� + max: { + type: [String, Number], + default: uni.$u.props.numberBox.max + }, + // ������������������������������ + step: { + type: [String, Number], + default: uni.$u.props.numberBox.step + }, + // ��������������������������� + integer: { + type: Boolean, + default: uni.$u.props.numberBox.integer + }, + // ��������������������������������������������� + disabled: { + type: Boolean, + default: uni.$u.props.numberBox.disabled + }, + // ��������������������� + disabledInput: { + type: Boolean, + default: uni.$u.props.numberBox.disabledInput + }, + // ��������������������������������������������������������������� + asyncChange: { + type: Boolean, + default: uni.$u.props.numberBox.asyncChange + }, + // ���������������������������px + inputWidth: { + type: [String, Number], + default: uni.$u.props.numberBox.inputWidth + }, + // ������������������������ + showMinus: { + type: Boolean, + default: uni.$u.props.numberBox.showMinus + }, + // ������������������������ + showPlus: { + type: Boolean, + default: uni.$u.props.numberBox.showPlus + }, + // ��������������������� + decimalLength: { + type: [String, Number, null], + default: uni.$u.props.numberBox.decimalLength + }, + // ������������������������������ + longPress: { + type: Boolean, + default: uni.$u.props.numberBox.longPress + }, + // ��������������������������������������������� + color: { + type: String, + default: uni.$u.props.numberBox.color + }, + // ������������������������������������������px��������������������������������������� + buttonSize: { + type: [String, Number], + default: uni.$u.props.numberBox.buttonSize + }, + // ��������������������������������� + bgColor: { + type: String, + default: uni.$u.props.numberBox.bgColor + }, + // ���������������������������������������������������������������������px + cursorSpacing: { + type: [String, Number], + default: uni.$u.props.numberBox.cursorSpacing + }, + // ������������������������ + disablePlus: { + type: Boolean, + default: uni.$u.props.numberBox.disablePlus + }, + // ������������������������ + disableMinus: { + type: Boolean, + default: uni.$u.props.numberBox.disableMinus + }, + // ��������������������������� + iconStyle: { + type: [Object, String], + default: uni.$u.props.numberBox.iconStyle + } + } +} diff --git a/uni_modules/uview-ui/components/u-number-box/u-number-box.vue b/uni_modules/uview-ui/components/u-number-box/u-number-box.vue new file mode 100644 index 0000000..69211c5 --- /dev/null +++ b/uni_modules/uview-ui/components/u-number-box/u-number-box.vue @@ -0,0 +1,416 @@ +<template> + <view class="u-number-box"> + <view + class="u-number-box__slot" + @tap.stop="clickHandler('minus')" + @touchstart="onTouchStart('minus')" + @touchend.stop="clearTimeout" + v-if="showMinus && $slots.minus" + > + <slot name="minus" /> + </view> + <view + v-else-if="showMinus" + class="u-number-box__minus" + @tap.stop="clickHandler('minus')" + @touchstart="onTouchStart('minus')" + @touchend.stop="clearTimeout" + hover-class="u-number-box__minus--hover" + hover-stay-time="150" + :class="{ 'u-number-box__minus--disabled': isDisabled('minus') }" + :style="[buttonStyle('minus')]" + > + <u-icon + name="minus" + :color="isDisabled('minus') ? '#c8c9cc' : '#323233'" + size="15" + bold + :customStyle="iconStyle" + ></u-icon> + </view> + + <slot name="input"> + <input + :disabled="disabledInput || disabled" + :cursor-spacing="getCursorSpacing" + :class="{ 'u-number-box__input--disabled': disabled || disabledInput }" + v-model="currentValue" + class="u-number-box__input" + @blur="onBlur" + @focus="onFocus" + @input="onInput" + type="number" + :style="[inputStyle]" + /> + </slot> + <view + class="u-number-box__slot" + @tap.stop="clickHandler('plus')" + @touchstart="onTouchStart('plus')" + @touchend.stop="clearTimeout" + v-if="showPlus && $slots.plus" + > + <slot name="plus" /> + </view> + <view + v-else-if="showPlus" + class="u-number-box__plus" + @tap.stop="clickHandler('plus')" + @touchstart="onTouchStart('plus')" + @touchend.stop="clearTimeout" + hover-class="u-number-box__plus--hover" + hover-stay-time="150" + :class="{ 'u-number-box__minus--disabled': isDisabled('plus') }" + :style="[buttonStyle('plus')]" + > + <u-icon + name="plus" + :color="isDisabled('plus') ? '#c8c9cc' : '#323233'" + size="15" + bold + :customStyle="iconStyle" + ></u-icon> + </view> + </view> +</template> + +<script> + import props from './props.js'; + /** + * numberBox ��������� + * @description ��������������������������������������������������������������� + * @tutorial https://uviewui.com/components/numberBox.html + * @property {String | Number} name ������������������������change������������ + * @property {String | Number} value ���������������������������������������������������������min���(���������) ��������� 0 ��� + * @property {String | Number} min ��������� ��������� 1 ��� + * @property {String | Number} max ��������� ��������� Number.MAX_SAFE_INTEGER ��� + * @property {String | Number} step ������������������������������ ��������� 1 ��� + * @property {Boolean} integer ��������������������������� ��������� false ��� + * @property {Boolean} disabled ��������������������������������������������� ��������� false ��� + * @property {Boolean} disabledInput ��������������������� ��������� false ��� + * @property {Boolean} asyncChange ��������������������������������������������������������������� ��������� false ��� + * @property {String | Number} inputWidth ���������������������������px ��������� 35 ��� + * @property {Boolean} showMinus ������������������������ ��������� true ��� + * @property {Boolean} showPlus ������������������������ ��������� true ��� + * @property {String | Number} decimalLength ��������������������� + * @property {Boolean} longPress ������������������������������ ��������� true ��� + * @property {String} color ��������������������������������������������� ��������� '#323233' ��� + * @property {String | Number} buttonSize ������������������������������������������px��������������������������������������� ��������� 30 ��� + * @property {String} bgColor ��������������������������������� ��������� '#EBECEE' ��� + * @property {String | Number} cursorSpacing ���������������������������������������������������������������������px ��������� 100 ��� + * @property {Boolean} disablePlus ������������������������ ��������� false ��� + * @property {Boolean} disableMinus ������������������������ ��������� false ��� + * @property {Object ��� String} iconStyle ��������������������������� + * + * @event {Function} onFocus ��������������������� + * @event {Function} onBlur ��������������������� + * @event {Function} onInput ������������������������ + * @event {Function} onChange + * @example <u-number-box v-model="value" @change="valChange"></u-number-box> + */ + export default { + name: 'u-number-box', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + // ��������������������������� + currentValue: '', + // ��������� + longPressTimer: null + } + }, + watch: { + // ������������������������������������������������������������������check()������ + watchChange(n) { + this.check() + }, + // ������v-mode��������������������������������������� + value(n) { + if (n !== this.currentValue) { + this.currentValue = this.format(this.value) + } + } + }, + computed: { + getCursorSpacing() { + // ���������������������������������px���������������������px + return uni.$u.getPx(this.cursorSpacing) + }, + // ��������������� + buttonStyle() { + return (type) => { + const style = { + backgroundColor: this.bgColor, + height: uni.$u.addUnit(this.buttonSize), + color: this.color + } + if (this.isDisabled(type)) { + style.backgroundColor = '#f7f8fa' + } + return style + } + }, + // ������������������ + inputStyle() { + const disabled = this.disabled || this.disabledInput + const style = { + color: this.color, + backgroundColor: this.bgColor, + height: uni.$u.addUnit(this.buttonSize), + width: uni.$u.addUnit(this.inputWidth) + } + return style + }, + // ��������������������������������� + watchChange() { + return [this.integer, this.decimalLength, this.min, this.max] + }, + isDisabled() { + return (type) => { + if (type === 'plus') { + // ������������������������������������������������disabled��������������������������������������������������������������������������������� + return ( + this.disabled || + this.disablePlus || + this.currentValue >= this.max + ) + } + // ������������������������ + return ( + this.disabled || + this.disableMinus || + this.currentValue <= this.min + ) + } + }, + }, + mounted() { + this.init() + }, + methods: { + init() { + this.currentValue = this.format(this.value) + }, + // ������������������������������������ + format(value) { + value = this.filter(value) + // ���������������������������������������0���������������������Number������ + value = value === '' ? 0 : +value + // ������������������������������min���max������������ + value = Math.max(Math.min(this.max, value), this.min) + // ���������������������������������������������toFixed������������������ + if (this.decimalLength !== null) { + value = value.toFixed(this.decimalLength) + } + return value + }, + // ��������������������� + filter(value) { + // ���������0-9������������������"."���������������"-"��������������������� + value = String(value).replace(/[^0-9.-]/g, '') + // ��������������������������������������������������������������� + if (this.integer && value.indexOf('.') !== -1) { + value = value.split('.')[0] + } + return value; + }, + check() { + // ������������������������������������������������������������������������������������ + const val = this.format(this.currentValue); + if (val !== this.currentValue) { + this.currentValue = val + } + }, + // ������������������������������������ + // isDisabled(type) { + // if (type === 'plus') { + // // ������������������������������������������������disabled��������������������������������������������������������������������������������� + // return ( + // this.disabled || + // this.disablePlus || + // this.currentValue >= this.max + // ) + // } + // // ������������������������ + // return ( + // this.disabled || + // this.disableMinus || + // this.currentValue <= this.min + // ) + // }, + // ��������������������� + onFocus(event) { + this.$emit('focus', { + ...event.detail, + name: this.name, + }) + }, + // ��������������������� + onBlur(event) { + // ��������������������������� + const value = this.format(event.detail.value) + // ������blur������ + this.$emit( + 'blur',{ + ...event.detail, + name: this.name, + } + ) + }, + // ������������������������ + onInput(e) { + const { + value = '' + } = e.detail || {} + // ������������ + if (value === '') return + let formatted = this.filter(value) + // ��������������������������� + if (this.decimalLength !== null && formatted.indexOf('.') !== -1) { + const pair = formatted.split('.'); + formatted = `${pair[0]}.${pair[1].slice(0, this.decimalLength)}` + } + formatted = this.format(formatted) + this.emitChange(formatted); + }, + // ������change������ + emitChange(value) { + // ���������������������������������������������������������������������������������������������v-model������ + if (!this.asyncChange) { + this.$nextTick(() => { + this.$emit('input', value) + this.currentValue = value + this.$forceUpdate() + }) + } + this.$emit('change', { + value, + name: this.name, + }); + }, + onChange() { + const { + type + } = this + if (this.isDisabled(type)) { + return this.$emit('overlimit', type) + } + const diff = type === 'minus' ? -this.step : +this.step + const value = this.format(this.add(+this.currentValue, diff)) + this.emitChange(value) + this.$emit(type) + }, + // ������������������������������������������������������������������������������������������������������ + add(num1, num2) { + const cardinal = Math.pow(10, 10); + return Math.round((num1 + num2) * cardinal) / cardinal + }, + // ������������������ + clickHandler(type) { + this.type = type + this.onChange() + }, + longPressStep() { + // ���������������������������������longPressStep��������������������������� + this.clearTimeout() + this.longPressTimer = setTimeout(() => { + this.onChange() + this.longPressStep() + }, 250); + }, + onTouchStart(type) { + if (!this.longPress) return + this.clearTimeout() + this.type = type + // ������������������������������������������ + this.longPressTimer = setTimeout(() => { + this.onChange() + this.longPressStep() + }, 600) + }, + // ��������������������������������������������������� + onTouchEnd() { + if (!this.longPress) return + this.clearTimeout() + }, + // ��������������� + clearTimeout() { + clearTimeout(this.longPressTimer) + this.longPressTimer = null + } + } + } +</script> + +<style lang="scss" scoped> + @import '../../libs/css/components.scss'; + + $u-numberBox-hover-bgColor: #E6E6E6 !default; + $u-numberBox-disabled-color: #c8c9cc !default; + $u-numberBox-disabled-bgColor: #f7f8fa !default; + $u-numberBox-plus-radius: 4px !default; + $u-numberBox-minus-radius: 4px !default; + $u-numberBox-input-text-align: center !default; + $u-numberBox-input-font-size: 15px !default; + $u-numberBox-input-padding: 0 !default; + $u-numberBox-input-margin: 0 2px !default; + $u-numberBox-input-disabled-color: #c8c9cc !default; + $u-numberBox-input-disabled-bgColor: #f2f3f5 !default; + + .u-number-box { + @include flex(row); + align-items: center; + + &__slot { + /* #ifndef APP-NVUE */ + touch-action: none; + /* #endif */ + } + + &__plus, + &__minus { + width: 35px; + @include flex; + justify-content: center; + align-items: center; + /* #ifndef APP-NVUE */ + touch-action: none; + /* #endif */ + + &--hover { + background-color: $u-numberBox-hover-bgColor !important; + } + + &--disabled { + color: $u-numberBox-disabled-color; + background-color: $u-numberBox-disabled-bgColor; + } + } + + &__plus { + border-top-right-radius: $u-numberBox-plus-radius; + border-bottom-right-radius: $u-numberBox-plus-radius; + } + + &__minus { + border-top-left-radius: $u-numberBox-minus-radius; + border-bottom-left-radius: $u-numberBox-minus-radius; + } + + &__input { + position: relative; + text-align: $u-numberBox-input-text-align; + font-size: $u-numberBox-input-font-size; + padding: $u-numberBox-input-padding; + margin: $u-numberBox-input-margin; + @include flex; + align-items: center; + justify-content: center; + + &--disabled { + color: $u-numberBox-input-disabled-color; + background-color: $u-numberBox-input-disabled-bgColor; + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-number-keyboard/props.js b/uni_modules/uview-ui/components/u-number-keyboard/props.js new file mode 100644 index 0000000..5e3bf55 --- /dev/null +++ b/uni_modules/uview-ui/components/u-number-keyboard/props.js @@ -0,0 +1,19 @@ +export default { + props: { + // ������������������number-���������������card-��������������� + mode: { + type: String, + default: uni.$u.props.numberKeyboard.value + }, + // ���������������������"."������ + dotDisabled: { + type: Boolean, + default: uni.$u.props.numberKeyboard.dotDisabled + }, + // ��������������������������������� + random: { + type: Boolean, + default: uni.$u.props.numberKeyboard.random + } + } +} diff --git a/uni_modules/uview-ui/components/u-number-keyboard/u-number-keyboard.vue b/uni_modules/uview-ui/components/u-number-keyboard/u-number-keyboard.vue new file mode 100644 index 0000000..4f505c6 --- /dev/null +++ b/uni_modules/uview-ui/components/u-number-keyboard/u-number-keyboard.vue @@ -0,0 +1,196 @@ +<template> + <view + class="u-keyboard" + @touchmove.stop.prevent="noop" + > + <view + class="u-keyboard__button-wrapper" + v-for="(item, index) in numList" + :key="index" + > + <view + class="u-keyboard__button-wrapper__button" + :style="[itemStyle(index)]" + @tap="keyboardClick(item)" + hover-class="u-hover-class" + :hover-stay-time="200" + > + <text class="u-keyboard__button-wrapper__button__text">{{ item }}</text> + </view> + </view> + <view + class="u-keyboard__button-wrapper" + > + <view + class="u-keyboard__button-wrapper__button u-keyboard__button-wrapper__button--gray" + hover-class="u-hover-class" + :hover-stay-time="200" + @touchstart.stop="backspaceClick" + @touchend="clearTimer" + > + <u-icon + name="backspace" + color="#303133" + size="28" + ></u-icon> + </view> + </view> + </view> +</template> + +<script> + import props from './props.js'; + + /** + * keyboard ������������ + * @description + * @tutorial + * @property {String} mode ������������������number-���������������card-��������������� + * @property {Boolean} dotDisabled ���������������������"."������ + * @property {Boolean} random ��������������������������������� + * @event {Function} change ������������������ + * @event {Function} backspace ��������������������� + * @example + */ + export default { + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + backspace: 'backspace', // ��������������� + dot: '.', // ��� + timer: null, // ��������������������������������� + cardX: 'X' // ������������X������ + }; + }, + computed: { + // ��������������������������� + numList() { + let tmp = []; + if (this.dotDisabled && this.mode == 'number') { + if (!this.random) { + return [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; + } else { + return uni.$u.randomArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); + } + } else if (!this.dotDisabled && this.mode == 'number') { + if (!this.random) { + return [1, 2, 3, 4, 5, 6, 7, 8, 9, this.dot, 0]; + } else { + return uni.$u.randomArray([1, 2, 3, 4, 5, 6, 7, 8, 9, this.dot, 0]); + } + } else if (this.mode == 'card') { + if (!this.random) { + return [1, 2, 3, 4, 5, 6, 7, 8, 9, this.cardX, 0]; + } else { + return uni.$u.randomArray([1, 2, 3, 4, 5, 6, 7, 8, 9, this.cardX, 0]); + } + } + }, + // ������������������������������&&������������&&������������������������index���9������������������������������ + itemStyle() { + return index => { + let style = {}; + if (this.mode == 'number' && this.dotDisabled && index == 9) style.width = '464rpx'; + return style; + }; + }, + // ���������������������������������������������&&������������&&��������������������������� + btnBgGray() { + return index => { + if (!this.random && index == 9 && (this.mode != 'number' || (this.mode == 'number' && !this + .dotDisabled))) return true; + else return false; + }; + }, + }, + created() { + + }, + methods: { + // ��������������� + backspaceClick() { + this.$emit('backspace'); + clearInterval(this.timer); //��������������������������������������������������� + this.timer = null; + this.timer = setInterval(() => { + this.$emit('backspace'); + }, 250); + }, + clearTimer() { + clearInterval(this.timer); + this.timer = null; + }, + // ��������������������������� + keyboardClick(val) { + // ��������������������������������������������������������������������������������� + if (!this.dotDisabled && val != this.dot && val != this.cardX) val = Number(val); + this.$emit('change', val); + } + } + }; +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + $u-number-keyboard-background-color:rgb(224, 228, 230) !default; + $u-number-keyboard-padding:8px 10rpx 8px 10rpx !default; + $u-number-keyboard-button-width:222rpx !default; + $u-number-keyboard-button-margin:4px 6rpx !default; + $u-number-keyboard-button-border-top-left-radius:4px !default; + $u-number-keyboard-button-border-top-right-radius:4px !default; + $u-number-keyboard-button-border-bottom-left-radius:4px !default; + $u-number-keyboard-button-border-bottom-right-radius:4px !default; + $u-number-keyboard-button-height: 90rpx!default; + $u-number-keyboard-button-background-color:#FFFFFF !default; + $u-number-keyboard-button-box-shadow:0 2px 0px #BBBCBE !default; + $u-number-keyboard-text-font-size:20px !default; + $u-number-keyboard-text-font-weight:500 !default; + $u-number-keyboard-text-color:$u-main-color !default; + $u-number-keyboard-gray-background-color:rgb(200, 202, 210) !default; + $u-number-keyboard-u-hover-class-background-color: #BBBCC6 !default; + + .u-keyboard { + @include flex; + flex-direction: row; + justify-content: space-around; + background-color: $u-number-keyboard-background-color; + flex-wrap: wrap; + padding: $u-number-keyboard-padding; + + &__button-wrapper { + box-shadow: $u-number-keyboard-button-box-shadow; + margin: $u-number-keyboard-button-margin; + border-top-left-radius: $u-number-keyboard-button-border-top-left-radius; + border-top-right-radius: $u-number-keyboard-button-border-top-right-radius; + border-bottom-left-radius: $u-number-keyboard-button-border-bottom-left-radius; + border-bottom-right-radius: $u-number-keyboard-button-border-bottom-right-radius; + + &__button { + width: $u-number-keyboard-button-width; + height: $u-number-keyboard-button-height; + background-color: $u-number-keyboard-button-background-color; + @include flex; + justify-content: center; + align-items: center; + border-top-left-radius: $u-number-keyboard-button-border-top-left-radius; + border-top-right-radius: $u-number-keyboard-button-border-top-right-radius; + border-bottom-left-radius: $u-number-keyboard-button-border-bottom-left-radius; + border-bottom-right-radius: $u-number-keyboard-button-border-bottom-right-radius; + + &__text { + font-size: $u-number-keyboard-text-font-size; + font-weight: $u-number-keyboard-text-font-weight; + color: $u-number-keyboard-text-color; + } + + &--gray { + background-color: $u-number-keyboard-gray-background-color; + } + } + } + } + + .u-hover-class { + background-color: $u-number-keyboard-u-hover-class-background-color; + } +</style> diff --git a/uni_modules/uview-ui/components/u-overlay/props.js b/uni_modules/uview-ui/components/u-overlay/props.js new file mode 100644 index 0000000..e6974df --- /dev/null +++ b/uni_modules/uview-ui/components/u-overlay/props.js @@ -0,0 +1,24 @@ +export default { + props: { + // ������������������ + show: { + type: Boolean, + default: uni.$u.props.overlay.show + }, + // ������z-index + zIndex: { + type: [String, Number], + default: uni.$u.props.overlay.zIndex + }, + // ���������������������������������ms + duration: { + type: [String, Number], + default: uni.$u.props.overlay.duration + }, + // ������������������������rgba������������������ + opacity: { + type: [String, Number], + default: uni.$u.props.overlay.opacity + } + } +} diff --git a/uni_modules/uview-ui/components/u-overlay/u-overlay.vue b/uni_modules/uview-ui/components/u-overlay/u-overlay.vue new file mode 100644 index 0000000..92de4e9 --- /dev/null +++ b/uni_modules/uview-ui/components/u-overlay/u-overlay.vue @@ -0,0 +1,68 @@ +<template> + <u-transition + :show="show" + custom-class="u-overlay" + :duration="duration" + :custom-style="overlayStyle" + @click="clickHandler" + > + <slot /> + </u-transition> +</template> + +<script> + import props from './props.js'; + + /** + * overlay ������ + * @description ������������������������������������������������������������������������������������������������������������������������������������������ + * @tutorial https://www.uviewui.com/components/overlay.html + * @property {Boolean} show ��������������������������� false ��� + * @property {String | Number} zIndex zIndex ��������������� 10070 ��� + * @property {String | Number} duration ������������������������������������ 300 ��� + * @property {String | Number} opacity ������������������������rgba������������������ ��������� 0.5 ��� + * @property {Object} customStyle ��������������������������������� + * @event {Function} click ������������������������ + * @example <u-overlay :show="show" @click="show = false"></u-overlay> + */ + export default { + name: "u-overlay", + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + computed: { + overlayStyle() { + const style = { + position: 'fixed', + top: 0, + left: 0, + right: 0, + zIndex: this.zIndex, + bottom: 0, + 'background-color': `rgba(0, 0, 0, ${this.opacity})` + } + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) + } + }, + methods: { + clickHandler() { + this.$emit('click') + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + $u-overlay-top:0 !default; + $u-overlay-left:0 !default; + $u-overlay-width:100% !default; + $u-overlay-height:100% !default; + $u-overlay-background-color:rgba(0, 0, 0, .7) !default; + .u-overlay { + position: fixed; + top:$u-overlay-top; + left:$u-overlay-left; + width: $u-overlay-width; + height:$u-overlay-height; + background-color:$u-overlay-background-color; + } +</style> diff --git a/uni_modules/uview-ui/components/u-parse/node/node.vue b/uni_modules/uview-ui/components/u-parse/node/node.vue new file mode 100644 index 0000000..73e30fd --- /dev/null +++ b/uni_modules/uview-ui/components/u-parse/node/node.vue @@ -0,0 +1,499 @@ +<template> + <view :id="attrs.id" :class="'_'+name+' '+attrs.class" :style="attrs.style"> + <block v-for="(n, i) in childs" v-bind:key="i"> + <!-- ������ --> + <!-- ��������� --> + <image v-if="n.name=='img'&&((opts[1]&&!ctrl[i])||ctrl[i]<0)" class="_img" :style="n.attrs.style" :src="ctrl[i]<0?opts[2]:opts[1]" mode="widthFix" /> + <!-- ������������ --> + <!-- #ifdef H5 || APP-PLUS --> + <img v-if="n.name=='img'" :id="n.attrs.id" :class="'_img '+n.attrs.class" :style="(ctrl[i]==-1?'display:none;':'')+n.attrs.style" :src="n.attrs.src||(ctrl.load?n.attrs['data-src']:'')" :data-i="i" @load="imgLoad" @error="mediaError" @tap.stop="imgTap" @longpress="imgLongTap"/> + <!-- #endif --> + <!-- #ifndef H5 || APP-PLUS --> + <image v-if="n.name=='img'" :id="n.attrs.id" :class="'_img '+n.attrs.class" :style="(ctrl[i]==-1?'display:none;':'')+'width:'+(ctrl[i]||1)+'px;height:1px;'+n.attrs.style" :src="n.attrs.src" :mode="n.h?'':'widthFix'" :lazy-load="opts[0]" :webp="n.webp" :show-menu-by-longpress="opts[3]&&!n.attrs.ignore" :image-menu-prevent="!opts[3]||n.attrs.ignore" :data-i="i" @load="imgLoad" @error="mediaError" @tap.stop="imgTap" @longpress="imgLongTap" /> + <!-- #endif --> + <!-- ������ --> + <!-- #ifndef MP-BAIDU --> + <text v-else-if="n.type=='text'" decode>{{n.text}}</text> + <!-- #endif --> + <text v-else-if="n.name=='br'">\n</text> + <!-- ������ --> + <view v-else-if="n.name=='a'" :id="n.attrs.id" :class="(n.attrs.href?'_a ':'')+n.attrs.class" hover-class="_hover" :style="'display:inline;'+n.attrs.style" :data-i="i" @tap.stop="linkTap"> + <node name="span" :childs="n.children" :opts="opts" style="display:inherit" /> + </view> + <!-- ������ --> + <!-- #ifdef APP-PLUS --> + <view v-else-if="n.html" :id="n.attrs.id" :class="'_video '+n.attrs.class" :style="n.attrs.style" v-html="n.html" /> + <!-- #endif --> + <!-- #ifndef APP-PLUS --> + <video v-else-if="n.name=='video'" :id="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style" :autoplay="n.attrs.autoplay" :controls="n.attrs.controls" :loop="n.attrs.loop" :muted="n.attrs.muted" :poster="n.attrs.poster" :src="n.src[ctrl[i]||0]" :data-i="i" @play="play" @error="mediaError" /> + <!-- #endif --> + <!-- #ifdef H5 || APP-PLUS --> + <iframe v-else-if="n.name=='iframe'" :style="n.attrs.style" :allowfullscreen="n.attrs.allowfullscreen" :frameborder="n.attrs.frameborder" :src="n.attrs.src" /> + <embed v-else-if="n.name=='embed'" :style="n.attrs.style" :src="n.attrs.src" /> + <!-- #endif --> + <!-- #ifndef MP-TOUTIAO --> + <!-- ������ --> + <audio v-else-if="n.name=='audio'" :id="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style" :author="n.attrs.author" :controls="n.attrs.controls" :loop="n.attrs.loop" :name="n.attrs.name" :poster="n.attrs.poster" :src="n.src[ctrl[i]||0]" :data-i="i" @play="play" @error="mediaError" /> + <!-- #endif --> + <view v-else-if="(n.name=='table'&&n.c)||n.name=='li'" :id="n.attrs.id" :class="'_'+n.name+' '+n.attrs.class" :style="n.attrs.style"> + <node v-if="n.name=='li'" :childs="n.children" :opts="opts" /> + <view v-else v-for="(tbody, x) in n.children" v-bind:key="x" :class="'_'+tbody.name+' '+tbody.attrs.class" :style="tbody.attrs.style"> + <node v-if="tbody.name=='td'||tbody.name=='th'" :childs="tbody.children" :opts="opts" /> + <block v-else v-for="(tr, y) in tbody.children" v-bind:key="y"> + <view v-if="tr.name=='td'||tr.name=='th'" :class="'_'+tr.name+' '+tr.attrs.class" :style="tr.attrs.style"> + <node :childs="tr.children" :opts="opts" /> + </view> + <view v-else :class="'_'+tr.name+' '+tr.attrs.class" :style="tr.attrs.style"> + <view v-for="(td, z) in tr.children" v-bind:key="z" :class="'_'+td.name+' '+td.attrs.class" :style="td.attrs.style"> + <node :childs="td.children" :opts="opts" /> + </view> + </view> + </block> + </view> + </view> + + <!-- ��������� --> + <!-- #ifdef H5 || MP-WEIXIN || MP-QQ || APP-PLUS || MP-360 --> + <rich-text v-else-if="handler.use(n)" :id="n.attrs.id" :style="n.f" :nodes="[n]" /> + <!-- #endif --> + <!-- #ifndef H5 || MP-WEIXIN || MP-QQ || APP-PLUS || MP-360 --> + <rich-text v-else-if="!n.c" :id="n.attrs.id" :style="n.f+';display:inline'" :preview="false" :nodes="[n]" /> + <!-- #endif --> + <!-- ������������ --> + <view v-else-if="n.c==2" :id="n.attrs.id" :class="'_'+n.name+' '+n.attrs.class" :style="n.f+';'+n.attrs.style"> + <node v-for="(n2, j) in n.children" v-bind:key="j" :style="n2.f" :name="n2.name" :attrs="n2.attrs" :childs="n2.children" :opts="opts" /> + </view> + <node v-else :style="n.f" :name="n.name" :attrs="n.attrs" :childs="n.children" :opts="opts" /> + </block> + </view> +</template> +<script module="handler" lang="wxs"> +// ������������������ +var inlineTags = { + abbr: true, + b: true, + big: true, + code: true, + del: true, + em: true, + i: true, + ins: true, + label: true, + q: true, + small: true, + span: true, + strong: true, + sub: true, + sup: true +} +/** + * @description ������������ rich-text ������������������ + */ +module.exports = { + use: function (item) { + // ��������� QQ ��� rich-text inline ������������ + if (inlineTags[item.name] || (item.attrs.style || '').indexOf('display:inline') != -1) + return false + return !item.c + } +} +</script> +<script> + +import node from './node' +export default { + name: 'node', + // #ifdef MP-WEIXIN + options: { + virtualHost: true + }, + // #endif + data() { + return { + ctrl: {} + } + }, + props: { + name: String, + attrs: { + type: Object, + default() { + return {} + } + }, + childs: Array, + opts: Array + }, + components: { + + node + }, + mounted() { + for (this.root = this.$parent; this.root.$options.name != 'mp-html'; this.root = this.root.$parent); + // #ifdef H5 || APP-PLUS + if (this.opts[0]) { + for (var i = this.childs.length; i--;) + if (this.childs[i].name == 'img') + break + if (i != -1) { + this.observer = uni.createIntersectionObserver(this).relativeToViewport({ + top: 500, + bottom: 500 + }) + this.observer.observe('._img', res => { + if (res.intersectionRatio) { + this.$set(this.ctrl, 'load', 1) + this.observer.disconnect() + } + }) + } + } + // #endif + }, + beforeDestroy() { + // #ifdef H5 || APP-PLUS + if (this.observer) + this.observer.disconnect() + // #endif + }, + methods:{ + // #ifdef MP-WEIXIN + toJSON() { }, + // #endif + /** + * @description ������������������ + * @param {Event} e + */ + play(e) { + // #ifndef APP-PLUS + if (this.root.pauseVideo) { + var flag = false, id = e.target.id + for (var i = this.root._videos.length; i--;) { + if (this.root._videos[i].id == id) + flag = true + else + this.root._videos[i].pause() // ������������������������ + } + // ��������������������� + if (!flag) { + var ctx = uni.createVideoContext(id + // #ifndef MP-BAIDU + , this + // #endif + ) + ctx.id = id + this.root._videos.push(ctx) + } + } + // #endif + }, + + /** + * @description ������������������ + * @param {Event} e + */ + imgTap(e) { + var node = this.childs[e.currentTarget.dataset.i] + if (node.a) + return this.linkTap(node.a) + if (node.attrs.ignore) + return + // #ifdef H5 || APP-PLUS + node.attrs.src = node.attrs.src || node.attrs['data-src'] + // #endif + this.root.$emit('imgTap', node.attrs) + // ������������������ + if (this.root.previewImg) + uni.previewImage({ + current: parseInt(node.attrs.i), + urls: this.root.imgList + }) + }, + + /** + * @description ������������ + */ + imgLongTap(e) { + // #ifdef APP-PLUS + var attrs = this.childs[e.currentTarget.dataset.i].attrs + if (!attrs.ignore) + uni.showActionSheet({ + itemList: ['������������'], + success: () => { + uni.downloadFile({ + url: this.root.imgList[attrs.i], + success: res => { + uni.saveImageToPhotosAlbum({ + filePath: res.tempFilePath, + success() { + uni.showToast({ + title: '������������' + }) + } + }) + } + }) + } + }) + // #endif + }, + + /** + * @description ������������������������ + * @param {Event} e + */ + imgLoad(e) { + var i = e.currentTarget.dataset.i + // #ifndef H5 || APP-PLUS + // ��������������� + if (!this.childs[i].w) + this.$set(this.ctrl, i, e.detail.width) + else + // #endif + // ��������������������������������������� + if ((this.opts[1] && !this.ctrl[i]) || this.ctrl[i] == -1) + this.$set(this.ctrl, i, 1) + }, + + /** + * @description ������������������ + * @param {Event} e + */ + linkTap(e) { + var attrs = e.currentTarget ? this.childs[e.currentTarget.dataset.i].attrs : e, + href = attrs.href + this.root.$emit('linkTap', attrs) + if (href) { + // ������������ + if (href[0] == '#') + this.root.navigateTo(href.substring(1)).catch(() => { }) + // ������������������ + else if (href.includes('://')) { + if (this.root.copyLink) { + // #ifdef H5 + window.open(href) + // #endif + // #ifdef MP + uni.setClipboardData({ + data: href, + success: () => + uni.showToast({ + title: '���������������' + }) + }) + // #endif + // #ifdef APP-PLUS + plus.runtime.openWeb(href) + // #endif + } + } + // ������������ + else + uni.navigateTo({ + url: href, + fail() { + uni.switchTab({ + url: href, + fail() { } + }) + } + }) + } + }, + + /** + * @description ������������ + * @param {Event} e + */ + mediaError(e) { + var i = e.currentTarget.dataset.i, + node = this.childs[i] + // ��������������� + if (node.name == 'video' || node.name == 'audio') { + var index = (this.ctrl[i] || 0) + 1 + if (index > node.src.length) + index = 0 + if (index < node.src.length) + return this.$set(this.ctrl, i, index) + } + // ��������������������� + else if (node.name == 'img' && this.opts[2]) + this.$set(this.ctrl, i, -1) + if (this.root) + this.root.$emit('error', { + source: node.name, + attrs: node.attrs, + errMsg: e.detail.errMsg + }) + } + } +} +</script> +<style> +/* a ������������������ */ +._a { + padding: 1.5px 0 1.5px 0; + color: #366092; + word-break: break-all; +} + +/* a ��������������������� */ +._hover { + text-decoration: underline; + opacity: 0.7; +} + +/* ������������������ */ +._img { + max-width: 100%; + -webkit-touch-callout: none; +} + +/* ������������ */ + +._b, +._strong { + font-weight: bold; +} + +._code { + font-family: monospace; +} + +._del { + text-decoration: line-through; +} + +._em, +._i { + font-style: italic; +} + +._h1 { + font-size: 2em; +} + +._h2 { + font-size: 1.5em; +} + +._h3 { + font-size: 1.17em; +} + +._h5 { + font-size: 0.83em; +} + +._h6 { + font-size: 0.67em; +} + +._h1, +._h2, +._h3, +._h4, +._h5, +._h6 { + display: block; + font-weight: bold; +} + +._image { + height: 1px; +} + +._ins { + text-decoration: underline; +} + +._li { + display: list-item; +} + +._ol { + list-style-type: decimal; +} + +._ol, +._ul { + display: block; + padding-left: 40px; + margin: 1em 0; +} + +._q::before { + content: '"'; +} + +._q::after { + content: '"'; +} + +._sub { + font-size: smaller; + vertical-align: sub; +} + +._sup { + font-size: smaller; + vertical-align: super; +} + +._thead, +._tbody, +._tfoot { + display: table-row-group; +} + +._tr { + display: table-row; +} + +._td, +._th { + display: table-cell; + vertical-align: middle; +} + +._th { + font-weight: bold; + text-align: center; +} + +._ul { + list-style-type: disc; +} + +._ul ._ul { + margin: 0; + list-style-type: circle; +} + +._ul ._ul ._ul { + list-style-type: square; +} + +._abbr, +._b, +._code, +._del, +._em, +._i, +._ins, +._label, +._q, +._span, +._strong, +._sub, +._sup { + display: inline; +} + +/* #ifdef APP-PLUS */ +._video { + width: 300px; + height: 225px; +} +/* #endif */ +</style> diff --git a/uni_modules/uview-ui/components/u-parse/parser.js b/uni_modules/uview-ui/components/u-parse/parser.js new file mode 100644 index 0000000..a78a654 --- /dev/null +++ b/uni_modules/uview-ui/components/u-parse/parser.js @@ -0,0 +1,1075 @@ +'use strict' + +/** + * @fileoverview html ��������� + */ +// ������ +const config = { + // ������������������������������������������ + trustTags: makeMap('a,abbr,ad,audio,b,blockquote,br,code,col,colgroup,dd,del,dl,dt,div,em,fieldset,h1,h2,h3,h4,h5,h6,hr,i,img,ins,label,legend,li,ol,p,q,ruby,rt,source,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,title,ul,video'), + // ��������������������� div��������������������������������� span��� + blockTags: makeMap('address,article,aside,body,caption,center,cite,footer,header,html,nav,pre,section'), + // ������������������ + ignoreTags: makeMap('area,base,canvas,embed,frame,head,iframe,input,link,map,meta,param,rp,script,source,style,textarea,title,track,wbr'), + // ������������������ + voidTags: makeMap('area,base,br,col,circle,ellipse,embed,frame,hr,img,input,line,link,meta,param,path,polygon,rect,source,track,use,wbr'), + // html ������ + entities: { + lt: '<', + gt: '>', + quot: '"', + apos: "'", + ensp: '\u2002', + emsp: '\u2003', + nbsp: '\xA0', + semi: ';', + ndash: '���', + mdash: '���', + middot: '��', + lsquo: '���', + rsquo: '���', + ldquo: '���', + rdquo: '���', + bull: '���', + hellip: '���' + }, + // ��������������������� + tagStyle: { + // #ifndef APP-PLUS-NVUE + address: 'font-style:italic', + big: 'display:inline;font-size:1.2em', + caption: 'display:table-caption;text-align:center', + center: 'text-align:center', + cite: 'font-style:italic', + dd: 'margin-left:40px', + mark: 'background-color:yellow', + pre: 'font-family:monospace;white-space:pre', + s: 'text-decoration:line-through', + small: 'display:inline;font-size:0.8em', + u: 'text-decoration:underline' // #endif + + } +} +const { windowWidth } = uni.getSystemInfoSync() +const blankChar = makeMap(' ,\r,\n,\t,\f') +let idIndex = 0 // #ifdef H5 || APP-PLUS + +config.ignoreTags.iframe = void 0 +config.trustTags.iframe = true +config.ignoreTags.embed = void 0 +config.trustTags.embed = true // #endif +// #ifdef APP-PLUS-NVUE + +config.ignoreTags.source = void 0 +config.ignoreTags.style = void 0 // #endif + +/** + * @description ������ map + * @param {String} str ������������ + */ + +function makeMap(str) { + const map = Object.create(null) + const list = str.split(',') + + for (let i = list.length; i--;) { + map[list[i]] = true + } + + return map +} +/** + * @description ������ html ������ + * @param {String} str ��������������������� + * @param {Boolean} amp ��������������� & + * @returns {String} ��������������������� + */ + +function decodeEntity(str, amp) { + let i = str.indexOf('&') + + while (i != -1) { + const j = str.indexOf(';', i + 3) + let code = void 0 + if (j == -1) break + + if (str[i + 1] == '#') { + // { ��������������� + code = parseInt((str[i + 2] == 'x' ? '0' : '') + str.substring(i + 2, j)) + if (!isNaN(code)) str = str.substr(0, i) + String.fromCharCode(code) + str.substr(j + 1) + } else { + // ��������������� + code = str.substring(i + 1, j) + if (config.entities[code] || code == 'amp' && amp) str = str.substr(0, i) + (config.entities[code] || '&') + str.substr(j + 1) + } + + i = str.indexOf('&', i + 1) + } + + return str +} +/** + * @description html ��������� + * @param {Object} vm ������������ + */ + +function parser(vm) { + this.options = vm || {} + this.tagStyle = Object.assign(config.tagStyle, this.options.tagStyle) + this.imgList = vm.imgList || [] + this.plugins = vm.plugins || [] + this.attrs = Object.create(null) + this.stack = [] + this.nodes = [] +} +/** + * @description ������������ + * @param {String} content ������������������ + */ + +parser.prototype.parse = function (content) { + // ������������ + for (let i = this.plugins.length; i--;) { + if (this.plugins[i].onUpdate) content = this.plugins[i].onUpdate(content, config) || content + } + + new lexer(this).parse(content) // ������������������������ + + while (this.stack.length) { + this.popNode() + } + + return this.nodes +} +/** + * @description ������������������������������ rich-text ��������� + */ + +parser.prototype.expose = function () { + // #ifndef APP-PLUS-NVUE + for (let i = this.stack.length; i--;) { + const item = this.stack[i] + if (item.name == 'a' || item.c) return + item.c = 1 + } // #endif +} +/** + * @description ������������ + * @param {Object} node ������������������ + * @returns {Boolean} ������������������������ + */ + +parser.prototype.hook = function (node) { + for (let i = this.plugins.length; i--;) { + if (this.plugins[i].onParse && this.plugins[i].onParse(node, this) == false) return false + } + + return true +} +/** + * @description ��������������������������� + * @param {String} url ��������������������� + * @returns {String} ������������������ + */ + +parser.prototype.getUrl = function (url) { + const { domain } = this.options + + if (url[0] == '/') { + // // ������������������������ + if (url[1] == '/') url = `${domain ? domain.split('://')[0] : 'http'}:${url}` // ������������������������ + else if (domain) url = domain + url + } else if (domain && !url.includes('data:') && !url.includes('://')) url = `${domain}/${url}` + + return url +} +/** + * @description ��������������� + * @param {Object} node ������ + * @returns {Object} + */ + +parser.prototype.parseStyle = function (node) { + const { attrs } = node + const list = (this.tagStyle[node.name] || '').split(';').concat((attrs.style || '').split(';')) + const styleObj = {} + let tmp = '' + + if (attrs.id) { + // ������������ + if (this.options.useAnchor) this.expose(); else if (node.name != 'img' && node.name != 'a' && node.name != 'video' && node.name != 'audio') attrs.id = void 0 + } // ������ width ��� height ������ + + if (attrs.width) { + styleObj.width = parseFloat(attrs.width) + (attrs.width.includes('%') ? '%' : 'px') + attrs.width = void 0 + } + + if (attrs.height) { + styleObj.height = parseFloat(attrs.height) + (attrs.height.includes('%') ? '%' : 'px') + attrs.height = void 0 + } + + for (let i = 0, len = list.length; i < len; i++) { + const info = list[i].split(':') + if (info.length < 2) continue + const key = info.shift().trim().toLowerCase() + let value = info.join(':').trim() // ������������ css ��������� + + if (value[0] == '-' && value.lastIndexOf('-') > 0 || value.includes('safe')) tmp += ';'.concat(key, ':').concat(value) // ��������������������������� + else if (!styleObj[key] || value.includes('import') || !styleObj[key].includes('import')) { + // ������������ + if (value.includes('url')) { + let j = value.indexOf('(') + 1 + + if (j) { + while (value[j] == '"' || value[j] == "'" || blankChar[value[j]]) { + j++ + } + + value = value.substr(0, j) + this.getUrl(value.substr(j)) + } + } // ������ rpx���rich-text ��������������� rpx��� + else if (value.includes('rpx')) { + value = value.replace(/[0-9.]+\s*rpx/g, ($) => `${parseFloat($) * windowWidth / 750}px`) + } + + styleObj[key] = value + } + } + + node.attrs.style = tmp + return styleObj +} +/** + * @description ������������������ + * @param {String} name ��������� + * @private + */ + +parser.prototype.onTagName = function (name) { + this.tagName = this.xml ? name : name.toLowerCase() + if (this.tagName == 'svg') this.xml = true // svg ������������������������ +} +/** + * @description ������������������ + * @param {String} name ��������� + * @private + */ + +parser.prototype.onAttrName = function (name) { + name = this.xml ? name : name.toLowerCase() + + if (name.substr(0, 5) == 'data-') { + // data-src ������������ src + if (name == 'data-src' && !this.attrs.src) this.attrName = 'src' // a ��� img ������������ data- ��������������������� imgtap ��� linktap ��������������� + else if (this.tagName == 'img' || this.tagName == 'a') this.attrName = name // ������������������������������ + else this.attrName = void 0 + } else { + this.attrName = name + this.attrs[name] = 'T' // boolean ��������������������� + } +} +/** + * @description ������������������ + * @param {String} val ��������� + * @private + */ + +parser.prototype.onAttrVal = function (val) { + const name = this.attrName || '' // ������������������������������ + + if (name == 'style' || name == 'href') this.attrs[name] = decodeEntity(val, true) // ��������������� + else if (name.includes('src')) this.attrs[name] = this.getUrl(decodeEntity(val, true)); else if (name) this.attrs[name] = val +} +/** + * @description ��������������������� + * @param {Boolean} selfClose ������������������������ /> + * @private + */ + +parser.prototype.onOpenTag = function (selfClose) { + // ������ node + const node = Object.create(null) + node.name = this.tagName + node.attrs = this.attrs + this.attrs = Object.create(null) + const { attrs } = node + const parent = this.stack[this.stack.length - 1] + const siblings = parent ? parent.children : this.nodes + const close = this.xml ? selfClose : config.voidTags[node.name] // ������ embed ������ + + if (node.name == 'embed') { + // #ifndef H5 || APP-PLUS + const src = attrs.src || '' // ������������������ type ��� embed ������ video ��� audio + + if (src.includes('.mp4') || src.includes('.3gp') || src.includes('.m3u8') || (attrs.type || '').includes('video')) node.name = 'video'; else if (src.includes('.mp3') || src.includes('.wav') || src.includes('.aac') || src.includes('.m4a') || (attrs.type || '').includes('audio')) node.name = 'audio' + if (attrs.autostart) attrs.autoplay = 'T' + attrs.controls = 'T' // #endif + // #ifdef H5 || APP-PLUS + + this.expose() // #endif + } // #ifndef APP-PLUS-NVUE + // ��������������� + + if (node.name == 'video' || node.name == 'audio') { + // ������ id ������������ context + if (node.name == 'video' && !attrs.id) attrs.id = `v${idIndex++}` // ������������ controls ��������������� autoplay ��������������� controls + + if (!attrs.controls && !attrs.autoplay) attrs.controls = 'T' // ������������������������������ source + + node.src = [] + + if (attrs.src) { + node.src.push(attrs.src) + attrs.src = void 0 + } + + this.expose() + } // #endif + // ��������������������� + + if (close) { + if (!this.hook(node) || config.ignoreTags[node.name]) { + // ������ base ��������������������� + if (node.name == 'base' && !this.options.domain) this.options.domain = attrs.href // #ifndef APP-PLUS-NVUE + // ������ source ������������������������ video ��� audio ������������ + else if (node.name == 'source' && parent && (parent.name == 'video' || parent.name == 'audio') && attrs.src) parent.src.push(attrs.src) // #endif + + return + } // ������ style + + const styleObj = this.parseStyle(node) // ������������ + + if (node.name == 'img') { + if (attrs.src) { + // ������ webp + if (attrs.src.includes('webp')) node.webp = 'T' // data url ������������������������ original-src ��������������������������������� + + if (attrs.src.includes('data:') && !attrs['original-src']) attrs.ignore = 'T' + + if (!attrs.ignore || node.webp || attrs.src.includes('cloud://')) { + for (let i = this.stack.length; i--;) { + const item = this.stack[i] + + if (item.name == 'a') { + node.a = item.attrs + break + } // #ifndef H5 || APP-PLUS + + const style = item.attrs.style || '' + + if (style.includes('flex:') && !style.includes('flex:0') && !style.includes('flex: 0') && (!styleObj.width || !styleObj.width.includes('%'))) { + styleObj.width = '100% !important' + styleObj.height = '' + + for (let j = i + 1; j < this.stack.length; j++) { + this.stack[j].attrs.style = (this.stack[j].attrs.style || '').replace('inline-', '') + } + } else if (style.includes('flex') && styleObj.width == '100%') { + for (let _j = i + 1; _j < this.stack.length; _j++) { + const _style = this.stack[_j].attrs.style || '' + + if (!_style.includes(';width') && !_style.includes(' width') && _style.indexOf('width') != 0) { + styleObj.width = '' + break + } + } + } else if (style.includes('inline-block')) { + if (styleObj.width && styleObj.width[styleObj.width.length - 1] == '%') { + item.attrs.style += `;max-width:${styleObj.width}` + styleObj.width = '' + } else item.attrs.style += ';max-width:100%' + } // #endif + + item.c = 1 + } + + attrs.i = this.imgList.length.toString() + + let _src = attrs['original-src'] || attrs.src // #ifndef H5 || MP-ALIPAY || APP-PLUS || MP-360 + + if (this.imgList.includes(_src)) { + // ������������������������������������������������������������������������������������ + let _i = _src.indexOf('://') + + if (_i != -1) { + _i += 3 + + let newSrc = _src.substr(0, _i) + + for (; _i < _src.length; _i++) { + if (_src[_i] == '/') break + newSrc += Math.random() > 0.5 ? _src[_i].toUpperCase() : _src[_i] + } + + newSrc += _src.substr(_i) + _src = newSrc + } + } // #endif + + this.imgList.push(_src) // #ifdef H5 || APP-PLUS + + if (this.options.lazyLoad) { + attrs['data-src'] = attrs.src + attrs.src = void 0 + } // #endif + } + } + + if (styleObj.display == 'inline') styleObj.display = '' // #ifndef APP-PLUS-NVUE + + if (attrs.ignore) { + styleObj['max-width'] = styleObj['max-width'] || '100%' + attrs.style += ';-webkit-touch-callout:none' + } // #endif + // ������������������������������������������������������������������ + + if (parseInt(styleObj.width) > windowWidth) styleObj.height = void 0 // ��������������������������� + + if (styleObj.width) { + if (styleObj.width.includes('auto')) styleObj.width = ''; else { + node.w = 'T' + if (styleObj.height && !styleObj.height.includes('auto')) node.h = 'T' + } + } + } else if (node.name == 'svg') { + siblings.push(node) + this.stack.push(node) + this.popNode() + return + } + + for (const key in styleObj) { + if (styleObj[key]) attrs.style += ';'.concat(key, ':').concat(styleObj[key].replace(' !important', '')) + } + + attrs.style = attrs.style.substr(1) || void 0 + } else { + if (node.name == 'pre' || (attrs.style || '').includes('white-space') && attrs.style.includes('pre')) this.pre = node.pre = true + node.children = [] + this.stack.push(node) + } // ��������������� + + siblings.push(node) +} +/** + * @description ��������������������� + * @param {String} name ��������� + * @private + */ + +parser.prototype.onCloseTag = function (name) { + // ��������������������������� + name = this.xml ? name : name.toLowerCase() + let i + + for (i = this.stack.length; i--;) { + if (this.stack[i].name == name) break + } + + if (i != -1) { + while (this.stack.length > i) { + this.popNode() + } + } else if (name == 'p' || name == 'br') { + const siblings = this.stack.length ? this.stack[this.stack.length - 1].children : this.nodes + siblings.push({ + name, + attrs: {} + }) + } +} +/** + * @description ������������������ + * @private + */ + +parser.prototype.popNode = function () { + const node = this.stack.pop() + let { attrs } = node + const { children } = node + const parent = this.stack[this.stack.length - 1] + const siblings = parent ? parent.children : this.nodes + + if (!this.hook(node) || config.ignoreTags[node.name]) { + // ������������ + if (node.name == 'title' && children.length && children[0].type == 'text' && this.options.setTitle) { + uni.setNavigationBarTitle({ + title: children[0].text + }) + } + siblings.pop() + return + } + + if (node.pre) { + // ��������������������������� + node.pre = this.pre = void 0 + + for (let i = this.stack.length; i--;) { + if (this.stack[i].pre) this.pre = true + } + } + + const styleObj = {} // ������ svg + + if (node.name == 'svg') { + // #ifndef APP-PLUS-NVUE + let src = '' + const { style } = attrs + attrs.style = '' + attrs.xmlns = 'http://www.w3.org/2000/svg'; + + (function traversal(node) { + src += `<${node.name}` + + for (let item in node.attrs) { + const val = node.attrs[item] + + if (val) { + if (item == 'viewbox') item = 'viewBox' + src += ' '.concat(item, '="').concat(val, '"') + } + } + + if (!node.children) src += '/>'; else { + src += '>' + + for (let _i2 = 0; _i2 < node.children.length; _i2++) { + traversal(node.children[_i2]) + } + + src += `</${node.name}>` + } + }(node)) + + node.name = 'img' + node.attrs = { + src: `data:image/svg+xml;utf8,${src.replace(/#/g, '%23')}`, + style, + ignore: 'T' + } + node.children = void 0 // #endif + + this.xml = false + return + } // #ifndef APP-PLUS-NVUE + // ������ align ������ + + if (attrs.align) { + if (node.name == 'table') { + if (attrs.align == 'center') styleObj['margin-inline-start'] = styleObj['margin-inline-end'] = 'auto'; else styleObj.float = attrs.align + } else styleObj['text-align'] = attrs.align + + attrs.align = void 0 + } // ������ font ��������������� + + if (node.name == 'font') { + if (attrs.color) { + styleObj.color = attrs.color + attrs.color = void 0 + } + + if (attrs.face) { + styleObj['font-family'] = attrs.face + attrs.face = void 0 + } + + if (attrs.size) { + let size = parseInt(attrs.size) + + if (!isNaN(size)) { + if (size < 1) size = 1; else if (size > 7) size = 7 + styleObj['font-size'] = ['xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'][size - 1] + } + + attrs.size = void 0 + } + } // #endif + // ������������������������ class + + if ((attrs.class || '').includes('align-center')) styleObj['text-align'] = 'center' + Object.assign(styleObj, this.parseStyle(node)) + + if (parseInt(styleObj.width) > windowWidth) { + styleObj['max-width'] = '100%' + styleObj['box-sizing'] = 'border-box' + } // #ifndef APP-PLUS-NVUE + + if (config.blockTags[node.name]) node.name = 'div' // ������������������ span��������������������� + else if (!config.trustTags[node.name] && !this.xml) node.name = 'span' + if (node.name == 'a' || node.name == 'ad' // #ifdef H5 || APP-PLUS + || node.name == 'iframe' // #endif + ) this.expose() // #ifdef APP-PLUS + else if (node.name == 'video') { + let str = '<video style="width:100%;height:100%"' // ��������������� + + if (!attrs.poster && !attrs.autoplay) attrs.poster = "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'/>" + + for (const item in attrs) { + if (attrs[item]) str += ` ${item}="${attrs[item]}"` + } + + if (this.options.pauseVideo) str += ' onplay="for(var e=document.getElementsByTagName(\'video\'),t=0;t<e.length;t++)e[t]!=this&&e[t].pause()"' + str += '>' + + for (let _i3 = 0; _i3 < node.src.length; _i3++) { + str += `<source src="${node.src[_i3]}">` + } + + str += '</video>' + node.html = str + } // #endif + // ������������ + else if ((node.name == 'ul' || node.name == 'ol') && node.c) { + const types = { + a: 'lower-alpha', + A: 'upper-alpha', + i: 'lower-roman', + I: 'upper-roman' + } + + if (types[attrs.type]) { + attrs.style += `;list-style-type:${types[attrs.type]}` + attrs.type = void 0 + } + + for (let _i4 = children.length; _i4--;) { + if (children[_i4].name == 'li') children[_i4].c = 1 + } + } // ������������ + else if (node.name == 'table') { + // cellpadding���cellspacing���border ��������������������������������������������������� + let padding = parseFloat(attrs.cellpadding) + let spacing = parseFloat(attrs.cellspacing) + const border = parseFloat(attrs.border) + + if (node.c) { + // padding ��� spacing ������ 2 + if (isNaN(padding)) padding = 2 + if (isNaN(spacing)) spacing = 2 + } + + if (border) attrs.style += `;border:${border}px solid gray` + + if (node.flag && node.c) { + // ��� colspan ��� rowspan ������������������������������ grid ������������ + styleObj.display = 'grid' + + if (spacing) { + styleObj['grid-gap'] = `${spacing}px` + styleObj.padding = `${spacing}px` + } // ��������������������������������������� + else if (border) attrs.style += ';border-left:0;border-top:0' + + const width = [] + // ��������������� + const trList = [] + // tr ������ + const cells = [] + // ��������������������� + const map = {}; // ��������������������������������� + + (function traversal(nodes) { + for (let _i5 = 0; _i5 < nodes.length; _i5++) { + if (nodes[_i5].name == 'tr') trList.push(nodes[_i5]); else traversal(nodes[_i5].children || []) + } + }(children)) + + for (let row = 1; row <= trList.length; row++) { + let col = 1 + + for (let j = 0; j < trList[row - 1].children.length; j++, col++) { + const td = trList[row - 1].children[j] + + if (td.name == 'td' || td.name == 'th') { + // ���������������������������������������������������++ + while (map[`${row}.${col}`]) { + col++ + } + + let _style2 = td.attrs.style || '' + const start = _style2.indexOf('width') ? _style2.indexOf(';width') : 0 // ��������� td ��������� + + if (start != -1) { + let end = _style2.indexOf(';', start + 6) + + if (end == -1) end = _style2.length + if (!td.attrs.colspan) width[col] = _style2.substring(start ? start + 7 : 6, end) + _style2 = _style2.substr(0, start) + _style2.substr(end) + } + + _style2 += (border ? ';border:'.concat(border, 'px solid gray') + (spacing ? '' : ';border-right:0;border-bottom:0') : '') + (padding ? ';padding:'.concat(padding, 'px') : '') // ��������������� + + if (td.attrs.colspan) { + _style2 += ';grid-column-start:'.concat(col, ';grid-column-end:').concat(col + parseInt(td.attrs.colspan)) + if (!td.attrs.rowspan) _style2 += ';grid-row-start:'.concat(row, ';grid-row-end:').concat(row + 1) + col += parseInt(td.attrs.colspan) - 1 + } // ��������������� + + if (td.attrs.rowspan) { + _style2 += ';grid-row-start:'.concat(row, ';grid-row-end:').concat(row + parseInt(td.attrs.rowspan)) + if (!td.attrs.colspan) _style2 += ';grid-column-start:'.concat(col, ';grid-column-end:').concat(col + 1) // ������������������������������ + + for (let k = 1; k < td.attrs.rowspan; k++) { + map[`${row + k}.${col}`] = 1 + } + } + + if (_style2) td.attrs.style = _style2 + cells.push(td) + } + } + + if (row == 1) { + let temp = '' + + for (let _i6 = 1; _i6 < col; _i6++) { + temp += `${width[_i6] ? width[_i6] : 'auto'} ` + } + + styleObj['grid-template-columns'] = temp + } + } + + node.children = cells + } else { + // ������������������������������������������ table ������������ + if (node.c) styleObj.display = 'table' + if (!isNaN(spacing)) styleObj['border-spacing'] = `${spacing}px` + + if (border || padding) { + // ������ + (function traversal(nodes) { + for (let _i7 = 0; _i7 < nodes.length; _i7++) { + const _td = nodes[_i7] + + if (_td.name == 'th' || _td.name == 'td') { + if (border) _td.attrs.style = 'border:'.concat(border, 'px solid gray;').concat(_td.attrs.style || '') + if (padding) _td.attrs.style = 'padding:'.concat(padding, 'px;').concat(_td.attrs.style || '') + } else if (_td.children) traversal(_td.children) + } + }(children)) + } + } // ��������������������������������������������� + + if (this.options.scrollTable && !(attrs.style || '').includes('inline')) { + const table = { ...node } + node.name = 'div' + node.attrs = { + style: 'overflow:auto' + } + node.children = [table] + attrs = table.attrs + } + } else if ((node.name == 'td' || node.name == 'th') && (attrs.colspan || attrs.rowspan)) { + for (let _i8 = this.stack.length; _i8--;) { + if (this.stack[_i8].name == 'table') { + this.stack[_i8].flag = 1 // ��������������������������� + + break + } + } + } // ������ ruby + else if (node.name == 'ruby') { + node.name = 'span' + + for (let _i9 = 0; _i9 < children.length - 1; _i9++) { + if (children[_i9].type == 'text' && children[_i9 + 1].name == 'rt') { + children[_i9] = { + name: 'div', + attrs: { + style: 'display:inline-block' + }, + children: [{ + name: 'div', + attrs: { + style: 'font-size:50%;text-align:start' + }, + children: children[_i9 + 1].children + }, children[_i9]] + } + children.splice(_i9 + 1, 1) + } + } + } else if (node.c) { + node.c = 2 + + for (let _i10 = node.children.length; _i10--;) { + if (!node.children[_i10].c || node.children[_i10].name == 'table') node.c = 1 + } + } + if ((styleObj.display || '').includes('flex') && !node.c) { + for (let _i11 = children.length; _i11--;) { + const _item = children[_i11] + + if (_item.f) { + _item.attrs.style = (_item.attrs.style || '') + _item.f + _item.f = void 0 + } + } + } // flex ������������������������������������ rich-text ������ + + const flex = parent && (parent.attrs.style || '').includes('flex') // #ifdef MP-WEIXIN + // ��������������������� virtualHost ������������ + && !(node.c && wx.getNFCAdapter) // #endif + // #ifndef MP-WEIXIN || MP-QQ || MP-BAIDU || MP-TOUTIAO + && !node.c // #endif + + if (flex) node.f = ';max-width:100%' // #endif + + for (const key in styleObj) { + if (styleObj[key]) { + const val = ';'.concat(key, ':').concat(styleObj[key].replace(' !important', '')) // #ifndef APP-PLUS-NVUE + + if (flex && (key.includes('flex') && key != 'flex-direction' || key == 'align-self' || styleObj[key][0] == '-' || key == 'width' && val.includes('%'))) { + node.f += val + if (key == 'width') attrs.style += ';width:100%' + } else // #endif + { attrs.style += val } + } + } + + attrs.style = attrs.style.substr(1) || void 0 +} +/** + * @description ��������������� + * @param {String} text ������������ + */ + +parser.prototype.onText = function (text) { + if (!this.pre) { + // ��������������� + let trim = '' + let flag + + for (let i = 0, len = text.length; i < len; i++) { + if (!blankChar[text[i]]) trim += text[i]; else { + if (trim[trim.length - 1] != ' ') trim += ' ' + if (text[i] == '\n' && !flag) flag = true + } + } // ������������������������������ + + if (trim == ' ' && flag) return + text = trim + } + + const node = Object.create(null) + node.type = 'text' + node.text = decodeEntity(text) + + if (this.hook(node)) { + const siblings = this.stack.length ? this.stack[this.stack.length - 1].children : this.nodes + siblings.push(node) + } +} +/** + * @description html ��������������� + * @param {Object} handler ��������������� + */ + +function lexer(handler) { + this.handler = handler +} +/** + * @description ������������ + * @param {String} content ������������������ + */ + +lexer.prototype.parse = function (content) { + this.content = content || '' + this.i = 0 // ������������������ + + this.start = 0 // ��������������������������������� + + this.state = this.text // ������������ + + for (let len = this.content.length; this.i != -1 && this.i < len;) { + this.state() + } +} +/** + * @description ������������������������ + * @param {String} method ������������������������������ + * @returns {Boolean} ������������ + * @private + */ + +lexer.prototype.checkClose = function (method) { + const selfClose = this.content[this.i] == '/' + + if (this.content[this.i] == '>' || selfClose && this.content[this.i + 1] == '>') { + if (method) this.handler[method](this.content.substring(this.start, this.i)) + this.i += selfClose ? 2 : 1 + this.start = this.i + this.handler.onOpenTag(selfClose) + + if (this.handler.tagName == 'script') { + this.i = this.content.indexOf('</', this.i) + + if (this.i != -1) { + this.i += 2 + this.start = this.i + } + + this.state = this.endTag + } else this.state = this.text + + return true + } + + return false +} +/** + * @description ������������ + * @private + */ + +lexer.prototype.text = function () { + this.i = this.content.indexOf('<', this.i) // ��������������������� + + if (this.i == -1) { + // ��������������� + if (this.start < this.content.length) this.handler.onText(this.content.substring(this.start, this.content.length)) + return + } + + const c = this.content[this.i + 1] + + if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') { + // ������������ + if (this.start != this.i) this.handler.onText(this.content.substring(this.start, this.i)) + this.start = ++this.i + this.state = this.tagName + } else if (c == '/' || c == '!' || c == '?') { + if (this.start != this.i) this.handler.onText(this.content.substring(this.start, this.i)) + const next = this.content[this.i + 2] + + if (c == '/' && (next >= 'a' && next <= 'z' || next >= 'A' && next <= 'Z')) { + // ������������ + this.i += 2 + this.start = this.i + return this.state = this.endTag + } // ������������ + + let end = '-->' + if (c != '!' || this.content[this.i + 2] != '-' || this.content[this.i + 3] != '-') end = '>' + this.i = this.content.indexOf(end, this.i) + + if (this.i != -1) { + this.i += end.length + this.start = this.i + } + } else this.i++ +} +/** + * @description ��������������� + * @private + */ + +lexer.prototype.tagName = function () { + if (blankChar[this.content[this.i]]) { + // ������������������ + this.handler.onTagName(this.content.substring(this.start, this.i)) + + while (blankChar[this.content[++this.i]]) { + + } + + if (this.i < this.content.length && !this.checkClose()) { + this.start = this.i + this.state = this.attrName + } + } else if (!this.checkClose('onTagName')) this.i++ +} +/** + * @description ��������������� + * @private + */ + +lexer.prototype.attrName = function () { + let c = this.content[this.i] + + if (blankChar[c] || c == '=') { + // ������������������ + this.handler.onAttrName(this.content.substring(this.start, this.i)) + let needVal = c == '=' + const len = this.content.length + + while (++this.i < len) { + c = this.content[this.i] + + if (!blankChar[c]) { + if (this.checkClose()) return + + if (needVal) { + // ������������������������������������ + this.start = this.i + return this.state = this.attrVal + } + + if (this.content[this.i] == '=') needVal = true; else { + this.start = this.i + return this.state = this.attrName + } + } + } + } else if (!this.checkClose('onAttrName')) this.i++ +} +/** + * @description ��������������� + * @private + */ + +lexer.prototype.attrVal = function () { + const c = this.content[this.i] + const len = this.content.length // ������������������ + + if (c == '"' || c == "'") { + this.start = ++this.i + this.i = this.content.indexOf(c, this.i) + if (this.i == -1) return + this.handler.onAttrVal(this.content.substring(this.start, this.i)) + } // ��������������������� + else { + for (; this.i < len; this.i++) { + if (blankChar[this.content[this.i]]) { + this.handler.onAttrVal(this.content.substring(this.start, this.i)) + break + } else if (this.checkClose('onAttrVal')) return + } + } + + while (blankChar[this.content[++this.i]]) { + + } + + if (this.i < len && !this.checkClose()) { + this.start = this.i + this.state = this.attrName + } +} +/** + * @description ������������������ + * @returns {String} ������������������ + * @private + */ + +lexer.prototype.endTag = function () { + const c = this.content[this.i] + + if (blankChar[c] || c == '>' || c == '/') { + this.handler.onCloseTag(this.content.substring(this.start, this.i)) + + if (c != '>') { + this.i = this.content.indexOf('>', this.i) + if (this.i == -1) return + } + + this.start = ++this.i + this.state = this.text + } else this.i++ +} + +module.exports = parser diff --git a/uni_modules/uview-ui/components/u-parse/props.js b/uni_modules/uview-ui/components/u-parse/props.js new file mode 100644 index 0000000..defd06c --- /dev/null +++ b/uni_modules/uview-ui/components/u-parse/props.js @@ -0,0 +1,45 @@ +export default { + props: { + // #ifdef APP-PLUS-NVUE + bgColor: String, + // #endif + content: String, + copyLink: { + type: Boolean, + default: uni.$u.props.parse.copyLink + }, + domain: String, + errorImg: { + type: String, + default: uni.$u.props.parse.errorImg + }, + lazyLoad: { + type: Boolean, + default: uni.$u.props.parse.lazyLoad + }, + loadingImg: { + type: String, + default: uni.$u.props.parse.loadingImg + }, + pauseVideo: { + type: Boolean, + default: uni.$u.props.parse.pauseVideo + }, + previewImg: { + type: Boolean, + default: uni.$u.props.parse.previewImg + }, + scrollTable: Boolean, + selectable: Boolean, + setTitle: { + type: Boolean, + default: uni.$u.props.parse.setTitle + }, + showImgMenu: { + type: Boolean, + default: uni.$u.props.parse.showImgMenu + }, + tagStyle: Object, + useAnchor: null + } +} diff --git a/uni_modules/uview-ui/components/u-parse/u-parse.vue b/uni_modules/uview-ui/components/u-parse/u-parse.vue new file mode 100644 index 0000000..7bc8b3d --- /dev/null +++ b/uni_modules/uview-ui/components/u-parse/u-parse.vue @@ -0,0 +1,366 @@ +<template> + <view id="_root" :class="(selectable?'_select ':'')+'_root'"> + <slot v-if="!nodes[0]" /> + <!-- #ifndef APP-PLUS-NVUE --> + <node v-else :childs="nodes" :opts="[lazyLoad,loadingImg,errorImg,showImgMenu]" /> + <!-- #endif --> + <!-- #ifdef APP-PLUS-NVUE --> + <web-view ref="web" src="/static/app-plus/mp-html/local.html" :style="'margin-top:-2px;height:' + height + 'px'" @onPostMessage="_onMessage" /> + <!-- #endif --> + </view> +</template> + +<script> + import props from './props.js'; +/** + * mp-html v2.0.4 + * @description ��������������� + * @tutorial https://github.com/jin-yufeng/mp-html + * @property {String} bgColor ���������������������������APP-PLUS-NVUE + * @property {String} content ������������������������������������������ true ��� + * @property {Boolean} copyLink ������������������������������������������������ + * @property {String} domain ������������������������������ + * @property {String} errorImg ��������������������������������� + * @property {Boolean} lazyLoad ������������������������������������ true ��� + * @property {string} loadingImg ��������������������������������������� + * @property {Boolean} pauseVideo ��������������������������������������������������������������� true ��� + * @property {Boolean} previewImg ��������������������������������������������������� true ��� + * @property {Boolean} scrollTable ��������������������������������������������������������������������� + * @property {Boolean} selectable ������������������������ + * @property {Boolean} setTitle ��������� title ��������������������������������������������� true ��� + * @property {Boolean} showImgMenu ��������������������������������������������������� true ��� + * @property {Object} tagStyle ��������������������� + * @property {Boolean | Number} useAnchor ������������������������ + * + * @event {Function} load dom ��������������������������� + * @event {Function} ready ��������������������������������� + * @event {Function} imgTap ������������������������ + * @event {Function} linkTap ������������������������ + * @event {Function} error ��������������������������� + */ +const plugins=[] +const parser = require('./parser') +// #ifndef APP-PLUS-NVUE +import node from './node/node' +// #endif +// #ifdef APP-PLUS-NVUE +const dom = weex.requireModule('dom') +// #endif +export default { + name: 'mp-html', + data() { + return { + nodes: [], + // #ifdef APP-PLUS-NVUE + height: 0 + // #endif + } + }, + mixins:[props], + // #ifndef APP-PLUS-NVUE + components: { + node + }, + // #endif + watch: { + content(content) { + this.setContent(content) + } + }, + created() { + this.plugins = [] + for (let i = plugins.length; i--;) + this.plugins.push(new plugins[i](this)) + }, + mounted() { + if (this.content && !this.nodes.length) + this.setContent(this.content) + }, + beforeDestroy() { + this._hook('onDetached') + clearInterval(this._timer) + }, + methods: { + /** + * @description ��������������������������������������� scroll-view ��� + * @param {Object} page scroll-view ��������������������� + * @param {String} selector scroll-view ������������ + * @param {String} scrollTop scroll-view scroll-top ������������������������ + */ + in(page, selector, scrollTop) { + // #ifndef APP-PLUS-NVUE + if (page && selector && scrollTop) + this._in = { + page, + selector, + scrollTop + } + // #endif + }, + + /** + * @description ������������ + * @param {String} id ������������������ id + * @param {Number} offset ������������������������ + * @returns {Promise} + */ + navigateTo(id, offset) { + return new Promise((resolve, reject) => { + if (!this.useAnchor) + return reject('Anchor is disabled') + offset = offset || parseInt(this.useAnchor) || 0 + // #ifdef APP-PLUS-NVUE + if (!id) { + dom.scrollToElement(this.$refs.web, { + offset + }) + resolve() + } else { + this._navigateTo = { + resolve, + reject, + offset + } + this.$refs.web.evalJs('uni.postMessage({data:{action:"getOffset",offset:(document.getElementById(' + id + ')||{}).offsetTop}})') + } + // #endif + // #ifndef APP-PLUS-NVUE + let deep = ' ' + // #ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO + deep = '>>>' + // #endif + const selector = uni.createSelectorQuery() + // #ifndef MP-ALIPAY + .in(this._in ? this._in.page : this) + // #endif + .select((this._in ? this._in.selector : '._root') + (id ? `${deep}#${id}` : '')).boundingClientRect() + if (this._in) + selector.select(this._in.selector).scrollOffset() + .select(this._in.selector).boundingClientRect() // ������ scroll-view ������������������������ + else + selector.selectViewport().scrollOffset() // ��������������������������� + selector.exec(res => { + if (!res[0]) + return reject('Label not found') + const scrollTop = res[1].scrollTop + res[0].top - (res[2] ? res[2].top : 0) + offset + if (this._in) + // scroll-view ������ + this._in.page[this._in.scrollTop] = scrollTop + else + // ������������ + uni.pageScrollTo({ + scrollTop, + duration: 300 + }) + resolve() + }) + // #endif + }) + }, + + /** + * @description ������������������ + * @return {String} + */ + getText() { + let text = ''; + (function traversal(nodes) { + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i] + if (node.type == 'text') + text += node.text.replace(/&/g, '&') + else if (node.name == 'br') + text += '\n' + else { + // ��������������������������� + const isBlock = node.name == 'p' || node.name == 'div' || node.name == 'tr' || node.name == 'li' || (node.name[0] == 'h' && node.name[1] > '0' && node.name[1] < '7') + if (isBlock && text && text[text.length - 1] != '\n') + text += '\n' + // ������������������������������ + if (node.children) + traversal(node.children) + if (isBlock && text[text.length - 1] != '\n') + text += '\n' + else if (node.name == 'td' || node.name == 'th') + text += '\t' + } + } + })(this.nodes) + return text + }, + + /** + * @description ��������������������������� + * @return {Promise} + */ + getRect() { + return new Promise((resolve, reject) => { + uni.createSelectorQuery() + // #ifndef MP-ALIPAY + .in(this) + // #endif + .select('#_root').boundingClientRect().exec(res => res[0] ? resolve(res[0]) : reject('Root label not found')) + }) + }, + + /** + * @description ������������ + * @param {String} content html ������ + * @param {Boolean} append ��������������������� + */ + setContent(content, append) { + if (!append || !this.imgList) + this.imgList = [] + const nodes = new parser(this).parse(content) + // #ifdef APP-PLUS-NVUE + if (this._ready) + this._set(nodes, append) + // #endif + this.$set(this, 'nodes', append ? (this.nodes || []).concat(nodes) : nodes) + + // #ifndef APP-PLUS-NVUE + this._videos = [] + this.$nextTick(() => { + this._hook('onLoad') + this.$emit('load') + }) + + // ������������������������ + let height + clearInterval(this._timer) + this._timer = setInterval(() => { + this.getRect().then(rect => { + // 350ms ��������������������������� ready ������ + if (rect.height == height) { + this.$emit('ready', rect) + clearInterval(this._timer) + } + height = rect.height + }).catch(() => { }) + }, 350) + // #endif + }, + + /** + * @description ������������������������ + */ + _hook(name) { + for (let i = plugins.length; i--;) + if (this.plugins[i][name]) + this.plugins[i][name]() + }, + + // #ifdef APP-PLUS-NVUE + /** + * @description ������������ + */ + _set(nodes, append) { + this.$refs.web.evalJs('setContent(' + JSON.stringify(nodes) + ',' + JSON.stringify([this.bgColor, this.errorImg, this.loadingImg, this.pauseVideo, this.scrollTable, this.selectable]) + ',' + append + ')') + }, + + /** + * @description ��������� web-view ������ + */ + _onMessage(e) { + const message = e.detail.data[0] + switch (message.action) { + // web-view ��������������� + case 'onJSBridgeReady': + this._ready = true + if (this.nodes) + this._set(this.nodes) + break + // ������ dom ������������ + case 'onLoad': + this.height = message.height + this._hook('onLoad') + this.$emit('load') + break + // ������������������������ + case 'onReady': + this.getRect().then(res => { + this.$emit('ready', res) + }).catch(() => { }) + break + // ��������������������� + case 'onHeightChange': + this.height = message.height + break + // ������������ + case 'onImgTap': + this.$emit('imgTap', message.attrs) + if (this.previewImg) + uni.previewImage({ + current: parseInt(message.attrs.i), + urls: this.imgList + }) + break + // ������������ + case 'onLinkTap': + const href = message.attrs.href + this.$emit('linkTap', message.attrs) + if (href) { + // ������������ + if (href[0] == '#') { + if (this.useAnchor) + dom.scrollToElement(this.$refs.web, { + offset: message.offset + }) + } + // ������������ + else if (href.includes('://')) { + if (this.copyLink) + plus.runtime.openWeb(href) + } + else + uni.navigateTo({ + url: href, + fail() { + wx.switchTab({ + url: href + }) + } + }) + } + break + // ��������������������������� + case 'getOffset': + if (typeof message.offset == 'number') { + dom.scrollToElement(this.$refs.web, { + offset: message.offset + this._navigateTo.offset + }) + this._navigateTo.resolve() + } else + this._navigateTo.reject('Label not found') + break + // ������ + case 'onClick': + this.$emit('tap') + break + // ������ + case 'onError': + this.$emit('error', { + source: message.source, + attrs: message.attrs + }) + } + } + // #endif + } +} +</script> + +<style> +/* #ifndef APP-PLUS-NVUE */ +/* ��������������� */ +._root { + overflow: auto; + -webkit-overflow-scrolling: touch; +} + +/* ������������ */ +._select { + user-select: text; +} +/* #endif */ +</style> diff --git a/uni_modules/uview-ui/components/u-picker-column/props.js b/uni_modules/uview-ui/components/u-picker-column/props.js new file mode 100644 index 0000000..7c11331 --- /dev/null +++ b/uni_modules/uview-ui/components/u-picker-column/props.js @@ -0,0 +1,5 @@ +export default { + props: { + + } +} diff --git a/uni_modules/uview-ui/components/u-picker-column/u-picker-column.vue b/uni_modules/uview-ui/components/u-picker-column/u-picker-column.vue new file mode 100644 index 0000000..53553f3 --- /dev/null +++ b/uni_modules/uview-ui/components/u-picker-column/u-picker-column.vue @@ -0,0 +1,27 @@ +<template> + <picker-view-column> + <view class="u-picker-column"> + + </view> + </picker-view-column> +</template> + +<script> + import props from './props.js'; + /** + * PickerColumn + * @description + * @tutorial url + * @property {String} + * @event {Function} + * @example + */ + export default { + name: 'u-picker-column', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; +</style> diff --git a/uni_modules/uview-ui/components/u-picker/props.js b/uni_modules/uview-ui/components/u-picker/props.js new file mode 100644 index 0000000..7b5d091 --- /dev/null +++ b/uni_modules/uview-ui/components/u-picker/props.js @@ -0,0 +1,79 @@ +export default { + props: { + // ������������picker������ + show: { + type: Boolean, + default: uni.$u.props.picker.show + }, + // ������������������������������ + showToolbar: { + type: Boolean, + default: uni.$u.props.picker.showToolbar + }, + // ������������ + title: { + type: String, + default: uni.$u.props.picker.title + }, + // ��������������������������������������� + columns: { + type: Array, + default: uni.$u.props.picker.columns + }, + // ��������������������������� + loading: { + type: Boolean, + default: uni.$u.props.picker.loading + }, + // ��������������������������������� + itemHeight: { + type: [String, Number], + default: uni.$u.props.picker.itemHeight + }, + // ��������������������� + cancelText: { + type: String, + default: uni.$u.props.picker.cancelText + }, + // ��������������������� + confirmText: { + type: String, + default: uni.$u.props.picker.confirmText + }, + // ��������������������� + cancelColor: { + type: String, + default: uni.$u.props.picker.cancelColor + }, + // ��������������������� + confirmColor: { + type: String, + default: uni.$u.props.picker.confirmColor + }, + // ������������������������������ + visibleItemCount: { + type: [String, Number], + default: uni.$u.props.picker.visibleItemCount + }, + // ��������������������������������������������� + keyName: { + type: String, + default: uni.$u.props.picker.keyName + }, + // ��������������������������������������� + closeOnClickOverlay: { + type: Boolean, + default: uni.$u.props.picker.closeOnClickOverlay + }, + // ��������������������� + defaultIndex: { + type: Array, + default: uni.$u.props.picker.defaultIndex + }, + // ������������������������������������ change ��������������������������������������������������������� change ���������������������2.21.1��������������� + immediateChange: { + type: Boolean, + default: uni.$u.props.picker.immediateChange + } + } +} diff --git a/uni_modules/uview-ui/components/u-picker/u-picker.vue b/uni_modules/uview-ui/components/u-picker/u-picker.vue new file mode 100644 index 0000000..8885917 --- /dev/null +++ b/uni_modules/uview-ui/components/u-picker/u-picker.vue @@ -0,0 +1,283 @@ +<template> + <u-popup + :show="show" + @close="closeHandler" + > + <view class="u-picker"> + <u-toolbar + v-if="showToolbar" + :cancelColor="cancelColor" + :confirmColor="confirmColor" + :cancelText="cancelText" + :confirmText="confirmText" + :title="title" + @cancel="cancel" + @confirm="confirm" + ></u-toolbar> + <picker-view + class="u-picker__view" + :indicatorStyle="`height: ${$u.addUnit(itemHeight)}`" + :value="innerIndex" + :immediateChange="immediateChange" + :style="{ + height: `${$u.addUnit(visibleItemCount * itemHeight)}` + }" + @change="changeHandler" + > + <picker-view-column + v-for="(item, index) in innerColumns" + :key="index" + class="u-picker__view__column" + > + <text + v-if="$u.test.array(item)" + class="u-picker__view__column__item u-line-1" + v-for="(item1, index1) in item" + :key="index1" + :style="{ + height: $u.addUnit(itemHeight), + lineHeight: $u.addUnit(itemHeight), + fontWeight: index1 === innerIndex[index] ? 'bold' : 'normal' + }" + >{{ getItemText(item1) }}</text> + </picker-view-column> + </picker-view> + <view + v-if="loading" + class="u-picker--loading" + > + <u-loading-icon mode="circle"></u-loading-icon> + </view> + </view> + </u-popup> +</template> + +<script> +/** + * u-picker + * @description ��������� + * @property {Boolean} show ������������picker��������������� false ��� + * @property {Boolean} showToolbar ��������������������������������������� true ��� + * @property {String} title ������������ + * @property {Array} columns ��������������������������������������� + * @property {Boolean} loading ������������������������������������ false ��� + * @property {String | Number} itemHeight ������������������������������������������ 44 ��� + * @property {String} cancelText ������������������������������ '������' ��� + * @property {String} confirmText ������������������������������ '������' ��� + * @property {String} cancelColor ������������������������������ '#909193' ��� + * @property {String} confirmColor ������������������������������ '#3c9cff' ��� + * @property {String | Number} visibleItemCount ��������������������������������������� 5 ��� + * @property {String} keyName ������������������������������������������������������ 'text' ��� + * @property {Boolean} closeOnClickOverlay ������������������������������������������������ false ��� + * @property {Array} defaultIndex ��������������������� + * @property {Boolean} immediateChange ������������������������������������change��������������� false ��� + * @event {Function} close ������������������������ + * @event {Function} cancel ������������������������ + * @event {Function} change ��������������������������� + * @event {Function} confirm ��������������������������������������������� + */ +import props from './props.js'; +export default { + name: 'u-picker', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + // ��������������������������� + lastIndex: [], + // ��������� ���������picker-view���value + innerIndex: [], + // ������������ + innerColumns: [], + // ��������������������������� + columnIndex: 0, + } + }, + watch: { + // ������������������������������������������������������ + defaultIndex: { + immediate: true, + handler(n) { + this.setIndexs(n, true) + } + }, + // ������columns��������������� + columns: { + immediate: true, + handler(n) { + this.setColumns(n) + } + }, + }, + methods: { + // ������item��������������������������������������������������� + getItemText(item) { + if (uni.$u.test.object(item)) { + return item[this.keyName] + } else { + return item + } + }, + // ��������������� + closeHandler() { + if (this.closeOnClickOverlay) { + this.$emit('close') + } + }, + // ������������������������������ + cancel() { + this.$emit('cancel') + }, + // ������������������������������ + confirm() { + this.$emit('confirm', { + indexs: this.innerIndex, + value: this.innerColumns.map((item, index) => item[this.innerIndex[index]]), + values: this.innerColumns + }) + }, + // ������������������������������������������������ + changeHandler(e) { + const { + value + } = e.detail + let index = 0, + columnIndex = 0 + // ������������������������������������������������������������������������ + for (let i = 0; i < value.length; i++) { + let item = value[i] + if (item !== (this.lastIndex[i] || 0)) { // ���undefined������������������0 + // ������columnIndex��������������������������� + columnIndex = i + // index��������������������������������������� + index = item + break // ������������������������������������������������������������ + } + } + this.columnIndex = columnIndex + const values = this.innerColumns + // ������������������������������������������"���������"������������������ + this.setLastIndex(value) + this.setIndexs(value) + + this.$emit('change', { + // #ifndef MP-WEIXIN || MP-LARK + // ���������������������������this��������������������������������� + picker: this, + // #endif + value: this.innerColumns.map((item, index) => item[value[index]]), + index, + indexs: value, + // values��������������������������������� + values, + columnIndex + }) + }, + // ������index������������������������������������������ + setIndexs(index, setLastIndex) { + this.innerIndex = uni.$u.deepClone(index) + if (setLastIndex) { + this.setLastIndex(index) + } + }, + // ������������������������������������ + setLastIndex(index) { + // ���������������������������������������������������������������������������������������������������������������������������������changeHandler��� + // ��������������������������������������������������������������������������������� + this.lastIndex = uni.$u.deepClone(index) + }, + // ��������������������������������� + setColumnValues(columnIndex, values) { + // ������innerColumns���������columnIndex���������������values������������������������splice������ + this.innerColumns.splice(columnIndex, 1, values) + // ���������������������innerIndex���������������������������������������������������������������������������������0 + let tmpIndex = uni.$u.deepClone(this.innerIndex) + for (let i = 0; i < this.innerColumns.length; i++) { + if (i > this.columnIndex) { + tmpIndex[i] = 0 + } + } + // ��������������������������������������������������� + this.setIndexs(tmpIndex) + }, + // ������������������������������ + getColumnValues(columnIndex) { + // ���������������������������������������change���������������������������������setColumnValues��������������� + // ���������������������change������������������getColumnValues������������������������������������������������������������������������������������������������ + (async () => { + await uni.$u.sleep() + })() + return this.innerColumns[columnIndex] + }, + // ���������������������columns������ + setColumns(columns) { + this.innerColumns = uni.$u.deepClone(columns) + // ���������������������������������������������������������������������defaultIndex������������0������������������������������������������ + if (this.innerIndex.length === 0) { + this.innerIndex = new Array(columns.length).fill(0) + } + }, + // ������������������������������������ + getIndexs() { + return this.innerIndex + }, + // ������������������������ + getValues() { + // ���������������������������������������change���������������������������������setColumnValues��������������� + // ���������������������change������������������getValues������������������������������������������������������������������������������������������������ + (async () => { + await uni.$u.sleep() + })() + return this.innerColumns.map((item, index) => item[this.innerIndex[index]]) + } + }, +} +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-picker { + position: relative; + + &__view { + + &__column { + @include flex; + flex: 1; + justify-content: center; + + &__item { + @include flex; + justify-content: center; + align-items: center; + font-size: 16px; + text-align: center; + /* #ifndef APP-NVUE */ + display: block; + /* #endif */ + color: $u-main-color; + + &--disabled { + /* #ifndef APP-NVUE */ + cursor: not-allowed; + /* #endif */ + opacity: 0.35; + } + } + } + } + + &--loading { + position: absolute; + top: 0; + right: 0; + left: 0; + bottom: 0; + @include flex; + justify-content: center; + align-items: center; + background-color: rgba(255, 255, 255, 0.87); + z-index: 1000; + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-popup/props.js b/uni_modules/uview-ui/components/u-popup/props.js new file mode 100644 index 0000000..d9fe952 --- /dev/null +++ b/uni_modules/uview-ui/components/u-popup/props.js @@ -0,0 +1,79 @@ +export default { + props: { + // ������������������ + show: { + type: Boolean, + default: uni.$u.props.popup.show + }, + // ������������������ + overlay: { + type: Boolean, + default: uni.$u.props.popup.overlay + }, + // ������������������������������ top bottom right left center + mode: { + type: String, + default: uni.$u.props.popup.mode + }, + // ���������������������ms + duration: { + type: [String, Number], + default: uni.$u.props.popup.duration + }, + // ������������������������ + closeable: { + type: Boolean, + default: uni.$u.props.popup.closeable + }, + // ������������������������ + overlayStyle: { + type: [Object, String], + default: uni.$u.props.popup.overlayStyle + }, + // ������������������������������ + closeOnClickOverlay: { + type: Boolean, + default: uni.$u.props.popup.closeOnClickOverlay + }, + // ������ + zIndex: { + type: [String, Number], + default: uni.$u.props.popup.zIndex + }, + // ���������iPhoneX������������������������ + safeAreaInsetBottom: { + type: Boolean, + default: uni.$u.props.popup.safeAreaInsetBottom + }, + // ��������������������������������������������������� + safeAreaInsetTop: { + type: Boolean, + default: uni.$u.props.popup.safeAreaInsetTop + }, + // ������������������������������top-left���������������top-right���������������bottom-left���������������bottom-right������������ + closeIconPos: { + type: String, + default: uni.$u.props.popup.closeIconPos + }, + // ������������������ + round: { + type: [Boolean, String, Number], + default: uni.$u.props.popup.round + }, + // mode=center��������������������������������������������������� + zoom: { + type: Boolean, + default: uni.$u.props.popup.zoom + }, + // ���������������������������transparent��������������������� + bgColor: { + type: String, + default: uni.$u.props.popup.bgColor + }, + // ���������������������0-1������ + overlayOpacity: { + type: [Number, String], + default: uni.$u.props.popup.overlayOpacity + } + } +} diff --git a/uni_modules/uview-ui/components/u-popup/u-popup.vue b/uni_modules/uview-ui/components/u-popup/u-popup.vue new file mode 100644 index 0000000..2ca51cc --- /dev/null +++ b/uni_modules/uview-ui/components/u-popup/u-popup.vue @@ -0,0 +1,304 @@ +<template> + <view class="u-popup"> + <u-overlay + :show="show" + @click="overlayClick" + v-if="overlay" + :duration="overlayDuration" + :customStyle="overlayStyle" + :opacity="overlayOpacity" + ></u-overlay> + <u-transition + :show="show" + :customStyle="transitionStyle" + :mode="position" + :duration="duration" + @afterEnter="afterEnter" + @click="clickHandler" + > + <view + class="u-popup__content" + :style="[contentStyle]" + @tap.stop="noop" + > + <u-status-bar v-if="safeAreaInsetTop"></u-status-bar> + <slot></slot> + <view + v-if="closeable" + @tap.stop="close" + class="u-popup__content__close" + :class="['u-popup__content__close--' + closeIconPos]" + hover-class="u-popup__content__close--hover" + hover-stay-time="150" + > + <u-icon + name="close" + color="#909399" + size="18" + bold + ></u-icon> + </view> + <u-safe-bottom v-if="safeAreaInsetBottom"></u-safe-bottom> + </view> + </u-transition> + </view> +</template> + +<script> + import props from './props.js'; + + /** + * popup ������ + * @description ������������������������������������������������������������������������������������������������������������������������������������������������������������������ + * @tutorial https://www.uviewui.com/components/popup.html + * @property {Boolean} show ������������������ (������ false ) + * @property {Boolean} overlay ������������������ ��������� true ��� + * @property {String} mode ��������������������� 'bottom' ��� + * @property {String | Number} duration ���������������������ms ��������� 300 ��� + * @property {String | Number} overlayDuration ������������������������������ms ��������� 350 ��� + * @property {Boolean} closeable ��������������������������������� false ��� + * @property {Object | String} overlayStyle ������������������������ + * @property {String | Number} overlayOpacity ������������������0-1��������������� 0.5��� + * @property {Boolean} closeOnClickOverlay ������������������������������ ��������� true ��� + * @property {String | Number} zIndex ������ ��������� 10075 ��� + * @property {Boolean} safeAreaInsetBottom ���������iPhoneX������������������������ ��������� true ��� + * @property {Boolean} safeAreaInsetTop ��������������������������������������������������� ��������� false ��� + * @property {String} closeIconPos ������������������������������������ 'top-right' ��� + * @property {String | Number} round ������������������ 0��� + * @property {Boolean} zoom ���mode=center��� ��������������������������� true ��� + * @property {Object} customStyle ������������������������������ + * @event {Function} open ��������������� + * @event {Function} close ��������������� + * @example <u-popup v-model="show"><text>���������������������������������������</text></u-popup> + */ + export default { + name: 'u-popup', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + overlayDuration: this.duration + 50 + } + }, + watch: { + show(newValue, oldValue) { + if (newValue === true) { + // #ifdef MP-WEIXIN + const children = this.$children + this.retryComputedComponentRect(children) + // #endif + } + } + }, + computed: { + transitionStyle() { + const style = { + zIndex: this.zIndex, + position: 'fixed', + display: 'flex', + } + style[this.mode] = 0 + if (this.mode === 'left') { + return uni.$u.deepMerge(style, { + bottom: 0, + top: 0, + }) + } else if (this.mode === 'right') { + return uni.$u.deepMerge(style, { + bottom: 0, + top: 0, + }) + } else if (this.mode === 'top') { + return uni.$u.deepMerge(style, { + left: 0, + right: 0 + }) + } else if (this.mode === 'bottom') { + return uni.$u.deepMerge(style, { + left: 0, + right: 0, + }) + } else if (this.mode === 'center') { + return uni.$u.deepMerge(style, { + alignItems: 'center', + 'justify-content': 'center', + top: 0, + left: 0, + right: 0, + bottom: 0 + }) + } + }, + contentStyle() { + const style = {} + // ���������������������safeAreaInsets������������������������������������������������������������������������ + // ���������css������������������nvue���������css���iPhoneX��������������������� + const { + safeAreaInsets + } = uni.$u.sys() + if (this.mode !== 'center') { + style.flex = 1 + } + // ���������������������������������transparent������������������������������ + if (this.bgColor) { + style.backgroundColor = this.bgColor + } + if(this.round) { + const value = uni.$u.addUnit(this.round) + if(this.mode === 'top') { + style.borderBottomLeftRadius = value + style.borderBottomRightRadius = value + } else if(this.mode === 'bottom') { + style.borderTopLeftRadius = value + style.borderTopRightRadius = value + } else if(this.mode === 'center') { + style.borderRadius = value + } + } + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) + }, + position() { + if (this.mode === 'center') { + return this.zoom ? 'fade-zoom' : 'fade' + } + if (this.mode === 'left') { + return 'slide-left' + } + if (this.mode === 'right') { + return 'slide-right' + } + if (this.mode === 'bottom') { + return 'slide-up' + } + if (this.mode === 'top') { + return 'slide-down' + } + }, + }, + methods: { + // ������������ + overlayClick() { + if (this.closeOnClickOverlay) { + this.$emit('close') + } + }, + close(e) { + this.$emit('close') + }, + afterEnter() { + this.$emit('open') + }, + clickHandler() { + // ���������������������������u-transition������������������������������������������������������������������������������������������������������������������������ + if(this.mode === 'center') { + this.overlayClick() + } + this.$emit('click') + }, + // #ifdef MP-WEIXIN + retryComputedComponentRect(children) { + // ��������������������������������������� + const names = ['u-calendar-month', 'u-album', 'u-collapse-item', 'u-dropdown', 'u-index-item', 'u-index-list', + 'u-line-progress', 'u-list-item', 'u-rate', 'u-read-more', 'u-row', 'u-row-notice', 'u-scroll-list', + 'u-skeleton', 'u-slider', 'u-steps-item', 'u-sticky', 'u-subsection', 'u-swipe-action-item', 'u-tabbar', + 'u-tabs', 'u-tooltip' + ] + // ������������������������������ + for (let i = 0; i < children.length; i++) { + const child = children[i] + // ��������������������������� + const grandChild = child.$children + // ���������������������������������������������������������������������������init������������������������ + if (names.includes(child.$options.name) && typeof child?.init === 'function') { + // ��������������������������������������������������������������� + uni.$u.sleep(50).then(() => { + child.init() + }) + } + // ��������������������������������������������������� + if (grandChild.length) { + this.retryComputedComponentRect(grandChild) + } + } + } + // #endif + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + $u-popup-flex:1 !default; + $u-popup-content-background-color: #fff !default; + + .u-popup { + flex: $u-popup-flex; + + &__content { + background-color: $u-popup-content-background-color; + position: relative; + + &--round-top { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-left-radius: 10px; + border-bottom-right-radius: 10px; + } + + &--round-left { + border-top-left-radius: 0; + border-top-right-radius: 10px; + border-bottom-left-radius: 0; + border-bottom-right-radius: 10px; + } + + &--round-right { + border-top-left-radius: 10px; + border-top-right-radius: 0; + border-bottom-left-radius: 10px; + border-bottom-right-radius: 0; + } + + &--round-bottom { + border-top-left-radius: 10px; + border-top-right-radius: 10px; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } + + &--round-center { + border-top-left-radius: 10px; + border-top-right-radius: 10px; + border-bottom-left-radius: 10px; + border-bottom-right-radius: 10px; + } + + &__close { + position: absolute; + + &--hover { + opacity: 0.4; + } + } + + &__close--top-left { + top: 15px; + left: 15px; + } + + &__close--top-right { + top: 15px; + right: 15px; + } + + &__close--bottom-left { + bottom: 15px; + left: 15px; + } + + &__close--bottom-right { + right: 15px; + bottom: 15px; + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-radio-group/props.js b/uni_modules/uview-ui/components/u-radio-group/props.js new file mode 100644 index 0000000..bb86cba --- /dev/null +++ b/uni_modules/uview-ui/components/u-radio-group/props.js @@ -0,0 +1,85 @@ +export default { + props: { + // ������������ + value: { + type: [String, Number, Boolean], + default: uni.$u.props.radioGroup.value + }, + + // ������������������radio + disabled: { + type: Boolean, + default: uni.$u.props.radioGroup.disabled + }, + // ���������circle-���������square-������ + shape: { + type: String, + default: uni.$u.props.radioGroup.shape + }, + // ���������������������������������������������������������parent���activeColor��� + activeColor: { + type: String, + default: uni.$u.props.radioGroup.activeColor + }, + // ������������������ + inactiveColor: { + type: String, + default: uni.$u.props.radioGroup.inactiveColor + }, + // ��������� + name: { + type: String, + default: uni.$u.props.radioGroup.name + }, + // ������������������������������px + size: { + type: [String, Number], + default: uni.$u.props.radioGroup.size + }, + // ���������������row-���������column-������ + placement: { + type: String, + default: uni.$u.props.radioGroup.placement + }, + // label��������� + label: { + type: [String], + default: uni.$u.props.radioGroup.label + }, + // label��������� ��������� '#303133' ��� + labelColor: { + type: [String], + default: uni.$u.props.radioGroup.labelColor + }, + // label������������������px������ + labelSize: { + type: [String, Number], + default: uni.$u.props.radioGroup.labelSize + }, + // ������������������������������checkbox(������ false ) + labelDisabled: { + type: Boolean, + default: uni.$u.props.radioGroup.labelDisabled + }, + // ������������ + iconColor: { + type: String, + default: uni.$u.props.radioGroup.iconColor + }, + // ������������������������px + iconSize: { + type: [String, Number], + default: uni.$u.props.radioGroup.iconSize + }, + // ��������������������������������������� + borderBottom: { + type: Boolean, + default: uni.$u.props.radioGroup.borderBottom + }, + // ������������������������������ + iconPlacement: { + type: String, + default: uni.$u.props.radio.iconPlacement + } + } +} diff --git a/uni_modules/uview-ui/components/u-radio-group/u-radio-group.vue b/uni_modules/uview-ui/components/u-radio-group/u-radio-group.vue new file mode 100644 index 0000000..0d3c9b5 --- /dev/null +++ b/uni_modules/uview-ui/components/u-radio-group/u-radio-group.vue @@ -0,0 +1,108 @@ +<template> + <view + class="u-radio-group" + :class="bemClass" + > + <slot></slot> + </view> +</template> + +<script> + import props from './props.js'; + + /** + * radioRroup ������������������ + * @description ���������������������������������������������������������������������������������u-radio������ + * @tutorial https://www.uviewui.com/components/radio.html + * @property {String | Number | Boolean} value ������������ + * @property {Boolean} disabled ������������������radio��������� false ��� + * @property {String} shape ���������������shape-���������circle-������(������ circle ) + * @property {String} activeColor ���������������������������������������Radio��������������� '#2979ff' ��� + * @property {String} inactiveColor ������������������ (������ '#c8c9cc' ) + * @property {String} name ��������� + * @property {String | Number} size ������������������������������px��������� 18 ��� + * @property {String} placement ���������������row-���������column-������ ��������� 'row' ��� + * @property {String} label ������ + * @property {String} labelColor label��������� ��������� '#303133' ��� + * @property {String | Number} labelSize label������������������px������ ��������� 14 ��� + * @property {Boolean} labelDisabled ������������������������������checkbox(������ false ) + * @property {String} iconColor ������������ ��������� '#ffffff' ��� + * @property {String | Number} iconSize ������������������������px ��������� 12 ��� + * @property {Boolean} borderBottom placement���row��������������������������� ��������� false ��� + * @property {String} iconPlacement ������������������������������ ��������� 'left' ��� + * @property {Object} customStyle ������������������������������ + * @event {Function} change ���������radio��������������������������� + * @example <u-radio-group v-model="value"></u-radio-group> + */ + export default { + name: 'u-radio-group', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + computed: { + // ������computed���������������������������u-radio��������������������������������������������������������������������������������������������������������������� + // ������������������������������������������������������parentData������������watch���������������������������������������������������������������(u-radio-group) + // ��������������������������������������� + parentData() { + return [this.value, this.disabled, this.inactiveColor, this.activeColor, this.size, this.labelDisabled, this.shape, + this.iconSize, this.borderBottom, this.placement + ] + }, + bemClass() { + // this.bem���������computed������������mixin��� + return this.bem('radio-group', ['placement']) + }, + }, + watch: { + // ��������������������������������������������������������������������������������������� + parentData() { + if (this.children.length) { + this.children.map(child => { + // ���������������(u-radio)���������init���������������������������(������������������������������������������������������������������) + typeof(child.init) === 'function' && child.init() + }) + } + }, + }, + data() { + return { + + } + }, + created() { + this.children = [] + }, + methods: { + // ������������radio��������������������������� + unCheckedOther(childInstance) { + this.children.map(child => { + // ���������radio������������������������������checked������������������ + if (childInstance !== child) { + child.checked = false + } + }) + const { + name + } = childInstance + // ������emit������������������������������v-model������������������ + this.$emit('input', name) + // ������������ + this.$emit('change', name) + }, + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-radio-group { + flex: 1; + + &--row { + @include flex; + } + + &--column { + @include flex(column); + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-radio/props.js b/uni_modules/uview-ui/components/u-radio/props.js new file mode 100644 index 0000000..3ec5f6b --- /dev/null +++ b/uni_modules/uview-ui/components/u-radio/props.js @@ -0,0 +1,64 @@ +export default { + props: { + // radio��������� + name: { + type: [String, Number, Boolean], + default: uni.$u.props.radio.name + }, + // ���������square������������circle��������� + shape: { + type: String, + default: uni.$u.props.radio.shape + }, + // ������������ + disabled: { + type: [String, Boolean], + default: uni.$u.props.radio.disabled + }, + // ������������������������������������������ + labelDisabled: { + type: [String, Boolean], + default: uni.$u.props.radio.labelDisabled + }, + // ���������������������������������������������������������parent���activeColor��� + activeColor: { + type: String, + default: uni.$u.props.radio.activeColor + }, + // ������������������ + inactiveColor: { + type: String, + default: uni.$u.props.radio.inactiveColor + }, + // ������������������������px + iconSize: { + type: [String, Number], + default: uni.$u.props.radio.iconSize + }, + // label������������������px������ + labelSize: { + type: [String, Number], + default: uni.$u.props.radio.labelSize + }, + // label���������������������nvue������������slot������������������������������������������������������������ + label: { + type: [String, Number], + default: uni.$u.props.radio.label + }, + // ��������������� + size: { + type: [String, Number], + default: uni.$u.props.radio.size + }, + // ������������ + color: { + type: String, + default: uni.$u.props.radio.color + }, + // label��������� + labelColor: { + type: String, + default: uni.$u.props.radio.labelColor + } + } +} diff --git a/uni_modules/uview-ui/components/u-radio/u-radio.vue b/uni_modules/uview-ui/components/u-radio/u-radio.vue new file mode 100644 index 0000000..c0caab6 --- /dev/null +++ b/uni_modules/uview-ui/components/u-radio/u-radio.vue @@ -0,0 +1,339 @@ +<template> + <view + class="u-radio" + @tap.stop="wrapperClickHandler" + :style="[radioStyle]" + :class="[`u-radio-label--${parentData.iconPlacement}`, parentData.borderBottom && parentData.placement === 'column' && 'u-border-bottom']" + > + <view + class="u-radio__icon-wrap" + @tap.stop="iconClickHandler" + :class="iconClasses" + :style="[iconWrapStyle]" + > + <slot name="icon"> + <u-icon + class="u-radio__icon-wrap__icon" + name="checkbox-mark" + :size="elIconSize" + :color="elIconColor" + /> + </slot> + </view> + <slot> + <text + class="u-radio__text" + @tap.stop="labelClickHandler" + :style="{ + color: elDisabled ? elInactiveColor : elLabelColor, + fontSize: elLabelSize, + lineHeight: elLabelSize + }" + >{{label}}</text> + </slot> + </view> +</template> + +<script> + import props from './props.js'; + /** + * radio ��������� + * @description ���������������������������������������������������������������������������������u-radio-group������ + * @tutorial https://www.uviewui.com/components/radio.html + * @property {String | Number} name radio��������� + * @property {String} shape ���������square������������circle��������� + * @property {Boolean} disabled ������������ + * @property {String | Boolean} labelDisabled ������������������������������������������ + * @property {String} activeColor ������������������������������parent���active-color��������� + * @property {String} inactiveColor ������������������ + * @property {String | Number} iconSize ���������������������px + * @property {String | Number} labelSize label���������������������px + * @property {String | Number} label label���������������������nvue������������slot������������������������������������������������������������ + * @property {String | Number} size ��������������� + * @property {String} iconColor ������������ + * @property {String} labelColor label��������� + * @property {Object} customStyle ������������������������������ + * + * @event {Function} change ������radio���������������������������(������������) + * @example <u-radio :labelDisabled="false">������������������������������</u-radio> + */ + export default { + name: "u-radio", + + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + checked: false, + // ������������������������������������ + // ���������������������������������������������������������computed���������this.parent.shape��������� + // ��������������������������� + parentData: { + iconSize: 12, + labelDisabled: null, + disabled: null, + shape: null, + activeColor: null, + inactiveColor: null, + size: 18, + value: null, + iconColor: null, + placement: 'row', + borderBottom: false, + iconPlacement: 'left' + } + } + }, + computed: { + // ������������������������������u-raios-group��������������������������������������������� + elDisabled() { + return this.disabled !== '' ? this.disabled : this.parentData.disabled !== null ? this.parentData.disabled : false; + }, + // ������������label������ + elLabelDisabled() { + return this.labelDisabled !== '' ? this.labelDisabled : this.parentData.labelDisabled !== null ? this.parentData.labelDisabled : + false; + }, + // ���������������������size���������������������21px + elSize() { + return this.size ? this.size : (this.parentData.size ? this.parentData.size : 21); + }, + // ���������������������������������������12px + elIconSize() { + return this.iconSize ? this.iconSize : (this.parentData.iconSize ? this.parentData.iconSize : 12); + }, + // ������������������������������ + elActiveColor() { + return this.activeColor ? this.activeColor : (this.parentData.activeColor ? this.parentData.activeColor : '#2979ff'); + }, + // ��������������������������������� + elInactiveColor() { + return this.inactiveColor ? this.inactiveColor : (this.parentData.inactiveColor ? this.parentData.inactiveColor : + '#c8c9cc'); + }, + // label��������� + elLabelColor() { + return this.labelColor ? this.labelColor : (this.parentData.labelColor ? this.parentData.labelColor : '#606266') + }, + // ��������������� + elShape() { + return this.shape ? this.shape : (this.parentData.shape ? this.parentData.shape : 'circle'); + }, + // label������ + elLabelSize() { + return uni.$u.addUnit(this.labelSize ? this.labelSize : (this.parentData.labelSize ? this.parentData.labelSize : + '15')) + }, + elIconColor() { + const iconColor = this.iconColor ? this.iconColor : (this.parentData.iconColor ? this.parentData.iconColor : + '#ffffff'); + // ��������������� + if (this.elDisabled) { + // disabled������������������������radio������������elInactiveColor + return this.checked ? this.elInactiveColor : 'transparent' + } else { + return this.checked ? iconColor : 'transparent' + } + }, + iconClasses() { + let classes = [] + // ��������������� + classes.push('u-radio__icon-wrap--' + this.elShape) + if (this.elDisabled) { + classes.push('u-radio__icon-wrap--disabled') + } + if (this.checked && this.elDisabled) { + classes.push('u-radio__icon-wrap--disabled--checked') + } + // ������������������������������������������������������������������������������������������������������","������������������ + // #ifdef MP-ALIPAY || MP-TOUTIAO + classes = classes.join(' ') + // #endif + return classes + }, + iconWrapStyle() { + // radio��������������� + const style = {} + style.backgroundColor = this.checked && !this.elDisabled ? this.elActiveColor : '#ffffff' + style.borderColor = this.checked && !this.elDisabled ? this.elActiveColor : this.elInactiveColor + style.width = uni.$u.addUnit(this.elSize) + style.height = uni.$u.addUnit(this.elSize) + // ������������������������������������������������������ + if (this.parentData.iconPlacement === 'right') { + style.marginRight = 0 + } + return style + }, + radioStyle() { + const style = {} + if(this.parentData.borderBottom && this.parentData.placement === 'row') { + uni.$u.error('���������������borderBottom���������true������������������u-radio-group���placement���������column���������') + } + // ��������������������������������������������������������������������������������������������������������������� + if(this.parentData.borderBottom && this.parentData.placement === 'column') { + // ios������������������������������������������ + style.paddingBottom = uni.$u.os() === 'ios' ? '12px' : '8px' + } + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) + } + }, + mounted() { + this.init() + }, + methods: { + init() { + // ���������������������������provide/inject������������������������������������������������������created��������������������������� + this.updateParentData() + if (!this.parent) { + uni.$u.error('u-radio������������u-radio-group������������') + } + // ������������������������������������������������ + this.checked = this.name === this.parentData.value + }, + updateParentData() { + this.getParentData('u-radio-group') + }, + // ������������ + iconClickHandler(e) { + this.preventEvent(e) + // ������������������������������������������ + if (!this.elDisabled) { + this.setRadioCheckedStatus() + } + }, + // ������������������������������������������������������������ + wrapperClickHandler(e) { + this.parentData.iconPlacement === 'right' && this.iconClickHandler(e) + }, + // ������label + labelClickHandler(e) { + this.preventEvent(e) + // ���������������������������������label������������������������������������������������ + if (!this.elLabelDisabled && !this.elDisabled) { + this.setRadioCheckedStatus() + } + }, + emitEvent() { + // u-radio���checked������true���(������������������)��������������������������������������������������� + if (!this.checked) { + this.$emit('change', this.name) + // ������������u-form������������������������������������������������������������������������������������ + this.$nextTick(() => { + uni.$u.formValidate(this, 'change') + }) + } + }, + // ������������������������ + // ������������������������������������������������checked������true������������������������������������u-radio������ + // ������������������������u-radio���checked������������false(������������������������)��������������������������������������� + setRadioCheckedStatus() { + this.emitEvent() + // ��������������������������������� + this.checked = true + typeof this.parent.unCheckedOther === 'function' && this.parent.unCheckedOther(this) + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + $u-radio-wrap-margin-right:6px !default; + $u-radio-wrap-font-size:20px !default; + $u-radio-wrap-border-width:1px !default; + $u-radio-wrap-border-color: #c8c9cc !default; + $u-radio-line-height:0 !default; + $u-radio-circle-border-radius:100% !default; + $u-radio-square-border-radius:3px !default; + $u-radio-checked-color:#fff !default; + $u-radio-checked-background-color:red !default; + $u-radio-checked-border-color: #2979ff !default; + $u-radio-disabled-background-color:#ebedf0 !default; + $u-radio-disabled--checked-color:#c8c9cc !default; + $u-radio-label-margin-left: 5px !default; + $u-radio-label-margin-right:12px !default; + $u-radio-label-color:$u-content-color !default; + $u-radio-label-font-size:15px !default; + $u-radio-label-disabled-color:#c8c9cc !default; + + .u-radio { + /* #ifndef APP-NVUE */ + @include flex(row); + /* #endif */ + overflow: hidden; + flex-direction: row; + align-items: center; + + &-label--left { + flex-direction: row + } + + &-label--right { + flex-direction: row-reverse; + justify-content: space-between + } + + &__icon-wrap { + /* #ifndef APP-NVUE */ + box-sizing: border-box; + // nvue������border-color��������������� + transition-property: border-color, background-color, color; + transition-duration: 0.2s; + /* #endif */ + color: $u-content-color; + @include flex; + align-items: center; + justify-content: center; + color: transparent; + text-align: center; + margin-right: $u-radio-wrap-margin-right; + font-size: $u-radio-wrap-font-size; + border-width: $u-radio-wrap-border-width; + border-color: $u-radio-wrap-border-color; + border-style: solid; + + /* #ifdef MP-TOUTIAO */ + // ������������������������������������������������������0��������������������� + &__icon { + line-height: $u-radio-line-height; + } + + /* #endif */ + + &--circle { + border-radius: $u-radio-circle-border-radius; + } + + &--square { + border-radius: $u-radio-square-border-radius; + } + + &--checked { + color: $u-radio-checked-color; + background-color: $u-radio-checked-background-color; + border-color: $u-radio-checked-border-color; + } + + &--disabled { + background-color: $u-radio-disabled-background-color !important; + } + + &--disabled--checked { + color: $u-radio-disabled--checked-color !important; + } + } + + &__label { + /* #ifndef APP-NVUE */ + word-wrap: break-word; + /* #endif */ + margin-left: $u-radio-label-margin-left; + margin-right: $u-radio-label-margin-right; + color: $u-radio-label-color; + font-size: $u-radio-label-font-size; + + &--disabled { + color: $u-radio-label-disabled-color; + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-rate/props.js b/uni_modules/uview-ui/components/u-rate/props.js new file mode 100644 index 0000000..2a56350 --- /dev/null +++ b/uni_modules/uview-ui/components/u-rate/props.js @@ -0,0 +1,69 @@ +export default { + props: { + // ������v-model��������������������������������� + value: { + type: [String, Number], + default: uni.$u.props.rate.value + }, + // ������������������������ + count: { + type: [String, Number], + default: uni.$u.props.rate.count + }, + // ������������������ + disabled: { + type: Boolean, + default: uni.$u.props.rate.disabled + }, + // ������������ + readonly: { + type: Boolean, + default: uni.$u.props.rate.readonly + }, + // ������������������������px + size: { + type: [String, Number], + default: uni.$u.props.rate.size + }, + // ��������������������� + inactiveColor: { + type: String, + default: uni.$u.props.rate.inactiveColor + }, + // ��������������� + activeColor: { + type: String, + default: uni.$u.props.rate.activeColor + }, + // ������������������������������px + gutter: { + type: [String, Number], + default: uni.$u.props.rate.gutter + }, + // ������������������������������ + minCount: { + type: [String, Number], + default: uni.$u.props.rate.minCount + }, + // ������������������ + allowHalf: { + type: Boolean, + default: uni.$u.props.rate.allowHalf + }, + // ������������������(������) + activeIcon: { + type: String, + default: uni.$u.props.rate.activeIcon + }, + // ���������������������(������) + inactiveIcon: { + type: String, + default: uni.$u.props.rate.inactiveIcon + }, + // ������������������������������������������ + touchable: { + type: Boolean, + default: uni.$u.props.rate.touchable + } + } +} diff --git a/uni_modules/uview-ui/components/u-rate/u-rate.vue b/uni_modules/uview-ui/components/u-rate/u-rate.vue new file mode 100644 index 0000000..1aa5dd0 --- /dev/null +++ b/uni_modules/uview-ui/components/u-rate/u-rate.vue @@ -0,0 +1,306 @@ +<template> + <view + class="u-rate" + :id="elId" + ref="u-rate" + :style="[$u.addStyle(customStyle)]" + > + <view + class="u-rate__content" + @touchmove.stop="touchMove" + @touchend.stop="touchEnd" + > + <view + class="u-rate__content__item" + v-for="(item, index) in Number(count)" + :key="index" + :class="[elClass]" + > + <view + class="u-rate__content__item__icon-wrap" + ref="u-rate__content__item__icon-wrap" + @tap.stop="clickHandler($event, index + 1)" + > + <u-icon + :name=" + Math.floor(activeIndex) > index + ? activeIcon + : inactiveIcon + " + :color=" + disabled + ? '#c8c9cc' + : Math.floor(activeIndex) > index + ? activeColor + : inactiveColor + " + :custom-style="{ + 'padding-left': $u.addUnit(gutter / 2), + 'padding-right': $u.addUnit(gutter / 2) + }" + :size="size" + ></u-icon> + </view> + <view + v-if="allowHalf" + @tap.stop="clickHandler($event, index + 1)" + class="u-rate__content__item__icon-wrap u-rate__content__item__icon-wrap--half" + :style="[{ + width: $u.addUnit(rateWidth / 2), + }]" + ref="u-rate__content__item__icon-wrap" + > + <u-icon + :name=" + Math.ceil(activeIndex) > index + ? activeIcon + : inactiveIcon + " + :color=" + disabled + ? '#c8c9cc' + : Math.ceil(activeIndex) > index + ? activeColor + : inactiveColor + " + :custom-style="{ + 'padding-left': $u.addUnit(gutter / 2), + 'padding-right': $u.addUnit(gutter / 2) + }" + :size="size" + ></u-icon> + </view> + </view> + </view> + </view> +</template> + +<script> + import props from './props.js'; + + // #ifdef APP-NVUE + const dom = weex.requireModule("dom"); + // #endif + /** + * rate ������ + * @description ������������������������������������������������������������ + * @tutorial https://www.uviewui.com/components/rate.html + * @property {String | Number} value ������v-model��������������������������������� (������ 1 ) + * @property {String | Number} count ��������������������������� ��������� 5 ��� + * @property {Boolean} disabled ������������������������ ��������� false ��� + * @property {Boolean} readonly ������������ ��������� false ��� + * @property {String | Number} size ������������������������px ��������� 18 ��� + * @property {String} inactiveColor ������������������������ ��������� '#b2b2b2' ��� + * @property {String} activeColor ��������������������� ��������� '#FA3534' ��� + * @property {String | Number} gutter ��������������������� ��������� 4 ��� + * @property {String | Number} minCount ��������������������������� ��������� 1 ��� + * @property {Boolean} allowHalf ������������������������ ��������� false ��� + * @property {String} activeIcon ���������������������������������uView��������������� ��������� 'star-fill' ��� + * @property {String} inactiveIcon ������������������������������������uView��������������� ��������� 'star' ��� + * @property {Boolean} touchable ������������������������������������������ ��������� 'true' ��� + * @property {Object} customStyle ������������������������������ + * @event {Function} change ������������������������������������ + * @example <u-rate :count="count" :value="2"></u-rate> + */ + export default { + name: "u-rate", + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + // ������������������id��������������������������������������������������������� + elId: uni.$u.guid(), + elClass: uni.$u.guid(), + rateBoxLeft: 0, // ������������������������������������������������������������������������������ + activeIndex: this.value, + rateWidth: 0, // ��������������������� + // ���������������������������������iOS���������touch���click������������������������������������������������������click������������������������������ + moving: false, + }; + }, + watch: { + value(val) { + this.activeIndex = val; + }, + activeIndex: 'emitEvent' + }, + methods: { + init() { + uni.$u.sleep().then(() => { + this.getRateItemRect(); + this.getRateIconWrapRect(); + }) + }, + // ��������������������������������������� + async getRateItemRect() { + await uni.$u.sleep(); + // uView��������������������������������������������� + // #ifndef APP-NVUE + this.$uGetRect("#" + this.elId).then((res) => { + this.rateBoxLeft = res.left; + }); + // #endif + // #ifdef APP-NVUE + dom.getComponentRect(this.$refs["u-rate"], (res) => { + this.rateBoxLeft = res.size.left; + }); + // #endif + }, + // ��������������������������� + getRateIconWrapRect() { + // uView��������������������������������������������� + // #ifndef APP-NVUE + this.$uGetRect("." + this.elClass).then((res) => { + this.rateWidth = res.width; + }); + // #endif + // #ifdef APP-NVUE + dom.getComponentRect( + this.$refs["u-rate__content__item__icon-wrap"][0], + (res) => { + this.rateWidth = res.size.width; + } + ); + // #endif + }, + // ������������ + touchMove(e) { + // ��������������������������������������������� + if (!this.touchable) { + return; + } + this.preventEvent(e); + const x = e.changedTouches[0].pageX; + this.getActiveIndex(x); + }, + // ������������ + touchEnd(e) { + // ��������������������������������������������� + if (!this.touchable) { + return; + } + this.preventEvent(e); + const x = e.changedTouches[0].pageX; + this.getActiveIndex(x); + }, + // ��������������������������� + clickHandler(e, index) { + // ios������moving������������������������ + if (uni.$u.os() === "ios" && this.moving) { + return; + } + this.preventEvent(e); + let x = 0; + // ���������������nvue������������������������������������������������������������������������ + // #ifndef APP-NVUE + x = e.changedTouches[0].pageX; + // #endif + // #ifdef APP-NVUE + // nvue��������������������������������������������������������������������������������������������� + x = index * this.rateWidth + this.rateBoxLeft; + // #endif + this.getActiveIndex(x,true); + }, + // ������������ + emitEvent() { + // ������change������ + this.$emit("change", this.activeIndex); + // ���������������������������value������ + this.$emit("input", this.activeIndex); + }, + // ��������������������������������� + getActiveIndex(x,isClick = false) { + if (this.disabled || this.readonly) { + return; + } + // ���������������������������x��������������������������������������������� + const allRateWidth = this.rateWidth * this.count + this.rateBoxLeft; + // ������������������������������������������������������������������������������������������������������������������������ + x = uni.$u.range(this.rateBoxLeft, allRateWidth, x) - this.rateBoxLeft + // ��������������������������������������������� + const distance = x; + // ������������������������������������������ + let index; + // ������������������������ + if (this.allowHalf) { + index = Math.floor(distance / this.rateWidth); + // ������������������������������������ + const decimal = distance % this.rateWidth; + if (decimal <= this.rateWidth / 2 && decimal > 0) { + index += 0.5; + } else if (decimal > this.rateWidth / 2) { + index++; + } + } else { + index = Math.floor(distance / this.rateWidth); + // ������������������������������������ + const decimal = distance % this.rateWidth; + // ������������������������������������������������������������������������������������ + if (isClick){ + if (decimal > 0) index++; + } else { + if (decimal > this.rateWidth / 2) index++; + } + + } + this.activeIndex = Math.min(index, this.count); + // ��������������������������� + if (this.activeIndex < this.minCount) { + this.activeIndex = this.minCount; + } + + // ���������������������click���������touchmove������������ + setTimeout(() => { + this.moving = true; + }, 10); + // ���������������������������������������������������������������click������������ + setTimeout(() => { + this.moving = false; + }, 10); + }, + }, + mounted() { + this.init(); + }, + }; +</script> + +<style lang="scss" scoped> +@import "../../libs/css/components.scss"; +$u-rate-margin: 0 !default; +$u-rate-padding: 0 !default; +$u-rate-item-icon-wrap-half-top: 0 !default; +$u-rate-item-icon-wrap-half-left: 0 !default; + +.u-rate { + @include flex; + align-items: center; + margin: $u-rate-margin; + padding: $u-rate-padding; + /* #ifndef APP-NVUE */ + touch-action: none; + /* #endif */ + + &__content { + @include flex; + + &__item { + position: relative; + + &__icon-wrap { + &--half { + position: absolute; + overflow: hidden; + top: $u-rate-item-icon-wrap-half-top; + left: $u-rate-item-icon-wrap-half-left; + } + } + } + } +} + +.u-icon { + /* #ifndef APP-NVUE */ + box-sizing: border-box; + /* #endif */ +} +</style> diff --git a/uni_modules/uview-ui/components/u-read-more/props.js b/uni_modules/uview-ui/components/u-read-more/props.js new file mode 100644 index 0000000..b444e74 --- /dev/null +++ b/uni_modules/uview-ui/components/u-read-more/props.js @@ -0,0 +1,61 @@ +export default { + props: { + // ��������������������������� + showHeight: { + type: [String, Number], + default: uni.$u.props.readMore.showHeight + }, + // ���������������������"������"������ + toggle: { + type: Boolean, + default: uni.$u.props.readMore.toggle + }, + // ������������������������ + closeText: { + type: String, + default: uni.$u.props.readMore.closeText + }, + // ������������������������ + openText: { + type: String, + default: uni.$u.props.readMore.openText + }, + // ��������������������� + color: { + type: String, + default: uni.$u.props.readMore.color + }, + // ��������������������� + fontSize: { + type: [String, Number], + default: uni.$u.props.readMore.fontSize + }, + // ������������������ + // ���������������������props/readMore.js���������������������������������������������������������������js��� + // uni������������������������������������nvue���������nvue��� + shadowStyle: { + type: Object, + default: () => ({ + // #ifndef APP-NVUE + backgroundImage: 'linear-gradient(-180deg, rgba(255, 255, 255, 0) 0%, #fff 80%)', + // #endif + // #ifdef APP-NVUE + // nvue���������������������������backgroundImage������ + backgroundImage: 'linear-gradient(to top, #fff, rgba(255, 255, 255, 0.5))', + // #endif + paddingTop: '100px', + marginTop: '-100px' + }) + }, + // ��������������������������������� + textIndent: { + type: String, + default: uni.$u.props.readMore.textIndent + }, + // open���close������������������������������������������������ + name: { + type: [String, Number], + default: uni.$u.props.readMore.name + } + } +} diff --git a/uni_modules/uview-ui/components/u-read-more/u-read-more.vue b/uni_modules/uview-ui/components/u-read-more/u-read-more.vue new file mode 100644 index 0000000..9104e40 --- /dev/null +++ b/uni_modules/uview-ui/components/u-read-more/u-read-more.vue @@ -0,0 +1,157 @@ +<template> + <view class="u-read-more"> + <view + class="u-read-more__content" + :style="{ + height: isLongContent && status === 'close' ? $u.addUnit(showHeight) : $u.addUnit(contentHeight), + textIndent: textIndent + }" + > + <view + class="u-read-more__content__inner" + ref="u-read-more__content__inner" + :class="[elId]" + > + <slot></slot> + </view> + </view> + <view + class="u-read-more__toggle" + :style="[innerShadowStyle]" + v-if="isLongContent" + > + <slot name="toggle"> + <view + class="u-read-more__toggle__text" + @tap="toggleReadMore" + > + <u--text + :text="status === 'close' ? closeText : openText" + :color="color" + :size="fontSize" + :lineHeight="fontSize" + margin="0 5px 0 0" + ></u--text> + <view class="u-read-more__toggle__icon"> + <u-icon + :color="color" + :size="fontSize + 2" + :name="status === 'close' ? 'arrow-down' : 'arrow-up'" + ></u-icon> + </view> + </view> + </slot> + </view> + </view> +</template> + +<script> + // #ifdef APP-NVUE + const dom = uni.requireNativePlugin('dom') + // #endif + import props from './props.js'; + /** + * readMore ������������ + * @description ������������������������������������������������������������������������������������������������ + * @tutorial https://www.uviewui.com/components/readMore.html + * @property {String | Number} showHeight ������������������������������������������������������������px��������� 400 ��� + * @property {Boolean} toggle ������������������������������������������ false ��� + * @property {String} closeText ��������������������������������� '������������������' ��� + * @property {String} openText ��������������������������������� '������' ��� + * @property {String} color ������������������������������ '#2979ff' ��� + * @property {String | Number} fontSize ������������������������������px ��������� 14 ��� + * @property {Object} shadowStyle ��������������������� + * @property {String} textIndent ��������������������������������� ��������� '2em' ��� + * @property {String | Number} name ��������� open ��� close ��������������������������������� + * @event {Function} open ������������������������ + * @event {Function} close ������������������������ + * @example <u-read-more><rich-text :nodes="content"></rich-text></u-read-more> + */ + export default { + name: 'u-read-more', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + isLongContent: false, // ��������������������������������� + status: 'close', // ���������������������������������close-���������������open-������������ + elId: uni.$u.guid(), // ������������class + contentHeight: 100, // ������������ + } + }, + computed: { + // ������������������������������������������������������ + innerShadowStyle() { + if (this.status === 'open') return {} + else return this.shadowStyle + } + }, + mounted() { + this.init() + }, + methods: { + async init() { + this.getContentHeight().then(height => { + this.contentHeight = height + // ��������������������������������������������������������������������������������������������������� + if (height > uni.$u.getPx(this.showHeight)) { + this.isLongContent = true + this.status = 'close' + } + }) + }, + // ��������������������� + async getContentHeight() { + // ��������������������������������� + await uni.$u.sleep(30) + return new Promise(resolve => { + // #ifndef APP-NVUE + this.$uGetRect('.' + this.elId).then(res => { + resolve(res.height) + }) + // #endif + + // #ifdef APP-NVUE + const ref = this.$refs['u-read-more__content__inner'] + dom.getComponentRect(ref, (res) => { + resolve(res.size.height) + }) + // #endif + }) + }, + // ������������������ + toggleReadMore() { + this.status = this.status === 'close' ? 'open' : 'close' + // ������toggle���false���������"������"��������������� + if (this.toggle == false) this.isLongContent = false + // ��������������������������������� + this.$emit(this.status, this.name) + } + } + } +</script> + +<style lang="scss" scoped> +@import "../../libs/css/components.scss"; + +.u-read-more { + + &__content { + overflow: hidden; + color: $u-content-color; + font-size: 15px; + text-align: left; + } + + &__toggle { + @include flex; + justify-content: center; + + &__text { + @include flex; + align-items: center; + justify-content: center; + margin-top: 5px; + } + } +} +</style> diff --git a/uni_modules/uview-ui/components/u-row-notice/props.js b/uni_modules/uview-ui/components/u-row-notice/props.js new file mode 100644 index 0000000..107bd70 --- /dev/null +++ b/uni_modules/uview-ui/components/u-row-notice/props.js @@ -0,0 +1,39 @@ +export default { + props: { + // ��������������������������� + text: { + type: String, + default: uni.$u.props.rowNotice.text + }, + // ��������������������������������� + icon: { + type: String, + default: uni.$u.props.rowNotice.icon + }, + // ���������������link-������������������closable-������������������������ + mode: { + type: String, + default: uni.$u.props.rowNotice.mode + }, + // ������������������������������������������������ + color: { + type: String, + default: uni.$u.props.rowNotice.color + }, + // ������������ + bgColor: { + type: String, + default: uni.$u.props.rowNotice.bgColor + }, + // ���������������������px + fontSize: { + type: [String, Number], + default: uni.$u.props.rowNotice.fontSize + }, + // ������������������������������������������������������px(rpx)��������������������������������������������������������������������������� + speed: { + type: [String, Number], + default: uni.$u.props.rowNotice.speed + } + } +} diff --git a/uni_modules/uview-ui/components/u-row-notice/u-row-notice.vue b/uni_modules/uview-ui/components/u-row-notice/u-row-notice.vue new file mode 100644 index 0000000..20f43c3 --- /dev/null +++ b/uni_modules/uview-ui/components/u-row-notice/u-row-notice.vue @@ -0,0 +1,330 @@ +<template> + <view + class="u-notice" + @tap="clickHandler" + > + <slot name="icon"> + <view + class="u-notice__left-icon" + v-if="icon" + > + <u-icon + :name="icon" + :color="color" + size="19" + ></u-icon> + </view> + </slot> + <view + class="u-notice__content" + ref="u-notice__content" + > + <view + ref="u-notice__content__text" + class="u-notice__content__text" + :style="[animationStyle]" + > + <text + v-for="(item, index) in innerText" + :key="index" + :style="[textStyle]" + >{{item}}</text> + </view> + </view> + <view + class="u-notice__right-icon" + v-if="['link', 'closable'].includes(mode)" + > + <u-icon + v-if="mode === 'link'" + name="arrow-right" + :size="17" + :color="color" + ></u-icon> + <u-icon + v-if="mode === 'closable'" + @click="close" + name="close" + :size="16" + :color="color" + ></u-icon> + </view> + </view> +</template> +<script> + import props from './props.js'; + // #ifdef APP-NVUE + const animation = uni.requireNativePlugin('animation') + const dom = uni.requireNativePlugin('dom') + // #endif + /** + * RowNotice ������������������������������������ + * @description ������������ + * @tutorial https://www.uviewui.com/components/noticeBar.html + * @property {String | Number} text ��������������������������� + * @property {String} icon ��������������������������������� (������ 'volume' ) + * @property {String} mode ���������������link-������������������closable-������������������������ + * @property {String} color ������������������������������������������������ (������ '#f9ae3d' ) + * @property {String} bgColor ������������ (������ ''#fdf6ec' ) + * @property {String | Number} fontSize ���������������������px (������ 14 ) + * @property {String | Number} speed ������������������������������������������������������px(rpx)��������������������������������������������������������������������������� (������ 80 ) + * + * @event {Function} click ������������������������ + * @event {Function} close ������������������������������ + * @example + */ + export default { + name: 'u-row-notice', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + animationDuration: '0', // ������������������ + animationPlayState: 'paused', // ������������������������������ + // nvue������������������������������������������������������������������������������������������������������ + // ���������������������������������������������������nvue���animation��������������������������������������������������������� + nvueInit: true, + show: true + }; + }, + watch: { + text: { + immediate: true, + handler(newValue, oldValue) { + // #ifdef APP-NVUE + this.nvueInit = true + // #endif + // #ifndef APP-NVUE + this.vue() + // #endif + + if(!uni.$u.test.string(newValue)) { + uni.$u.error('noticebar������direction���row������������text������������������������') + } + } + }, + fontSize() { + // #ifdef APP-NVUE + this.nvueInit = true + // #endif + // #ifndef APP-NVUE + this.vue() + // #endif + }, + speed() { + // #ifdef APP-NVUE + this.nvueInit = true + // #endif + // #ifndef APP-NVUE + this.vue() + // #endif + } + }, + computed: { + // ��������������������� + textStyle() { + let style = {} + style.color = this.color + style.fontSize = uni.$u.addUnit(this.fontSize) + return style + }, + animationStyle() { + let style = {} + style.animationDuration = this.animationDuration + style.animationPlayState = this.animationPlayState + return style + }, + // ������������������������������������������������������������text������������������������������������������������������������100������������������ + // ������������text���������������������������������������������������������������������������������������������������������text��������������������� + innerText() { + let result = [], + // ������text��������������������� + len = 20 + const textArr = this.text.split('') + for (let i = 0; i < textArr.length; i += len) { + // ������������������text������slice������������������������������������join������������������ + result.push(textArr.slice(i, i + len).join('')) + } + return result + } + }, + mounted() { + // #ifdef APP-PLUS + // ���APP���(���nvue)���������������webview������������������������(������������������������hide������) + // ������webivew������������������������������������������������������������������������������������������������������������������������������������������������ + var pages = getCurrentPages() + var page = pages[pages.length - 1] + var currentWebview = page.$getAppWebview() + currentWebview.addEventListener('hide', () => { + this.webviewHide = true + }) + currentWebview.addEventListener('show', () => { + this.webviewHide = false + }) + // #endif + + this.init() + }, + methods: { + init() { + // #ifdef APP-NVUE + this.nvue() + // #endif + + // #ifndef APP-NVUE + this.vue() + // #endif + + if(!uni.$u.test.string(this.text)) { + uni.$u.error('noticebar������direction���row������������text������������������������') + } + }, + // vue��������� + async vue() { + // #ifndef APP-NVUE + let boxWidth = 0, + textWidth = 0 + // ��������������������� + await uni.$u.sleep() + // ������������������������������ + textWidth = (await this.$uGetRect('.u-notice__content__text')).width + boxWidth = (await this.$uGetRect('.u-notice__content')).width + // ������t=s/v(������=������/������)������������������������������#u-notice-box������������������������������.u-notice-content������������������padding-left: 100% + // ���������������������������������������������#u-notice-box��������� + this.animationDuration = `${textWidth / uni.$u.getPx(this.speed)}s` + // ������������������������������������������APP��������������������������� + this.animationPlayState = 'paused' + setTimeout(() => { + this.animationPlayState = 'running' + }, 10) + // #endif + }, + // nvue��������� + async nvue() { + // #ifdef APP-NVUE + this.nvueInit = false + let boxWidth = 0, + textWidth = 0 + // ��������������������� + await uni.$u.sleep() + // ������������������������������ + textWidth = (await this.getNvueRect('u-notice__content__text')).width + boxWidth = (await this.getNvueRect('u-notice__content')).width + // ���������������������������������������������������������������������������nvue���������100%���������������������������css������ + animation.transition(this.$refs['u-notice__content__text'], { + styles: { + transform: `translateX(${boxWidth}px)` + }, + }, () => { + // ��������������������������������������� + !this.stopAnimation && this.loopAnimation(textWidth, boxWidth) + }); + // #endif + }, + loopAnimation(textWidth, boxWidth) { + // #ifdef APP-NVUE + animation.transition(this.$refs['u-notice__content__text'], { + styles: { + // ���������������������-textWidth��������������������������������������������������������������� + transform: `translateX(-${textWidth}px)` + }, + // ��������������������������������� = ������(boxWidth + textWidth) / ��������������������������� + duration: (boxWidth + textWidth) / uni.$u.getPx(this.speed) * 1000, + delay: 10 + }, () => { + animation.transition(this.$refs['u-notice__content__text'], { + styles: { + // ������������������������������������������ + transform: `translateX(${this.stopAnimation ? 0 : boxWidth}px)` + }, + }, () => { + // ������������������������������������������������ + if (!this.stopAnimation) { + // ��������������������������������������� + if (this.nvueInit) { + this.nvue() + } else { + this.loopAnimation(textWidth, boxWidth) + } + } + }); + }) + // #endif + }, + getNvueRect(el) { + // #ifdef APP-NVUE + // ������������promise + return new Promise(resolve => { + dom.getComponentRect(this.$refs[el], (res) => { + resolve(res.size) + }) + }) + // #endif + }, + // ��������������� + clickHandler(index) { + this.$emit('click') + }, + // ��������������������������������������������������������������������������� + close() { + this.$emit('close') + } + }, + // #ifdef APP-NVUE + beforeDestroy() { + this.stopAnimation = true + }, + // #endif + }; +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-notice { + @include flex; + align-items: center; + justify-content: space-between; + + &__left-icon { + align-items: center; + margin-right: 5px; + } + + &__right-icon { + margin-left: 5px; + align-items: center; + } + + &__content { + text-align: right; + flex: 1; + @include flex; + flex-wrap: nowrap; + overflow: hidden; + + &__text { + font-size: 14px; + color: $u-warning; + /* #ifndef APP-NVUE */ + // ��������������������������������������������������������� + padding-left: 100%; + word-break: keep-all; + white-space: nowrap; + animation: u-loop-animation 10s linear infinite both; + /* #endif */ + @include flex(row); + } + } + + } + + @keyframes u-loop-animation { + 0% { + transform: translate3d(0, 0, 0); + } + + 100% { + transform: translate3d(-100%, 0, 0); + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-row/props.js b/uni_modules/uview-ui/components/u-row/props.js new file mode 100644 index 0000000..4b71b87 --- /dev/null +++ b/uni_modules/uview-ui/components/u-row/props.js @@ -0,0 +1,19 @@ +export default { + props: { + // ���col��������������������������������������� + gutter: { + type: [String, Number], + default: uni.$u.props.row.gutter + }, + // ���������������������������������`start`(���`flex-start`)���`end`(���`flex-end`)���`center`���`around`(���`space-around`)���`between`(���`space-between`) + justify: { + type: String, + default: uni.$u.props.row.justify + }, + // ���������������������������������top���center���bottom + align: { + type: String, + default: uni.$u.props.row.align + } + } +} diff --git a/uni_modules/uview-ui/components/u-row/u-row.vue b/uni_modules/uview-ui/components/u-row/u-row.vue new file mode 100644 index 0000000..e608fc5 --- /dev/null +++ b/uni_modules/uview-ui/components/u-row/u-row.vue @@ -0,0 +1,93 @@ +<template> + <view + class="u-row" + ref="u-row" + :style="[rowStyle]" + @tap="clickHandler" + > + <slot /> + </view> +</template> + +<script> + // #ifdef APP-NVUE + const dom = uni.requireNativePlugin('dom') + // #endif + import props from './props.js'; + /** + * Row ��������������������� + * @description ��������������� 12 ������������������������������������ + * @tutorial https://www.uviewui.com/components/layout.html + * @property {String | Number} gutter ���������������������������������������������������px (������ 0 ) + * @property {String} justify ������������������(���������������������������) ������������`start`(���`flex-start`)���`end`(���`flex-end`)���`center`���`around`(���`space-around`)���`between`(���`space-between`) (������ 'start' ) + * @property {String} align ������������������ (������ 'center' ) + * @property {Object} customStyle ��������������������������������� + * + * @event {Function} click row��������� + * @example <u-row justify="space-between" customStyle="margin-bottom: 10px"></u-row> + */ + export default { + name: "u-row", + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + + } + }, + computed: { + uJustify() { + if (this.justify == 'end' || this.justify == 'start') return 'flex-' + this.justify + else if (this.justify == 'around' || this.justify == 'between') return 'space-' + this.justify + else return this.justify + }, + uAlignItem() { + if (this.align == 'top') return 'flex-start' + if (this.align == 'bottom') return 'flex-end' + else return this.align + }, + rowStyle() { + const style = { + alignItems: this.uAlignItem, + justifyContent: this.uJustify + } + // ���������u-row������������������������������������u-col������gutter��������������������������������������������������������������������������������� + if(this.gutter) { + style.marginLeft = uni.$u.addUnit(-Number(this.gutter)/2) + style.marginRight = uni.$u.addUnit(-Number(this.gutter)/2) + } + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) + } + }, + methods: { + clickHandler(e) { + this.$emit('click') + }, + async getComponentWidth() { + // ������������������������������������������������ + await uni.$u.sleep() + return new Promise(resolve => { + // uView��������������������������������������������� + // #ifndef APP-NVUE + this.$uGetRect('.u-row').then(res => { + resolve(res.width) + }) + // #endif + // #ifdef APP-NVUE + // nvue���dom������������������������ + dom.getComponentRect(this.$refs['u-row'], (res) => { + resolve(res.size.width) + }) + // #endif + }) + }, + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-row { + @include flex; + } +</style> diff --git a/uni_modules/uview-ui/components/u-safe-bottom/props.js b/uni_modules/uview-ui/components/u-safe-bottom/props.js new file mode 100644 index 0000000..7c11331 --- /dev/null +++ b/uni_modules/uview-ui/components/u-safe-bottom/props.js @@ -0,0 +1,5 @@ +export default { + props: { + + } +} diff --git a/uni_modules/uview-ui/components/u-safe-bottom/u-safe-bottom.vue b/uni_modules/uview-ui/components/u-safe-bottom/u-safe-bottom.vue new file mode 100644 index 0000000..fb858ea --- /dev/null +++ b/uni_modules/uview-ui/components/u-safe-bottom/u-safe-bottom.vue @@ -0,0 +1,56 @@ +<template> + <view + class="u-safe-bottom" + :style="[style]" + :class="[!isNvue && 'u-safe-area-inset-bottom']" + > + </view> +</template> + +<script> + import props from "./props.js"; + /** + * SafeBottom ��������������� + * @description ������������������������������IPhone X��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� + * @tutorial https://www.uviewui.com/components/safeAreaInset.html + * @property {type} prop_name + * @property {Object} customStyle ��������������������������������� + * + * @event {Function()} + * @example <u-status-bar></u-status-bar> + */ + export default { + name: "u-safe-bottom", + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + safeAreaBottomHeight: 0, + isNvue: false, + }; + }, + computed: { + style() { + const style = {}; + // #ifdef APP-NVUE + // nvue������������������js������������ + style.height = uni.$u.addUnit(uni.$u.sys().safeAreaInsets.bottom, 'px'); + // #endif + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)); + }, + }, + mounted() { + // #ifdef APP-NVUE + // ���������������nvue + this.isNvue = true; + // #endif + }, + }; +</script> + +<style lang="scss" scoped> + .u-safe-bottom { + /* #ifndef APP-NVUE */ + width: 100%; + /* #endif */ + } +</style> diff --git a/uni_modules/uview-ui/components/u-scroll-list/nvue.js b/uni_modules/uview-ui/components/u-scroll-list/nvue.js new file mode 100644 index 0000000..94bb056 --- /dev/null +++ b/uni_modules/uview-ui/components/u-scroll-list/nvue.js @@ -0,0 +1,28 @@ +// ������bindingx���������������������������������wxs���������������js��������������������������������������������������������������� +const BindingX = uni.requireNativePlugin('bindingx') + +export default { + methods: { + // ������������������������������������ + nvueScrollHandler(e) { + const anchor = this.$refs['u-scroll-list__scroll-view'].ref + const element = this.$refs['u-scroll-list__indicator__line__bar'].ref + const scrollLeft = e.contentOffset.x + const contentSize = e.contentSize.width + const { scrollWidth } = this + const barAllMoveWidth = this.indicatorWidth - this.indicatorBarWidth + // ������������iOS������������������������������������iOS������������2 + const actionNum = uni.$u.os() === 'ios' ? 2 : 1 + const expression = `(x / ${actionNum}) / ${contentSize - scrollWidth} * ${barAllMoveWidth}` + BindingX.bind({ + anchor, + eventType: 'scroll', + props: [{ + element, + property: 'transform.translateX', + expression + }] + }) + } + } +} diff --git a/uni_modules/uview-ui/components/u-scroll-list/other.js b/uni_modules/uview-ui/components/u-scroll-list/other.js new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/uni_modules/uview-ui/components/u-scroll-list/other.js diff --git a/uni_modules/uview-ui/components/u-scroll-list/props.js b/uni_modules/uview-ui/components/u-scroll-list/props.js new file mode 100644 index 0000000..765be54 --- /dev/null +++ b/uni_modules/uview-ui/components/u-scroll-list/props.js @@ -0,0 +1,34 @@ +export default { + props: { + // ������������������������ + indicatorWidth: { + type: [String, Number], + default: uni.$u.props.scrollList.indicatorWidth + }, + // ��������������� + indicatorBarWidth: { + type: [String, Number], + default: uni.$u.props.scrollList.indicatorBarWidth + }, + // ��������������������������� + indicator: { + type: Boolean, + default: uni.$u.props.scrollList.indicator + }, + // ������������������������ + indicatorColor: { + type: String, + default: uni.$u.props.scrollList.indicatorColor + }, + // ������������������������ + indicatorActiveColor: { + type: String, + default: uni.$u.props.scrollList.indicatorActiveColor + }, + // ���������������������������bottom���left���right������������ + indicatorStyle: { + type: [String, Object], + default: uni.$u.props.scrollList.indicatorStyle + } + } +} diff --git a/uni_modules/uview-ui/components/u-scroll-list/scrollWxs.wxs b/uni_modules/uview-ui/components/u-scroll-list/scrollWxs.wxs new file mode 100644 index 0000000..ce94f1d --- /dev/null +++ b/uni_modules/uview-ui/components/u-scroll-list/scrollWxs.wxs @@ -0,0 +1,50 @@ +function scroll(event, ownerInstance) { + // detail���������scroll-view������������������scroll-view���������������������������������scroll-view������������������ + var detail = event.detail + var scrollWidth = detail.scrollWidth + var scrollLeft = detail.scrollLeft + // ���������������������dataset������������������������������������xun���������������ji + var dataset = event.currentTarget.dataset + // ������scroll-view��������������������������� + // ������HX������(3.1.18)���������view������������������data-scrollWidth������wxs������������������������������������������������������������ + var scrollComponentWidth = dataset.scrollWidth || dataset.scrollwidth || 0 + // ��������������������������� + var indicatorWidth = dataset.indicatorWidth || dataset.indicatorwidth || 0 + var barWidth = dataset.barWidth || dataset.barwidth || 0 + // ���������������������������scroll-view������������������������������������(scroll-view������������������������������������������)������������������������������������������������ + // ������������(���������������������������������������)��������� + var x = scrollLeft / (scrollWidth - scrollComponentWidth) * (indicatorWidth - barWidth) + setBarStyle(ownerInstance, x) +} + +// ������webview������������������������scroll-view���������������������������������scroll������������������ +// ������������������������������������������������������������������������������������������������������������������������������������������������������������ +// ������������������������������������������������ +function scrolltolower(event, ownerInstance) { + ownerInstance.callMethod('scrollEvent', 'right') + // ���������������������dataset + var dataset = event.currentTarget.dataset + // ��������������������������� + var indicatorWidth = dataset.indicatorWidth || dataset.indicatorwidth || 0 + var barWidth = dataset.barWidth || dataset.barwidth || 0 + // scroll-view������������������������������������������������������������������������������������������������������������������ - ������������ + setBarStyle(ownerInstance, indicatorWidth - barWidth) +} + +function scrolltoupper(event, ownerInstance) { + ownerInstance.callMethod('scrollEvent', 'left') + // ���������������������������������������0������������������������������ + setBarStyle(ownerInstance, 0) +} + +function setBarStyle(ownerInstance, x) { + ownerInstance.selectComponent('.u-scroll-list__indicator__line__bar') && ownerInstance.selectComponent('.u-scroll-list__indicator__line__bar').setStyle({ + transform: 'translateX(' + x + 'px)' + }) +} + +module.exports = { + scroll: scroll, + scrolltolower: scrolltolower, + scrolltoupper: scrolltoupper +} diff --git a/uni_modules/uview-ui/components/u-scroll-list/u-scroll-list.vue b/uni_modules/uview-ui/components/u-scroll-list/u-scroll-list.vue new file mode 100644 index 0000000..4fe885a --- /dev/null +++ b/uni_modules/uview-ui/components/u-scroll-list/u-scroll-list.vue @@ -0,0 +1,224 @@ +<template> + <view + class="u-scroll-list" + ref="u-scroll-list" + > + <!-- #ifdef APP-NVUE --> + <!-- nvue������bindingX��������������������������������� --> + <scroller + class="u-scroll-list__scroll-view" + ref="u-scroll-list__scroll-view" + scroll-direction="horizontal" + :show-scrollbar="false" + :offset-accuracy="1" + @scroll="nvueScrollHandler" + > + <view class="u-scroll-list__scroll-view__content"> + <slot /> + </view> + </scroller> + <!-- #endif --> + <!-- #ifndef APP-NVUE --> + <!-- #ifdef MP-WEIXIN || APP-VUE || H5 || MP-QQ --> + <!-- ���������������������wxs --> + <scroll-view + class="u-scroll-list__scroll-view" + scroll-x + @scroll="wxs.scroll" + @scrolltoupper="wxs.scrolltoupper" + @scrolltolower="wxs.scrolltolower" + :data-scrollWidth="scrollWidth" + :data-barWidth="$u.getPx(indicatorBarWidth)" + :data-indicatorWidth="$u.getPx(indicatorWidth)" + :show-scrollbar="false" + :upper-threshold="0" + :lower-threshold="0" + > + <!-- #endif --> + <!-- #ifndef APP-NVUE || MP-WEIXIN || H5 || APP-VUE || MP-QQ --> + <!-- ������������������������������������js������ --> + <scroll-view + class="u-scroll-list__scroll-view" + scroll-x + @scroll="scrollHandler" + @scrolltoupper="scrolltoupperHandler" + @scrolltolower="scrolltolowerHandler" + :show-scrollbar="false" + :upper-threshold="0" + :lower-threshold="0" + > + <!-- #endif --> + <view class="u-scroll-list__scroll-view__content"> + <slot /> + </view> + </scroll-view> + <!-- #endif --> + <view + class="u-scroll-list__indicator" + v-if="indicator" + :style="[$u.addStyle(indicatorStyle)]" + > + <view + class="u-scroll-list__indicator__line" + :style="[lineStyle]" + > + <view + class="u-scroll-list__indicator__line__bar" + :style="[barStyle]" + ref="u-scroll-list__indicator__line__bar" + ></view> + </view> + </view> + </view> +</template> + +<script + src="./scrollWxs.wxs" + module="wxs" + lang="wxs" +></script> + +<script> +/** + * scrollList ������������������ + * @description ��������������������������������������������������������������������������������������������������������� + * @tutorial https://www.uviewui.com/components/scrollList.html + * @property {String | Number} indicatorWidth ������������������������ (������ 50 ) + * @property {String | Number} indicatorBarWidth ��������������� (������ 20 ) + * @property {Boolean} indicator ��������������������������� (������ true ) + * @property {String} indicatorColor ������������������������ (������ '#f2f2f2' ) + * @property {String} indicatorActiveColor ������������������������ (������ '#3c9cff' ) + * @property {String | Object} indicatorStyle ���������������������������bottom���left���right������������ + * @event {Function} left ������������������������ + * @event {Function} right ������������������������ + * @example + */ +// #ifdef APP-NVUE +const dom = uni.requireNativePlugin('dom') +import nvueMixin from "./nvue.js" +// #endif +import props from './props.js'; +export default { + name: 'u-scroll-list', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + // #ifdef APP-NVUE + mixins: [uni.$u.mpMixin, uni.$u.mixin, nvueMixin, props], + // #endif + data() { + return { + scrollInfo: { + scrollLeft: 0, + scrollWidth: 0 + }, + scrollWidth: 0 + } + }, + computed: { + // ��������������������������� + barStyle() { + const style = {} + // #ifndef APP-NVUE || MP-WEIXIN || H5 || APP-VUE || MP-QQ + // ������������js���������������������nvue������������wxs������������������������ + // ���������������������������scroll-view������������������������������������(scroll-view������������������������������������������)������������������������������������������������ + // ������������(���������������������������������������)��������� + const scrollLeft = this.scrollInfo.scrollLeft, + scrollWidth = this.scrollInfo.scrollWidth, + barAllMoveWidth = this.indicatorWidth - this.indicatorBarWidth + const x = scrollLeft / (scrollWidth - this.scrollWidth) * barAllMoveWidth + style.transform = `translateX(${ x }px)` + // #endif + // ��������������������������������������������������������������� + style.width = uni.$u.addUnit(this.indicatorBarWidth) + style.backgroundColor = this.indicatorActiveColor + return style + }, + lineStyle() { + const style = {} + // ������������������������������������������������������������ + style.width = uni.$u.addUnit(this.indicatorWidth) + style.backgroundColor = this.indicatorColor + return style + } + }, + mounted() { + this.init() + }, + methods: { + init() { + this.getComponentWidth() + }, + // #ifndef APP-NVUE || MP-WEIXIN || H5 || APP-VUE || MP-QQ + // scroll-view������������������ + scrollHandler(e) { + this.scrollInfo = e.detail + }, + scrolltoupperHandler() { + this.scrollEvent('left') + this.scrollInfo.scrollLeft = 0 + }, + scrolltolowerHandler() { + this.scrollEvent('right') + // ���������js���������������������������������������������this.scrollInfo������������������������������������ + // ���������������������computed������������������������������������������������������ + this.scrollInfo.scrollLeft = uni.$u.getPx(this.indicatorWidth) - uni.$u.getPx(this.indicatorBarWidth) + }, + // #endif + // + scrollEvent(status) { + this.$emit(status) + }, + // ��������������������� + async getComponentWidth() { + // ������������������������������dom������ + await uni.$u.sleep(30) + // #ifndef APP-NVUE + this.$uGetRect('.u-scroll-list').then(size => { + this.scrollWidth = size.width + }) + // #endif + + // #ifdef APP-NVUE + const ref = this.$refs['u-scroll-list'] + ref && dom.getComponentRect(ref, (res) => { + this.scrollWidth = res.size.width + }) + // #endif + }, + } +} +</script> + +<style lang="scss" scoped> +@import "../../libs/css/components.scss"; + +.u-scroll-list { + padding-bottom: 10px; + + &__scroll-view { + @include flex; + + &__content { + @include flex; + } + } + + &__indicator { + @include flex; + justify-content: center; + margin-top: 15px; + + &__line { + width: 60px; + height: 4px; + border-radius: 100px; + overflow: hidden; + + &__bar { + width: 20px; + height: 4px; + border-radius: 100px; + } + } + } +} +</style> diff --git a/uni_modules/uview-ui/components/u-search/props.js b/uni_modules/uview-ui/components/u-search/props.js new file mode 100644 index 0000000..df1b342 --- /dev/null +++ b/uni_modules/uview-ui/components/u-search/props.js @@ -0,0 +1,118 @@ +export default { + props: { + // ������������������round-���������square-������ + shape: { + type: String, + default: uni.$u.props.search.shape + }, + // ������������������������������#f2f2f2 + bgColor: { + type: String, + default: uni.$u.props.search.bgColor + }, + // ������������������ + placeholder: { + type: String, + default: uni.$u.props.search.placeholder + }, + // ������������������������ + clearabled: { + type: Boolean, + default: uni.$u.props.search.clearabled + }, + // ������������������ + focus: { + type: Boolean, + default: uni.$u.props.search.focus + }, + // ������������������������������������������ + showAction: { + type: Boolean, + default: uni.$u.props.search.showAction + }, + // ��������������������� + actionStyle: { + type: Object, + default: uni.$u.props.search.actionStyle + }, + // ������������������ + actionText: { + type: String, + default: uni.$u.props.search.actionText + }, + // ������������������������������������������ left|center|right + inputAlign: { + type: String, + default: uni.$u.props.search.inputAlign + }, + // input������������������������������������������������������������������������ + inputStyle: { + type: Object, + default: uni.$u.props.search.inputStyle + }, + // ��������������������� + disabled: { + type: Boolean, + default: uni.$u.props.search.disabled + }, + // ������������ + borderColor: { + type: String, + default: uni.$u.props.search.borderColor + }, + // ������������������������������������������������������ + searchIconColor: { + type: String, + default: uni.$u.props.search.searchIconColor + }, + // ��������������������� + color: { + type: String, + default: uni.$u.props.search.color + }, + // placeholder��������� + placeholderColor: { + type: String, + default: uni.$u.props.search.placeholderColor + }, + // ������������������������������������uView��������������������������� + searchIcon: { + type: String, + default: uni.$u.props.search.searchIcon + }, + searchIconSize: { + type: [Number, String], + default: uni.$u.props.search.searchIconSize + }, + // ������������������������������������������������������������������������������������"30px"���"30px 20px"��������� + margin: { + type: String, + default: uni.$u.props.search.margin + }, + // ������showAction���������������input������������������������ + animation: { + type: Boolean, + default: uni.$u.props.search.animation + }, + // ��������������������������� + value: { + type: String, + default: uni.$u.props.search.value + }, + // ������������������������������������-1������������������(������uniapp������) + maxlength: { + type: [String, Number], + default: uni.$u.props.search.maxlength + }, + // ������������������������px + height: { + type: [String, Number], + default: uni.$u.props.search.height + }, + // ��������������������� + label: { + type: [String, Number, null], + default: uni.$u.props.search.label + } + } +} diff --git a/uni_modules/uview-ui/components/u-search/u-search.vue b/uni_modules/uview-ui/components/u-search/u-search.vue new file mode 100644 index 0000000..f169c7f --- /dev/null +++ b/uni_modules/uview-ui/components/u-search/u-search.vue @@ -0,0 +1,303 @@ +<template> + <view + class="u-search" + @tap="clickHandler" + :style="[{ + margin: margin, + }, $u.addStyle(customStyle)]" + > + <view + class="u-search__content" + :style="{ + backgroundColor: bgColor, + borderRadius: shape == 'round' ? '100px' : '4px', + borderColor: borderColor, + }" + > + <template v-if="$slots.label || label !== null"> + <slot name="label"> + <text class="u-search__content__label">{{ label }}</text> + </slot> + </template> + <view class="u-search__content__icon"> + <u-icon + @tap="clickIcon" + :size="searchIconSize" + :name="searchIcon" + :color="searchIconColor ? searchIconColor : color" + ></u-icon> + </view> + <input + confirm-type="search" + @blur="blur" + :value="value" + @confirm="search" + @input="inputChange" + :disabled="disabled" + @focus="getFocus" + :focus="focus" + :maxlength="maxlength" + placeholder-class="u-search__content__input--placeholder" + :placeholder="placeholder" + :placeholder-style="`color: ${placeholderColor}`" + class="u-search__content__input" + type="text" + :style="[{ + textAlign: inputAlign, + color: color, + backgroundColor: bgColor, + height: $u.addUnit(height) + }, inputStyle]" + /> + <view + class="u-search__content__icon u-search__content__close" + v-if="keyword && clearabled && focused" + @tap="clear" + > + <u-icon + name="close" + size="11" + color="#ffffff" + customStyle="line-height: 12px" + ></u-icon> + </view> + </view> + <text + :style="[actionStyle]" + class="u-search__action" + :class="[(showActionBtn || show) && 'u-search__action--active']" + @tap.stop.prevent="custom" + >{{ actionText }}</text> + </view> +</template> + +<script> + import props from './props.js'; + + /** + * search ��������� + * @description ������������������������������������������������������������������������������������������������ + * @tutorial https://www.uviewui.com/components/search.html + * @property {String} shape ������������������round-���������square-��������������� 'round' ��� + * @property {String} bgColor ������������������������������ '#f2f2f2' ��� + * @property {String} placeholder ��������������������������� '������������������' ��� + * @property {Boolean} clearabled ��������������������������������� true ��� + * @property {Boolean} focus ��������������������������������� false ��� + * @property {Boolean} showAction ��������������������������������� true ��� + * @property {Object} actionStyle ������������������������������������ + * @property {String} actionText ��������������������������� '������' ��� + * @property {String} inputAlign ��������������������������������� ��������� 'left' ��� + * @property {Object} inputStyle ��������������������������������������� + * @property {Boolean} disabled ������������������������������ false ��� + * @property {String} borderColor ������������������������������������������������ (������ 'transparent' ) + * @property {String} searchIconColor ������������������������������������������������������ (������ '#909399' ) + * @property {Number | String} searchIconSize ������������������������������22 + * @property {String} color ������������������������������ '#606266' ��� + * @property {String} placeholderColor placeholder������������������ '#909399' ��� + * @property {String} searchIcon ������������������������������������uView��������������������������� (������ 'search' ) + * @property {String} margin ������������������������������������������������������������������������������������"30px" (������ '0' ) + * @property {Boolean} animation ��������������������������������������������� false ��� + * @property {String} value ������������������ + * @property {String | Number} maxlength ������������������������������������-1������������������ (������ '-1' ) + * @property {String | Number} height ������������������������px��������� 64 ��� + * @property {String | Number} label ��������������������������� + * @property {Object} customStyle ��������������������������������� + * + * @event {Function} change ������������������������������������ + * @event {Function} search ���������������������������������������������������������������������������������"������"������������ + * @event {Function} custom ��������������������������������� + * @event {Function} clear ��������������������������������� + * @example <u-search placeholder="���������������������" v-model="keyword"></u-search> + */ + export default { + name: "u-search", + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + keyword: '', + showClear: false, // ��������������������������������� + show: false, + // ������input��������������������������������������������������������������������������������� + focused: this.focus + // ��������������������� + // inputValue: this.value + }; + }, + watch: { + keyword(nVal) { + // ���������������������v-model������������������������ + this.$emit('input', nVal); + // ������change������������������������v-model������������������������������������������������������ + this.$emit('change', nVal); + }, + value: { + immediate: true, + handler(nVal) { + this.keyword = nVal; + } + } + }, + computed: { + showActionBtn() { + return !this.animation && this.showAction + } + }, + methods: { + // ������HX2.6.9 v-model������������������������������input������������������������������������ + inputChange(e) { + this.keyword = e.detail.value; + }, + // ������������ + // ���������������������������this.$refs��������������������������������� + clear() { + this.keyword = ''; + // ���������������������������������������������clear������������value������������������(���������) + this.$nextTick(() => { + this.$emit('clear'); + }) + }, + // ������������ + search(e) { + this.$emit('search', e.detail.value); + try { + // ������������ + uni.hideKeyboard(); + } catch (e) {} + }, + // ������������������������������������ + custom() { + this.$emit('custom', this.keyword); + try { + // ������������ + uni.hideKeyboard(); + } catch (e) {} + }, + // ������������ + getFocus() { + this.focused = true; + // ��������������������������������������������� + if (this.animation && this.showAction) this.show = true; + this.$emit('focus', this.keyword); + }, + // ������������ + blur() { + // ���������������������������������@touchstart���������������hx2.8.4��������������������������������������� + // ������������������������������������������������������������������������������@blur������������������������������������������������������������������ + setTimeout(() => { + this.focused = false; + }, 100) + this.show = false; + this.$emit('blur', this.keyword); + }, + // ������������������������disabled=true������������������������������������������������������������������������������������ + clickHandler() { + if (this.disabled) this.$emit('click'); + }, + // ������������������ + clickIcon() { + this.$emit('clickIcon'); + } + } + } +</script> + +<style lang="scss" scoped> +@import "../../libs/css/components.scss"; +$u-search-content-padding: 0 10px !default; +$u-search-label-color: $u-main-color !default; +$u-search-label-font-size: 14px !default; +$u-search-label-margin: 0 4px !default; +$u-search-close-size: 20px !default; +$u-search-close-radius: 100px !default; +$u-search-close-bgColor: #C6C7CB !default; +$u-search-close-transform: scale(0.82) !default; +$u-search-input-font-size: 14px !default; +$u-search-input-margin: 0 5px !default; +$u-search-input-color: $u-main-color !default; +$u-search-input-placeholder-color: $u-tips-color !default; +$u-search-action-font-size: 14px !default; +$u-search-action-color: $u-main-color !default; +$u-search-action-width: 0 !default; +$u-search-action-active-width: 40px !default; +$u-search-action-margin-left: 5px !default; + +/* #ifdef H5 */ +// iOS15���H5������hx������������������input type=search������������������������������������������������ +[type="search"]::-webkit-search-decoration { + display: none; +} +/* #endif */ + +.u-search { + @include flex(row); + align-items: center; + flex: 1; + + &__content { + @include flex; + align-items: center; + padding: $u-search-content-padding; + flex: 1; + justify-content: space-between; + border-width: 1px; + border-color: transparent; + border-style: solid; + overflow: hidden; + + &__icon { + @include flex; + align-items: center; + } + + &__label { + color: $u-search-label-color; + font-size: $u-search-label-font-size; + margin: $u-search-label-margin; + } + + &__close { + width: $u-search-close-size; + height: $u-search-close-size; + border-top-left-radius: $u-search-close-radius; + border-top-right-radius: $u-search-close-radius; + border-bottom-left-radius: $u-search-close-radius; + border-bottom-right-radius: $u-search-close-radius; + background-color: $u-search-close-bgColor; + @include flex(row); + align-items: center; + justify-content: center; + transform: $u-search-close-transform; + } + + &__input { + flex: 1; + font-size: $u-search-input-font-size; + line-height: 1; + margin: $u-search-input-margin; + color: $u-search-input-color; + + &--placeholder { + color: $u-search-input-placeholder-color; + } + } + } + + &__action { + font-size: $u-search-action-font-size; + color: $u-search-action-color; + width: $u-search-action-width; + overflow: hidden; + transition-property: width; + transition-duration: 0.3s; + /* #ifndef APP-NVUE */ + white-space: nowrap; + /* #endif */ + text-align: center; + + &--active { + width: $u-search-action-active-width; + margin-left: $u-search-action-margin-left; + } + } +} +</style> diff --git a/uni_modules/uview-ui/components/u-skeleton/props.js b/uni_modules/uview-ui/components/u-skeleton/props.js new file mode 100644 index 0000000..ed3ba5a --- /dev/null +++ b/uni_modules/uview-ui/components/u-skeleton/props.js @@ -0,0 +1,59 @@ +export default { + props: { + // ������������������������ + loading: { + type: Boolean, + default: uni.$u.props.skeleton.loading + }, + // ������������������������ + animate: { + type: Boolean, + default: uni.$u.props.skeleton.animate + }, + // ��������������������� + rows: { + type: [String, Number], + default: uni.$u.props.skeleton.rows + }, + // ������������������������ + rowsWidth: { + type: [String, Number, Array], + default: uni.$u.props.skeleton.rowsWidth + }, + // ������������������������ + rowsHeight: { + type: [String, Number, Array], + default: uni.$u.props.skeleton.rowsHeight + }, + // ��������������������������� + title: { + type: Boolean, + default: uni.$u.props.skeleton.title + }, + // ��������������������� + titleWidth: { + type: [String, Number], + default: uni.$u.props.skeleton.titleWidth + }, + // ��������������������� + titleHeight: { + type: [String, Number], + default: uni.$u.props.skeleton.titleHeight + }, + // ��������������������������� + avatar: { + type: Boolean, + default: uni.$u.props.skeleton.avatar + }, + // ��������������������� + avatarSize: { + type: [String, Number], + default: uni.$u.props.skeleton.avatarSize + }, + // ���������������������������circle-���������square-������ + avatarShape: { + type: String, + default: uni.$u.props.skeleton.avatarShape + } + } +} diff --git a/uni_modules/uview-ui/components/u-skeleton/u-skeleton.vue b/uni_modules/uview-ui/components/u-skeleton/u-skeleton.vue new file mode 100644 index 0000000..efa649e --- /dev/null +++ b/uni_modules/uview-ui/components/u-skeleton/u-skeleton.vue @@ -0,0 +1,244 @@ +<template> + <view class="u-skeleton"> + <view + class="u-skeleton__wrapper" + ref="u-skeleton__wrapper" + v-if="loading" + style="display: flex; flex-direction: row;" + > + <view + class="u-skeleton__wrapper__avatar" + v-if="avatar" + :class="[`u-skeleton__wrapper__avatar--${avatarShape}`, animate && 'animate']" + :style="{ + height: $u.addUnit(avatarSize), + width: $u.addUnit(avatarSize) + }" + ></view> + <view + class="u-skeleton__wrapper__content" + ref="u-skeleton__wrapper__content" + style="flex: 1;" + > + <view + class="u-skeleton__wrapper__content__title" + v-if="title" + :style="{ + width: uTitleWidth, + height: $u.addUnit(titleHeight), + }" + :class="[animate && 'animate']" + ></view> + <view + class="u-skeleton__wrapper__content__rows" + :class="[animate && 'animate']" + v-for="(item, index) in rowsArray" + :key="index" + :style="{ + width: item.width, + height: item.height, + marginTop: item.marginTop + }" + > + + </view> + </view> + </view> + <slot v-else /> + </view> +</template> + +<script> + import props from './props.js'; + // #ifdef APP-NVUE + // ������weex������������KPI���������������������������������������������������������������������������dom��������������������� + const dom = uni.requireNativePlugin('dom') + const animation = uni.requireNativePlugin('animation') + // #endif + /** + * Skeleton ��������� + * @description ������������������������������������������������������������������������������������������������������������������������������������������������ + * @tutorial https://www.uviewui.com/components/skeleton.html + * @property {Boolean} loading ���������������������������������������false��������������������������� (������ true ) + * @property {Boolean} animate ������������������������ (������ true ) + * @property {String | Number} rows ��������������������� (������ 0 ) + * @property {String | Number | Array} rowsWidth ������������������������������������������������������������������������������������������������������������������������������������ (������ '100%' ) + * @property {String | Number | Array} rowsHeight ��������������� (������ 18 ) + * @property {Boolean} title ��������������������������� (������ true ) + * @property {String | Number} titleWidth ��������������� (������ '50%' ) + * @property {String | Number} titleHeight ��������������� (������ 18 ) + * @property {Boolean} avatar ��������������������������� (������ false ) + * @property {String | Number} avatarSize ��������������������� (������ 32 ) + * @property {String} avatarShape ���������������������������circle-���������square-������ (������ 'circle' ) + * @example <u-search placeholder="���������������������" v-model="keyword"></u-search> + */ + export default { + name: 'u-skeleton', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + width: 0, + } + }, + watch: { + loading() { + this.getComponentWidth() + } + }, + computed: { + rowsArray() { + if (/%$/.test(this.rowsHeight)) { + uni.$u.error('rowsHeight������������������������������') + } + const rows = [] + for (let i = 0; i < this.rows; i++) { + let item = {}, + // ��������������������������������������� + rowWidth = uni.$u.test.array(this.rowsWidth) ? (this.rowsWidth[i] || (i === this.row - 1 ? '70%' : '100%')) : i === + this.rows - 1 ? '70%' : this.rowsWidth, + rowHeight = uni.$u.test.array(this.rowsHeight) ? (this.rowsHeight[i] || '18px') : this.rowsHeight + // ���������title������������������������������������������������������������������������������title������������������������������������������������������ + // ������������������������������������weex���������������������������������������������css��������������� + item.marginTop = !this.title && i === 0 ? 0 : this.title && i === 0 ? '20px' : '12px' + // ������������������������������������������������px������������nvue������������������������ + if (/%$/.test(rowWidth)) { + // ������parseInt���������������������������������������������������100��������������������������� + item.width = uni.$u.addUnit(this.width * parseInt(rowWidth) / 100) + } else { + item.width = uni.$u.addUnit(rowWidth) + } + item.height = uni.$u.addUnit(rowHeight) + rows.push(item) + } + // console.log(rows); + return rows + }, + uTitleWidth() { + let tWidth = 0 + if (/%$/.test(this.titleWidth)) { + // ������parseInt���������������������������������������������������100��������������������������� + tWidth = uni.$u.addUnit(this.width * parseInt(this.titleWidth) / 100) + } else { + tWidth = uni.$u.addUnit(this.titleWidth) + } + return uni.$u.addUnit(tWidth) + }, + + }, + mounted() { + this.init() + }, + methods: { + init() { + this.getComponentWidth() + // #ifdef APP-NVUE + this.loading && this.animate && this.setNvueAnimation() + // #endif + }, + async setNvueAnimation() { + // #ifdef APP-NVUE + // ���������opacity:1��������������������������������������������������� + await uni.$u.sleep(500) + const skeleton = this.$refs['u-skeleton__wrapper']; + skeleton && this.loading && this.animate && animation.transition(skeleton, { + styles: { + opacity: 0.5 + }, + duration: 600, + }, () => { + // ������������������������loading���������������������������������������������������������opacity: 1��������������� + // ������������opacity: 0.5������������ + animation.transition(skeleton, { + styles: { + opacity: 1 + }, + duration: 600, + }, () => { + // ���������loading������������������������ + this.loading && this.animate && this.setNvueAnimation() + }) + }) + // #endif + }, + // ��������������������� + async getComponentWidth() { + // ������������������������������dom������ + await uni.$u.sleep(20) + // #ifndef APP-NVUE + this.$uGetRect('.u-skeleton__wrapper__content').then(size => { + this.width = size.width + }) + // #endif + + // #ifdef APP-NVUE + const ref = this.$refs['u-skeleton__wrapper__content'] + ref && dom.getComponentRect(ref, (res) => { + this.width = res.size.width + }) + // #endif + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + @mixin background { + /* #ifdef APP-NVUE */ + background-color: #F1F2F4; + /* #endif */ + /* #ifndef APP-NVUE */ + background: linear-gradient(90deg, #F1F2F4 25%, #e6e6e6 37%, #F1F2F4 50%); + background-size: 400% 100%; + /* #endif */ + } + + .u-skeleton { + flex: 1; + + &__wrapper { + @include flex(row); + + &__avatar { + @include background; + margin-right: 15px; + + &--circle { + border-radius: 100px; + } + + &--square { + border-radius: 4px; + } + } + + &__content { + flex: 1; + + &__rows, + &__title { + @include background; + border-radius: 3px; + } + } + } + } + + /* #ifndef APP-NVUE */ + .animate { + animation: skeleton 1.8s ease infinite + } + + @keyframes skeleton { + 0% { + background-position: 100% 50% + } + + 100% { + background-position: 0 50% + } + } + + /* #endif */ +</style> diff --git a/uni_modules/uview-ui/components/u-slider/mpother.js b/uni_modules/uview-ui/components/u-slider/mpother.js new file mode 100644 index 0000000..040c848 --- /dev/null +++ b/uni_modules/uview-ui/components/u-slider/mpother.js @@ -0,0 +1,113 @@ +/** + * ���������������js������������slider + */ +export default { + watch: { + value(n) { + // ���������������������������������������������value��������������������������������������������������������� + if (this.status === 'end') { + this.updateSliderPlacement(n, true) + } + } + }, + mounted() { + this.init() + }, + methods: { + init() { + this.getSliderRect() + }, + // ������slider������ + getSliderRect() { + // ������������������������������ + setTimeout(() => { + this.$uGetRect('.u-slider').then((rect) => { + this.sliderRect = rect + this.updateSliderPlacement(this.value, true) + }) + }, 10) + }, + // ������������������ + canNotDo() { + return this.disabled + }, + // ������������������������X������������ + getTouchX(e) { + return e.touches[0].clientX + }, + formatStep(value) { + // ��������������������������������� + return Math.round(Math.max(this.min, Math.min(value, this.max)) / this.step) * this.step + }, + // ������������ + emitEvent(event, value) { + this.$emit(event, value || this.value) + }, + // ��������������������������� + setTouchStatus(status) { + this.status = status + }, + onTouchStart(e) { + if (this.canNotDo()) { + return + } + // ������������������������������������������ + this.emitEvent('start') + this.setTouchStatus('start') + }, + onTouchMove(e) { + if (this.canNotDo()) { + return + } + // ������������������������������������������������������������������������������������������������ + const x = this.getTouchX(e) + const { left, width } = this.sliderRect + const distanceX = x - left + // ������������������������������������������������������������������������������������������������������������ + // ������������������������������������������������step������������������������ + const percent = (distanceX / width) * 100 + this.setTouchStatus('moving') + this.updateSliderPlacement(percent, true, 'moving') + }, + onTouchEnd() { + if (this.canNotDo()) { + return + } + this.emitEvent('end') + this.setTouchStatus('end') + }, + // ��������������������� + updateSliderPlacement(value, drag, event) { + // ������������������������������������step��������������� + const { width } = this.sliderRect + const percent = this.formatStep(value) + // ������������������ + const barStyle = { + width: `${percent / 100 * width}px` + } + // ������������������������������ + if (drag === true) { + barStyle.transition = 'none' + } else { + // ������������������������������������������������������css������������������ + delete barStyle.transition + } + // ������value��� + this.$emit('input', percent) + // ��������������� + if (event) { + this.emitEvent(event, percent) + } + this.barStyle = barStyle + }, + onClick(e) { + if (this.canNotDo()) { + return + } + // ���������������������������������������������onTouchMove������������ + const { left, width } = this.sliderRect + const value = ((e.detail.x - left) / width) * 100 + this.updateSliderPlacement(value, false, 'click') + } + } +} diff --git a/uni_modules/uview-ui/components/u-slider/mpwxs.js b/uni_modules/uview-ui/components/u-slider/mpwxs.js new file mode 100644 index 0000000..f263911 --- /dev/null +++ b/uni_modules/uview-ui/components/u-slider/mpwxs.js @@ -0,0 +1,42 @@ +export default { + data() { + return { + sliderRect: {}, + info: { + width: null, + left: null, + step: this.step, + disabled: this.disabled, + min: this.min, + max: this.max, + value: this.value + } + } + }, + mounted() { + this.init() + }, + methods: { + init() { + this.getSliderRect() + }, + // ������slider������ + getSliderRect() { + // ������������������������������ + uni.$u.sleep().then(() => { + this.$uGetRect('.u-slider').then((rect) => { + this.info.width = rect.width + this.info.left = rect.left + }) + }) + }, + // ������������wxs���������������������v-model������������ + updateValue(value) { + this.$emit('input', value) + }, + // ������������wxs��������������������� + emitEvent(e) { + this.$emit(e.event, e.value ? e.value : this.value) + } + } +} diff --git a/uni_modules/uview-ui/components/u-slider/mpwxs.wxs b/uni_modules/uview-ui/components/u-slider/mpwxs.wxs new file mode 100644 index 0000000..847df4a --- /dev/null +++ b/uni_modules/uview-ui/components/u-slider/mpwxs.wxs @@ -0,0 +1,121 @@ +/** + * ������wxs������������slider + * ���������������QQ���H5���Vue���������������iOS + */ +/** + * ������������������ + * @param {Object} e + * @param {Object} ownerInstance + */ +function onTouchMove(e, ownerInstance) { + // wxs������������������������instance������������������������������������������������������������������������������������������������dataset������������������������ + // https://developers.weixin.qq.com/miniprogram/dev/framework/view/interactive-animation.html + var instance = e.instance; + // getState()���������������������������instance���������������������data��������������������������������������������������������������������� + var state = instance.getState() + + // ��������������������������������� + var mp = state.mp + if(mp.disabled) { + return + } + + var distanceX = getTouchX(e) - mp.left + // ������������������������������������������������������������������������������������step������1������������������������������ + var percent = (distanceX / mp.width) * 100 + + updateSliderPlacement(instance, ownerInstance, percent, 'moving') + + // ������������������������������������������������������������������������������������������������������������ + e.stopPropagation && e.stopPropagation() + e.preventDefault && e.preventDefault() +} + +function onClick(e, ownerInstance) { + var instance = e.instance + var state = instance.getState() + var mp = state.mp + if(mp.disabled) { + return + } + + // ���������������������������������������������onTouchMove������������ + var value = ((e.detail.x - mp.left) / mp.width) * 100 + updateSliderPlacement(instance, ownerInstance, value, 'click') +} + +function sizeReady(newValue, oldValue, ownerInstance, instance) { + // ��������������������������������������������������������������������������������������������������� + if(!newValue || newValue.disabled) { + return + } + var state = instance.getState() + state.mp = newValue + updateSliderPlacement(instance, ownerInstance, newValue.value) +} + +// ��������������������� +function updateSliderPlacement(instance, ownerInstance, value, event) { + var state = instance.getState() + var mp = state.mp + if(mp.disabled) { + return + } + + var percent = 0 + if (mp.step > 1) { + // ������step������������1������������������������������������Math.round������������ + percent = Math.round(Math.max(mp.min, Math.min(value, mp.max)) / mp.step) * mp.step + } else { + // ���step=1���������������������������������wxs��������������������������������������������������������� + percent = Math.max(mp.min, Math.min(value, mp.max)) + } + // ��������������������� + var gapInstance = ownerInstance.selectComponent('.u-slider__gap') + // ���������������������������transition������������������������������ + gapInstance[event === 'click' ? 'addClass' : 'removeClass']('u-slider__gap--ani') + // ���������������������������������v-model������������ + ownerInstance.callMethod('updateValue', Math.round(percent)) + if(event) { + ownerInstance.callMethod('emitEvent', { + event: event, + value: Math.round(percent) + }) + } + + // ������������������ + gapInstance.requestAnimationFrame(function() { + gapInstance.setStyle({ + width: percent / 100 * mp.width + 'px', + }) + }) +} + +// ������������ +function onTouchStart(e, ownerInstance) { + ownerInstance.callMethod('emitEvent', { + event: 'start', + value: null + }) +} + +// ������������ +function onTouchEnd(e, ownerInstance) { + ownerInstance.callMethod('emitEvent', { + event: 'end', + value: null + }) +} + +// ������������������������X������������ +function getTouchX(e) { + return e.touches[0].clientX +} + +module.exports = { + onTouchStart: onTouchStart, + onTouchMove: onTouchMove, + onTouchEnd: onTouchEnd, + sizeReady: sizeReady, + onClick: onClick +} diff --git "a/uni_modules/uview-ui/components/u-slider/nvue - \345\211\257\346\234\254.js" "b/uni_modules/uview-ui/components/u-slider/nvue - \345\211\257\346\234\254.js" new file mode 100644 index 0000000..df62349 --- /dev/null +++ "b/uni_modules/uview-ui/components/u-slider/nvue - \345\211\257\346\234\254.js" @@ -0,0 +1,180 @@ +/** + * ������bindingx������������slider + * ���������������nvue��� + */ +// ������bindingx���������������������������������wxs���������������js��������������������������������������������������������������� +const BindingX = uni.requireNativePlugin('bindingx') +// nvue������dom���������������������dom��������������� +const dom = uni.requireNativePlugin('dom') +// nvue���������������������������������������������uni.animation������������uni.animation������������nvue +const animation = uni.requireNativePlugin('animation') + +export default { + data() { + return { + // bindingx��������������������������������� + panEvent: null, + // ������������������������ + moving: false, + // ������������������ + x: 0, + // ������������������������������������������������������������������������ + touching: false, + changeFromInside: false + } + }, + watch: { + // ������vlaue������������������������������������������������v-model��������������������� + // ������������������������������������������slider���v-model������������ + value(n) { + if (!this.changeFromInside) { + this.initX() + } else { + this.changeFromInside = false + } + } + }, + mounted() { + this.init() + }, + methods: { + init() { + this.getSliderRect() + }, + // ������������������ + // ������slider������ + getSliderRect() { + // ������������������������������ + // ������nvue���dom��������������������������� + setTimeout(() => { + dom.getComponentRect(this.$refs['slider'], res => { + this.sliderRect = res.size + this.initX() + }) + }, 10) + }, + // ��������������������� + initButtonStyle({ + barStyle, + buttonWrapperStyle + }) { + this.barStyle = barStyle + this.buttonWrapperStyle = buttonWrapperStyle + }, + emitEvent(event, value) { + this.$emit(event, value ? value : this.value) + }, + formatStep(value) { + // ��������������������������������� + return Math.round(Math.max(this.min, Math.min(value, this.max)) / this.step) * this.step + }, + // ������������ + onTouchStart(e) { + // ������������������������������������������������������������������������������������������������������������ + e.stopPropagation && e.stopPropagation() + e.preventDefault && e.preventDefault() + if (this.moving || this.disabled) { + // ������������������������ + if (this.panEvent?.token != 0) { + BindingX.unbind({ + token: this.panEvent.token, + // pan��������������� + eventType: 'pan' + }) + this.gesToken = 0 + } + return + } + + this.moving = true + this.touching = true + + // ������������ref + const button = this.$refs['nvue-button'].ref + const gap = this.$refs['nvue-gap'].ref + + const { + min, + max, + step + } = this + const { + left, + width + } = this.sliderRect + + // ���������������������������x��������������������������������������� + let exporession = `(${this.x} + x)` + // ������������x������������������������������������������������min���max������������ + exporession = `(${exporession} / ${width}) * 100` + if (step > 1) { + // ������step������������1������������������������������������Math.round������������ + exporession = `round(max(${min}, min(${exporession}, ${max})) / ${step}) * ${step}` + } else { + // ���step=1���������������������������������bindingx��������������������������������������������������������� + exporession = `max(${min}, min(${exporession}, ${max}))` + } + // ������������������������������������px��� + exporession = `${exporession} / 100 * ${width}` + // ��������������������������������������� + const { + sliderWidth + } = this.sliderRect + exporession = `min(${sliderWidth}, ${exporession})` + // ��������������������������������������������������������������������� + const buttonExpression = `${exporession} - ${this.blockHeight / 2}` + // ������������KPI������������BindingX + this.panEvent = BindingX.bind({ + anchor: button, + eventType: 'pan', + props: [{ + element: gap, + // ������width��������������������������� + property: 'width', + expression + }, { + element: button, + // ������width��������������������������� + property: 'transform.translateX', + expression: buttonExpression + }] + }, (e) => { + if (e.state === 'end' || e.state === 'exit') { + // + this.x = uni.$u.range(0, left + width, e.deltaX + this.x) + // ������������������������������������������������������������������������v-model������ + const value = (this.x / width) * 100 + const percent = this.formatStep(value) + // ������value��� + this.$emit('input', percent) + // ���������������������value���watch������������������������������������������������ + this.changeFromInside = true + this.moving = false + this.touching = false + } + }) + }, + // ���value������������������������x������������������ + initX() { + const { + left, + width + } = this.sliderRect + // ������x������������������������������������������������������������bindingX������������������������������������������������������������ + // ���������������������������������������������������������������weex������������������������KPI(������������������)������������������������ + this.x = this.value / 100 * width + // ������������������ + const barStyle = { + width: this.x + 'px' + } + // ������������������ + const buttonWrapperStyle = { + transform: `translateX(${this.x - this.blockHeight / 2}px)` + } + this.initButtonStyle({ + barStyle, + buttonWrapperStyle + }) + } + } +} diff --git a/uni_modules/uview-ui/components/u-slider/nvue.js b/uni_modules/uview-ui/components/u-slider/nvue.js new file mode 100644 index 0000000..344dce8 --- /dev/null +++ b/uni_modules/uview-ui/components/u-slider/nvue.js @@ -0,0 +1,193 @@ +/** + * ������bindingx������������slider + * ���������������nvue��� + */ +// ������bindingx���������������������������������wxs���������������js��������������������������������������������������������������� +const BindingX = uni.requireNativePlugin('bindingx') +// nvue������dom���������������������dom��������������� +const dom = uni.requireNativePlugin('dom') +// nvue���������������������������������������������uni.animation������������uni.animation������������nvue +const animation = uni.requireNativePlugin('animation') + +export default { + data() { + return { + // ������������������ + x: 0, + // ������������������������������������������������������������������������ + touching: false, + changeFromInside: false + } + }, + watch: { + // ������vlaue������������������������������������������������v-model��������������������� + // ������������������������������������������slider���v-model������������ + value(n) { + if (!this.changeFromInside) { + this.initX() + } else { + this.changeFromInside = false + } + } + }, + mounted() { + this.init() + }, + methods: { + init() { + // ������������������������ + this.getSliderRect().then((size) => { + this.sliderRect = size + this.initX() + }) + }, + // ������������������ + // ������slider������ + getSliderRect() { + // ������������������������������ + // ������nvue���dom��������������������������� + return new Promise((resolve) => { + this.$nextTick(() => { + dom.getComponentRect(this.$refs.slider, (res) => { + resolve(res.size) + }) + }) + }) + }, + // ��������������������� + initButtonStyle({ + barStyle, + buttonWrapperStyle + }) { + this.barStyle = barStyle + this.buttonWrapperStyle = buttonWrapperStyle + }, + emitEvent(event, value) { + this.$emit(event, value || this.value) + }, + // ������������ + async onTouchStart(e) { + // if (this.disabled) return + // // ������������������������������������������������������������������������������������������������������������ + // e.stopPropagation && e.stopPropagation() + // e.preventDefault && e.preventDefault() + // // ��������������������������� + // this.sliderRect = await this.getSliderRect() + // // ��������������������������������������� + // this.touchStart(e) + // this.startValue = this.format(this.value) + // this.dragStatus = 'start' + + // ��������������������������������������� + // this.touchStart(e) + }, + // ������������ + onTouchMove(e) { + // if (this.disabled) return; + // if (this.dragStatus === 'start') { + // this.$emit('drag-start') + // } + // // ���������������������������������������������������������touch mixin��� + // this.touchMove(e) + // this.dragStatus = 'draging' + // const { + // width: sliderWidth + // } = this.sliderRect + // const diff = (this.deltaX / sliderWidth) * this.getRange() + // this.newValue = this.startValue + diff + // this.updateValue(this.newValue, false, true) + // ������������ref + // const button = this.$refs['nvue-button'].ref + // const gap = this.$refs['nvue-gap'].ref + + // animation.transition(gap, { + // styles: { + // width: `${this.startX + this.deltaX}px` + // } + // }) + // // console.log(this.startX + this.deltaX); + // animation.transition(button, { + // styles: { + // transform: `translateX(${this.startX + this.deltaX}px)` + // } + // }) + // this.barStyle = { + // width: `${this.startX + this.deltaX}px` + // } + const { + x + } = this.getTouchPoint(e) + this.buttonWrapperStyle = { + transform: `translateX(${x}px)` + } + // this.buttonWrapperStyle = { + // transform: `translateX(${this.format(this.startX + this.deltaX)}px)` + // } + }, + // onTouchEnd() { + // if (this.disabled) return; + // if (this.dragStatus === 'draging') { + // this.updateValue(this.newValue, true) + // this.$emit('drag-end'); + // } + // }, + updateValue(value, end, drag) { + value = this.format(value) + const { + width: sliderWidth + } = this.sliderRect + const width = `${((value - this.min) * sliderWidth) / this.getRange()}` + this.value = value + this.barStyle = { + width: `${width}px` + } + // console.log('width', width); + if (drag) { + this.$emit('drag', { + value + }) + } + if (end) { + this.$emit('change', value) + } + if ((drag || end)) { + this.changeFromInside = true + this.$emit('update', value) + } + }, + // ���value������������������������x������������������ + initX() { + const { + left, + width + } = this.sliderRect + // ������x������������������������������������������������������������bindingX������������������������������������������������������������ + // ���������������������������������������������������������������weex������������������������KPI(������������������)������������������������ + this.x = this.value / 100 * width + // ������������������ + const barStyle = { + width: `${this.x}px` + } + // ������������������ + const buttonWrapperStyle = { + transform: `translateX(${this.x - this.blockHeight / 2}px)` + } + this.initButtonStyle({ + barStyle, + buttonWrapperStyle + }) + }, + // ���������������������������������������������������������step������������������step������1������������10������������������11,12px��������� + // ������������������������������������������������������16,17px���������������������������������������20px��������������������������� + format(value) { + return Math.round(uni.$u.range(this.min, this.max, value) / this.step) * this.step + }, + getRange() { + const { + max, + min + } = this + return max - min + } + } +} diff --git a/uni_modules/uview-ui/components/u-slider/props.js b/uni_modules/uview-ui/components/u-slider/props.js new file mode 100644 index 0000000..433a7b5 --- /dev/null +++ b/uni_modules/uview-ui/components/u-slider/props.js @@ -0,0 +1,54 @@ +export default { + props: { + // ��������������� + min: { + type: [Number, String], + default: uni.$u.props.slider.min + }, + // ��������������� + max: { + type: [Number, String], + default: uni.$u.props.slider.max + }, + // ��������������������������� 0���������������(max - min)������ + step: { + type: [Number, String], + default: uni.$u.props.slider.step + }, + // ������������ + value: { + type: [Number, String], + default: uni.$u.props.slider.value + }, + // ��������������������������������������� + activeColor: { + type: String, + default: uni.$u.props.slider.activeColor + }, + // ��������������������������������������� + inactiveColor: { + type: String, + default: uni.$u.props.slider.inactiveColor + }, + // ��������������������������������� 12 - 28 + blockSize: { + type: [Number, String], + default: uni.$u.props.slider.blockSize + }, + // ��������������� + blockColor: { + type: String, + default: uni.$u.props.slider.blockColor + }, + // ������������ + disabled: { + type: Boolean, + default: uni.$u.props.slider.disabled + }, + // ������������������������������ + showValue: { + type: Boolean, + default: uni.$u.props.slider.showValue + } + } +} diff --git a/uni_modules/uview-ui/components/u-slider/u-slider.vue b/uni_modules/uview-ui/components/u-slider/u-slider.vue new file mode 100644 index 0000000..80ebbed --- /dev/null +++ b/uni_modules/uview-ui/components/u-slider/u-slider.vue @@ -0,0 +1,55 @@ +<template> + <view + class="u-slider" + :style="[$u.addStyle(customStyle)]" + > + <slider + :min="min" + :max="max" + :step="step" + :value="value" + :activeColor="activeColor" + :inactiveColor="inactiveColor" + :blockSize="$u.getPx(blockSize)" + :blockColor="blockColor" + :showValue="showValue" + :disabled="disabled" + @changing="changingHandler" + @change="changeHandler" + ></slider> + </view> +</template> + +<script> + import props from './props.js' + export default { + name: 'u--slider', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + methods: { + // ��������������������� + changingHandler(e) { + const { + value + } = e.detail + // ������v-model������ + this.$emit('input', value) + // ������������ + this.$emit('changing', value) + }, + // ��������������������� + changeHandler(e) { + const { + value + } = e.detail + // ������v-model������ + this.$emit('input', value) + // ������������ + this.$emit('change', value) + } + }, + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; +</style> diff --git a/uni_modules/uview-ui/components/u-status-bar/props.js b/uni_modules/uview-ui/components/u-status-bar/props.js new file mode 100644 index 0000000..64b9e63 --- /dev/null +++ b/uni_modules/uview-ui/components/u-status-bar/props.js @@ -0,0 +1,8 @@ +export default { + props: { + bgColor: { + type: String, + default: uni.$u.props.statusBar.bgColor + } + } +} diff --git a/uni_modules/uview-ui/components/u-status-bar/u-status-bar.vue b/uni_modules/uview-ui/components/u-status-bar/u-status-bar.vue new file mode 100644 index 0000000..ed91373 --- /dev/null +++ b/uni_modules/uview-ui/components/u-status-bar/u-status-bar.vue @@ -0,0 +1,46 @@ +<template> + <view + :style="[style]" + class="u-status-bar" + > + <slot /> + </view> +</template> + +<script> + import props from './props.js'; + /** + * StatbusBar ��������������� + * @description ��������������������������������������������������������������������������������������������������������������������������� + * @tutorial https://uviewui.com/components/statusBar.html + * @property {String} bgColor ��������� (������ 'transparent' ) + * @property {String | Object} customStyle ��������������� + * @example <u-status-bar></u-status-bar> + */ + export default { + name: 'u-status-bar', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + } + }, + computed: { + style() { + const style = {} + // ���������������������������������������������������������������������css���������������������������������������js��������������� + style.height = uni.$u.addUnit(uni.$u.sys().statusBarHeight, 'px') + style.backgroundColor = this.bgColor + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) + } + }, + } +</script> + +<style lang="scss" scoped> + .u-status-bar { + // nvue���������100%���������nvue���������������100%������������������������������100%��������� + /* #ifndef APP-NVUE */ + width: 100%; + /* #endif */ + } +</style> diff --git a/uni_modules/uview-ui/components/u-steps-item/props.js b/uni_modules/uview-ui/components/u-steps-item/props.js new file mode 100644 index 0000000..825727a --- /dev/null +++ b/uni_modules/uview-ui/components/u-steps-item/props.js @@ -0,0 +1,24 @@ +export default { + props: { + // ������ + title: { + type: [String, Number], + default: uni.$u.props.stepsItem.title + }, + // ������������ + desc: { + type: [String, Number], + default: uni.$u.props.stepsItem.desc + }, + // ������������ + iconSize: { + type: [String, Number], + default: uni.$u.props.stepsItem.iconSize + }, + // ������������������������������������ + error: { + type: Boolean, + default: uni.$u.props.stepsItem.error + } + } +} diff --git a/uni_modules/uview-ui/components/u-steps-item/u-steps-item.vue b/uni_modules/uview-ui/components/u-steps-item/u-steps-item.vue new file mode 100644 index 0000000..342fa63 --- /dev/null +++ b/uni_modules/uview-ui/components/u-steps-item/u-steps-item.vue @@ -0,0 +1,316 @@ +<template> + <view class="u-steps-item" ref="u-steps-item" :class="[`u-steps-item--${parentData.direction}`]"> + <view class="u-steps-item__line" v-if="index + 1 < childLength" + :class="[`u-steps-item__line--${parentData.direction}`]" :style="[lineStyle]"></view> + <view class="u-steps-item__wrapper" + :class="[`u-steps-item__wrapper--${parentData.direction}`, parentData.dot && `u-steps-item__wrapper--${parentData.direction}--dot`]"> + <slot name="icon"> + <view class="u-steps-item__wrapper__dot" v-if="parentData.dot" :style="{ + backgroundColor: statusColor + }"> + + </view> + <view class="u-steps-item__wrapper__icon" v-else-if="parentData.activeIcon || parentData.inactiveIcon"> + <u-icon :name="index <= parentData.current ? parentData.activeIcon : parentData.inactiveIcon" + :size="iconSize" + :color="index <= parentData.current ? parentData.activeColor : parentData.inactiveColor"> + </u-icon> + </view> + <view v-else :style="{ + backgroundColor: statusClass === 'process' ? parentData.activeColor : 'transparent', + borderColor: statusColor + }" class="u-steps-item__wrapper__circle"> + <text v-if="statusClass === 'process' || statusClass === 'wait'" + class="u-steps-item__wrapper__circle__text" :style="{ + color: index == parentData.current ? '#ffffff' : parentData.inactiveColor + }">{{ index + 1}}</text> + <u-icon v-else :color="statusClass === 'error' ? 'error' : parentData.activeColor" size="12" + :name="statusClass === 'error' ? 'close' : 'checkmark'"></u-icon> + </view> + </slot> + </view> + <view class="u-steps-item__content" :class="[`u-steps-item__content--${parentData.direction}`]" + :style="[contentStyle]"> + <u--text :text="title" :type="parentData.current == index ? 'main' : 'content'" lineHeight="20px" + :size="parentData.current == index ? 14 : 13"></u--text> + <slot name="desc"> + <u--text :text="desc" type="tips" size="12"></u--text> + </slot> + </view> + <!-- <view + class="u-steps-item__line" + v-if="showLine && parentData.direction === 'column'" + :class="[`u-steps-item__line--${parentData.direction}`]" + :style="[lineStyle]" + ></view> --> + </view> +</template> + +<script> + import props from './props.js'; + // #ifdef APP-NVUE + const dom = uni.requireNativePlugin('dom') + // #endif + /** + * StepsItem ��������������������� + * @description ������������������u-steps������������ + * @tutorial https://uviewui.com/components/steps.html + * @property {String} title ������������ + * @property {String} current ������������ + * @property {String | Number} iconSize ������������ (������ 17 ) + * @property {Boolean} error ������������������������������������ (������ false ) + * @example <u-steps current="0"><u-steps-item title="���������" desc="10:35" ></u-steps-item></u-steps> + */ + export default { + name: 'u-steps-item', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + index: 0, + childLength: 0, + showLine: false, + size: { + height: 0, + width: 0 + }, + parentData: { + direction: 'row', + current: 0, + activeColor: '', + inactiveColor: '', + activeIcon: '', + inactiveIcon: '', + dot: false + } + } + }, + watch: { + 'parentData'(newValue, oldValue) { + } + }, + created() { + this.init() + }, + computed: { + lineStyle() { + const style = {} + if (this.parentData.direction === 'row') { + style.width = this.size.width + 'px' + style.left = this.size.width / 2 + 'px' + } else { + style.height = this.size.height + 'px' + // style.top = this.size.height / 2 + 'px' + } + style.backgroundColor = this.parent.children?.[this.index + 1]?.error ? uni.$u.color.error : this.index < + this + .parentData + .current ? this.parentData.activeColor : this.parentData.inactiveColor + return style + }, + statusClass() { + const { + index, + error + } = this + const { + current + } = this.parentData + if (current == index) { + return error === true ? 'error' : 'process' + } else if (error) { + return 'error' + } else if (current > index) { + return 'finish' + } else { + return 'wait' + } + }, + statusColor() { + let color = '' + switch (this.statusClass) { + case 'finish': + color = this.parentData.activeColor + break + case 'error': + color = uni.$u.color.error + break + case 'process': + color = this.parentData.dot ? this.parentData.activeColor : 'transparent' + break + default: + color = this.parentData.inactiveColor + break + } + return color + }, + contentStyle() { + const style = {} + if (this.parentData.direction === 'column') { + style.marginLeft = this.parentData.dot ? '2px' : '6px' + style.marginTop = this.parentData.dot ? '0px' : '6px' + } else { + style.marginTop = this.parentData.dot ? '2px' : '6px' + style.marginLeft = this.parentData.dot ? '2px' : '6px' + } + + return style + } + }, + mounted() { + this.parent && this.parent.updateFromChild() + uni.$u.sleep().then(() => { + this.getStepsItemRect() + }) + }, + methods: { + init() { + // ��������������� + this.updateParentData() + if (!this.parent) { + return uni.$u.error('u-steps-item���������������u-steps������������') + } + this.index = this.parent.children.indexOf(this) + this.childLength = this.parent.children.length + }, + updateParentData() { + // ������������mixin��� + this.getParentData('u-steps') + }, + // ��������������������������� + updateFromParent() { + this.init() + }, + // ��������������������������������������������������� + getStepsItemRect() { + // #ifndef APP-NVUE + this.$uGetRect('.u-steps-item').then(size => { + this.size = size + }) + // #endif + + // #ifdef APP-NVUE + dom.getComponentRect(this.$refs['u-steps-item'], res => { + const { + size + } = res + this.size = size + }) + // #endif + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-steps-item { + flex: 1; + @include flex; + + &--row { + flex-direction: column; + align-items: center; + position: relative; + } + + &--column { + position: relative; + flex-direction: row; + justify-content: flex-start; + padding-bottom: 5px; + } + + &__wrapper { + @include flex; + justify-content: center; + align-items: center; + position: relative; + background-color: #fff; + + &--column { + width: 20px; + height: 32px; + + &--dot { + height: 20px; + width: 20px; + } + } + + &--row { + width: 32px; + height: 20px; + + &--dot { + width: 20px; + height: 20px; + } + } + + &__circle { + width: 20px; + height: 20px; + /* #ifndef APP-NVUE */ + box-sizing: border-box; + flex-shrink: 0; + /* #endif */ + border-radius: 100px; + border-width: 1px; + border-color: $u-tips-color; + border-style: solid; + @include flex(row); + align-items: center; + justify-content: center; + transition: background-color 0.3s; + + &__text { + color: $u-tips-color; + font-size: 11px; + @include flex(row); + align-items: center; + justify-content: center; + text-align: center; + line-height: 11px; + } + } + + &__dot { + width: 10px; + height: 10px; + border-radius: 100px; + background-color: $u-content-color; + } + } + + &__content { + @include flex; + flex: 1; + + &--row { + flex-direction: column; + align-items: center; + } + + &--column { + flex-direction: column; + margin-left: 6px; + } + } + + &__line { + position: absolute; + background: $u-tips-color; + + &--row { + top: 10px; + height: 1px; + } + + &--column { + width: 1px; + left: 10px; + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-steps/props.js b/uni_modules/uview-ui/components/u-steps/props.js new file mode 100644 index 0000000..6d4c768 --- /dev/null +++ b/uni_modules/uview-ui/components/u-steps/props.js @@ -0,0 +1,39 @@ +export default { + props: { + // ������������ + direction: { + type: String, + default: uni.$u.props.steps.direction + }, + // ��������������������� + current: { + type: [String, Number], + default: uni.$u.props.steps.current + }, + // ������������������ + activeColor: { + type: String, + default: uni.$u.props.steps.activeColor + }, + // ��������������������� + inactiveColor: { + type: String, + default: uni.$u.props.steps.inactiveColor + }, + // ��������������������� + activeIcon: { + type: String, + default: uni.$u.props.steps.activeIcon + }, + // ��������������������� + inactiveIcon: { + type: String, + default: uni.$u.props.steps.inactiveIcon + }, + // ��������������������� + dot: { + type: Boolean, + default: uni.$u.props.steps.dot + } + } +} diff --git a/uni_modules/uview-ui/components/u-steps/u-steps.vue b/uni_modules/uview-ui/components/u-steps/u-steps.vue new file mode 100644 index 0000000..3ab7764 --- /dev/null +++ b/uni_modules/uview-ui/components/u-steps/u-steps.vue @@ -0,0 +1,80 @@ +<template> + <view + class="u-steps" + :class="[`u-steps--${direction}`]" + > + <slot></slot> + </view> +</template> + +<script> + import props from './props.js'; + /** + * Steps ��������� + * @description ��������������������������������������������������������������������������������������������������� + * @tutorial https://uviewui.com/components/steps.html + * @property {String} direction row-���������column-������ (������ 'row' ) + * @property {String | Number} current ��������������������������� (������ 0 ) + * @property {String} activeColor ������������������ (������ '#3c9cff' ) + * @property {String} inactiveColor ��������������������� (������ '#969799' ) + * @property {String} activeIcon ��������������������� + * @property {String} inactiveIcon ��������������������� + * @property {Boolean} dot ��������������������� (������ false ) + * @example <u-steps current="0"><u-steps-item title="���������" desc="10:35" ></u-steps-item></u-steps> + */ + export default { + name: 'u-steps', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + } + }, + watch: { + children() { + this.updateChildData() + }, + parentData() { + this.updateChildData() + } + }, + computed: { + // ������������������������������watch��������������������������������������������������������������������������� + parentData() { + return [this.current, this.direction, this.activeColor, this.inactiveColor, this.activeIcon, this.inactiveIcon, this.dot] + } + }, + methods: { + // ������������������������ + updateChildData() { + this.children.map(child => { + // ��������������������������������������������� + uni.$u.test.func((child || {}).updateFromParent()) && child.updateFromParent() + }) + }, + // ������������������������������������������������������������ + updateFromChild() { + this.updateChildData() + } + }, + created() { + this.children = [] + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-steps { + @include flex; + + &--column { + flex-direction: column + } + + &--row { + flex-direction: row; + flex: 1; + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-sticky/props.js b/uni_modules/uview-ui/components/u-sticky/props.js new file mode 100644 index 0000000..c2ca8da --- /dev/null +++ b/uni_modules/uview-ui/components/u-sticky/props.js @@ -0,0 +1,40 @@ +export default { + props: { + // ���������������������������������������������������������������H5���������NavigationBar���44px + offsetTop: { + type: [String, Number], + default: uni.$u.props.sticky.offsetTop + }, + // ��������������������������� + customNavHeight: { + type: [String, Number], + // #ifdef H5 + // H5��������������������������������������������������������������������������������������������������������� + default: 44, + // #endif + // #ifndef H5 + default: uni.$u.props.sticky.customNavHeight + // #endif + }, + // ������������������������ + disabled: { + type: Boolean, + default: uni.$u.props.sticky.disabled + }, + // ��������������������������� + bgColor: { + type: String, + default: uni.$u.props.sticky.bgColor + }, + // z-index��� + zIndex: { + type: [String, Number], + default: uni.$u.props.sticky.zIndex + }, + // ��������������������� + index: { + type: [String, Number], + default: uni.$u.props.sticky.index + } + } +} diff --git a/uni_modules/uview-ui/components/u-sticky/u-sticky.vue b/uni_modules/uview-ui/components/u-sticky/u-sticky.vue new file mode 100644 index 0000000..ff74688 --- /dev/null +++ b/uni_modules/uview-ui/components/u-sticky/u-sticky.vue @@ -0,0 +1,212 @@ +<template> + <view + class="u-sticky" + :id="elId" + :style="[style]" + > + <view + :style="[stickyContent]" + class="u-sticky__content" + > + <slot /> + </view> + </view> +</template> + +<script> + import props from './props.js';; + /** + * sticky ������ + * @description ������������CSS���position: sticky��������������������������������������������������������������������������� ������������������������������������������������������������������������������������������������������������������ + * @tutorial https://www.uviewui.com/components/sticky.html + * @property {String ��� Number} offsetTop ������������������������������������px��������� 0 ��� + * @property {String ��� Number} customNavHeight ��������������������������� ���h5 ������44 ������������ 0 ��� + * @property {Boolean} disabled ������������������������ ��������� false ��� + * @property {String} bgColor ��������������������������� '#ffffff' ��� + * @property {String ��� Number} zIndex ������������z-index��� + * @property {String ��� Number} index ������������������������������������������������ + * @property {Object} customStyle ������������������������������ + * @event {Function} fixed ��������������������� + * @event {Function} unfixed ��������������������������� + * @example <u-sticky offsetTop="200"><view>���������������������������������������������</view></u-sticky> + */ + export default { + name: 'u-sticky', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + cssSticky: false, // ������������css���sticky������ + stickyTop: 0, // ���������top���������������������������������������������������������������������offsetTop��� + elId: uni.$u.guid(), + left: 0, // js���������������������������������������postition: fixed���������������������������������������������������������������������������������left���height���width������ + width: 'auto', + height: 'auto', + fixed: false, // js������������������������������������ + } + }, + computed: { + style() { + const style = {} + if(!this.disabled) { + if (this.cssSticky) { + style.position = 'sticky' + style.zIndex = this.uZindex + style.top = uni.$u.addUnit(this.stickyTop) + } else { + style.height = this.fixed ? this.height + 'px' : 'auto' + } + } else { + // ������������������������������������relative(nvue)������nvue���static������������������ + // #ifdef APP-NVUE + style.position = 'relative' + // #endif + // #ifndef APP-NVUE + style.position = 'static' + // #endif + } + style.backgroundColor = this.bgColor + return uni.$u.deepMerge(uni.$u.addStyle(this.customStyle), style) + }, + // ��������������������� + stickyContent() { + const style = {} + if (!this.cssSticky) { + style.position = this.fixed ? 'fixed' : 'static' + style.top = this.stickyTop + 'px' + style.left = this.left + 'px' + style.width = this.width == 'auto' ? 'auto' : this.width + 'px' + style.zIndex = this.uZindex + } + return style + }, + uZindex() { + return this.zIndex ? this.zIndex : uni.$u.zIndex.sticky + } + }, + mounted() { + this.init() + }, + methods: { + init() { + this.getStickyTop() + // ��������������������� + this.checkSupportCssSticky() + // ���������������css sticky������������js���������������������������������css������ + if (!this.cssSticky) { + !this.disabled && this.initObserveContent() + } + }, + initObserveContent() { + // ���������������������������������������js���������������������������������������������������������"������" + this.$uGetRect('#' + this.elId).then((res) => { + this.height = res.height + this.left = res.left + this.width = res.width + this.$nextTick(() => { + this.observeContent() + }) + }) + }, + observeContent() { + // ������������������������ + this.disconnectObserver('contentObserver') + const contentObserver = uni.createIntersectionObserver({ + // ��������������������� + thresholds: [0.95, 0.98, 1] + }) + // ��������������������������������� + contentObserver.relativeToViewport({ + top: -this.stickyTop + }) + // ��������������������� + contentObserver.observe(`#${this.elId}`, res => { + this.setFixed(res.boundingClientRect.top) + }) + this.contentObserver = contentObserver + }, + setFixed(top) { + // ������������������������������������ + const fixed = top <= this.stickyTop + this.fixed = fixed + }, + disconnectObserver(observerName) { + // ��������������������������� + const observer = this[observerName] + observer && observer.disconnect() + }, + getStickyTop() { + this.stickyTop = uni.$u.getPx(this.offsetTop) + uni.$u.getPx(this.customNavHeight) + }, + async checkSupportCssSticky() { + // #ifdef H5 + // H5������������������������������������������css sticky��������������������������������������������������� + if (this.checkCssStickyForH5()) { + this.cssSticky = true + } + // #endif + + // ������������������������8.0������������������������css sticky���(������������7���������������������������������sticky) + if (uni.$u.os() === 'android' && Number(uni.$u.sys().system) > 8) { + this.cssSticky = true + } + + // APP-Vue������������������������computedStyle������������������css sticky + // #ifdef APP-VUE || MP-WEIXIN + this.cssSticky = await this.checkComputedStyle() + // #endif + + // ios���������ios6���������������������css sticky��� + if (uni.$u.os() === 'ios') { + this.cssSticky = true + } + + // nvue������������css sticky��� + // #ifdef APP-NVUE + this.cssSticky = true + // #endif + }, + // ���APP������������������������������uni.createSelectorQuery������������������������css sticky + checkComputedStyle() { + // ��������������������������������������������������������������� + // #ifdef APP-VUE || MP-WEIXIN + return new Promise(resolve => { + uni.createSelectorQuery().in(this).select('.u-sticky').fields({ + computedStyle: ["position"] + }).exec(e => { + resolve('sticky' === e[0].position) + }) + }) + // #endif + }, + // H5���������������������������������������������css sticky + // ���������������������������sticky������ + checkCssStickyForH5() { + // ��������������������������������������������������������������� + // #ifdef H5 + const vendorList = ['', '-webkit-', '-ms-', '-moz-', '-o-'], + vendorListLength = vendorList.length, + stickyElement = document.createElement('div') + for (let i = 0; i < vendorListLength; i++) { + stickyElement.style.position = vendorList[i] + 'sticky' + if (stickyElement.style.position !== '') { + return true + } + } + return false; + // #endif + } + }, + beforeDestroy() { + this.disconnectObserver('contentObserver') + } + } +</script> + +<style lang="scss" scoped> + .u-sticky { + /* #ifdef APP-VUE || MP-WEIXIN */ + // ���������������sticky������������������������������APP������uni.createSelectorQuery������������������css sticky������ + position: sticky; + /* #endif */ + } +</style> diff --git a/uni_modules/uview-ui/components/u-subsection/props.js b/uni_modules/uview-ui/components/u-subsection/props.js new file mode 100644 index 0000000..5675eaa --- /dev/null +++ b/uni_modules/uview-ui/components/u-subsection/props.js @@ -0,0 +1,49 @@ +export default { + props: { + // tab��������� + list: { + type: Array, + default: uni.$u.props.subsection.list + }, + // ���������������tab���index + current: { + type: [String, Number], + default: uni.$u.props.subsection.current + }, + // ��������������� + activeColor: { + type: String, + default: uni.$u.props.subsection.activeColor + }, + // ������������������ + inactiveColor: { + type: String, + default: uni.$u.props.subsection.inactiveColor + }, + // ���������������mode=button������������������mode=subsection������������������ + mode: { + type: String, + default: uni.$u.props.subsection.mode + }, + // ������������ + fontSize: { + type: [String, Number], + default: uni.$u.props.subsection.fontSize + }, + // ������tab��������������������� + bold: { + type: Boolean, + default: uni.$u.props.subsection.bold + }, + // mode = button������������������������ + bgColor: { + type: String, + default: uni.$u.props.subsection.bgColor + }, + // ���list������������������������������ + keyName: { + type: String, + default: uni.$u.props.subsection.keyName + } + } +} diff --git a/uni_modules/uview-ui/components/u-subsection/u-subsection.vue b/uni_modules/uview-ui/components/u-subsection/u-subsection.vue new file mode 100644 index 0000000..cc4d540 --- /dev/null +++ b/uni_modules/uview-ui/components/u-subsection/u-subsection.vue @@ -0,0 +1,299 @@ +<template> + <view + class="u-subsection" + ref="u-subsection" + :class="[`u-subsection--${mode}`]" + :style="[$u.addStyle(customStyle), wrapperStyle]" + > + <view + class="u-subsection__bar" + ref="u-subsection__bar" + :style="[barStyle]" + :class="[ + mode === 'button' && 'u-subsection--button__bar', + current === 0 && + mode === 'subsection' && + 'u-subsection__bar--first', + current > 0 && + current < list.length - 1 && + mode === 'subsection' && + 'u-subsection__bar--center', + current === list.length - 1 && + mode === 'subsection' && + 'u-subsection__bar--last', + ]" + ></view> + <view + class="u-subsection__item" + :class="[ + `u-subsection__item--${index}`, + index < list.length - 1 && + 'u-subsection__item--no-border-right', + index === 0 && 'u-subsection__item--first', + index === list.length - 1 && 'u-subsection__item--last', + ]" + :ref="`u-subsection__item--${index}`" + :style="[itemStyle(index)]" + @tap="clickHandler(index)" + v-for="(item, index) in list" + :key="index" + > + <text + class="u-subsection__item__text" + :style="[textStyle(index)]" + >{{ getText(item) }}</text + > + </view> + </view> +</template> + +<script> +// #ifdef APP-NVUE +const dom = uni.requireNativePlugin("dom"); +const animation = uni.requireNativePlugin("animation"); +// #endif +import props from "./props.js"; +/** + * Subsection ��������� + * @description ������������������������������������������������������������������������ + * @tutorial https://www.uviewui.com/components/subsection.html + * @property {Array} list tab��������� + * @property {String ��� Number} current ���������������tab���index��������� 0 ��� + * @property {String} activeColor ��������������������������� '#3c9cff' ��� + * @property {String} inactiveColor ������������������������������ '#303133' ��� + * @property {String} mode ���������������mode=button������������������mode=subsection��������������������������� 'button' ��� + * @property {String ��� Number} fontSize ���������������������px��������� 12 ��� + * @property {Boolean} bold ������������������������������������������ true ��� + * @property {String} bgColor ���������������������mode���button������������������ '#eeeeef' ��� + * @property {Object} customStyle ��������������������������������� + * @property {String} keyName ���`list`��������������������������������������� 'name' ��� + * + * @event {Function} change ������������������������������������ ������ index������������index���������������0������ + * @example <u-subsection :list="list" :current="curNow" @change="sectionChange"></u-subsection> + */ +export default { + name: "u-subsection", + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + // ������������ + itemRect: { + width: 0, + height: 0, + }, + }; + }, + watch: { + list(newValue, oldValue) { + this.init(); + }, + current: { + immediate: true, + handler(n) { + // #ifdef APP-NVUE + // ���������nvue������������������translateX��������������������������������������������������������������������� + // ������animation������������������ + const ref = this.$refs?.["u-subsection__bar"]?.ref; + // ���������ref���������(���������������������������������������������dom������������������������������ref)������������100ms������������������������������(���������������������������������)������������������ + uni.$u.sleep(ref ? 0 : 100).then(() => { + animation.transition(this.$refs["u-subsection__bar"].ref, { + styles: { + transform: `translateX(${ + n * this.itemRect.width + }px)`, + transformOrigin: "center center", + }, + duration: 300, + }); + }); + // #endif + }, + }, + }, + computed: { + wrapperStyle() { + const style = {}; + // button��������������������������� + if (this.mode === "button") { + style.backgroundColor = this.bgColor; + } + return style; + }, + // ��������������� + barStyle() { + const style = {}; + style.width = `${this.itemRect.width}px`; + style.height = `${this.itemRect.height}px`; + // ������translateX������������������������������������������*item��������� + // #ifndef APP-NVUE + style.transform = `translateX(${ + this.current * this.itemRect.width + }px)`; + // #endif + if (this.mode === "subsection") { + // ���subsection������������������������������������������������������������������������������translateX������������������������������overflow: hidden��������������������� + style.backgroundColor = this.activeColor; + } + return style; + }, + // ���������item��������� + itemStyle(index) { + return (index) => { + const style = {}; + if (this.mode === "subsection") { + // ������border��������� + style.borderColor = this.activeColor; + style.borderWidth = "1px"; + style.borderStyle = "solid"; + } + return style; + }; + }, + // ��������������������� + textStyle(index) { + return (index) => { + const style = {}; + style.fontWeight = + this.bold && this.current === index ? "bold" : "normal"; + style.fontSize = uni.$u.addUnit(this.fontSize); + // subsection��������������������������������������������� + if (this.mode === "subsection") { + style.color = + this.current === index ? "#fff" : this.inactiveColor; + } else { + // button������������������������������������������activeColor + style.color = + this.current === index + ? this.activeColor + : this.inactiveColor; + } + return style; + }; + }, + }, + mounted() { + this.init(); + }, + methods: { + init() { + uni.$u.sleep().then(() => this.getRect()); + }, + // ������������������ + getText(item) { + return typeof item === 'object' ? item[this.keyName] : item + }, + // ��������������������� + getRect() { + // #ifndef APP-NVUE + this.$uGetRect(".u-subsection__item--0").then((size) => { + this.itemRect = size; + }); + // #endif + + // #ifdef APP-NVUE + const ref = this.$refs["u-subsection__item--0"][0]; + ref && + dom.getComponentRect(ref, (res) => { + this.itemRect = res.size; + }); + // #endif + }, + clickHandler(index) { + this.$emit("change", index); + }, + }, +}; +</script> + +<style lang="scss" scoped> +@import "../../libs/css/components.scss"; + +.u-subsection { + @include flex; + position: relative; + overflow: hidden; + /* #ifndef APP-NVUE */ + width: 100%; + box-sizing: border-box; + /* #endif */ + + &--button { + height: 32px; + background-color: rgb(238, 238, 239); + padding: 3px; + border-radius: 3px; + align-items: stretch; + + &__bar { + background-color: #ffffff; + border-radius: 3px !important; + } + } + + &--subsection { + height: 30px; + } + + &__bar { + position: absolute; + /* #ifndef APP-NVUE */ + transition-property: transform, color; + transition-duration: 0.3s; + transition-timing-function: ease-in-out; + /* #endif */ + + &--first { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; + border-top-right-radius: 0px; + border-bottom-right-radius: 0px; + } + + &--center { + border-top-left-radius: 0px; + border-bottom-left-radius: 0px; + border-top-right-radius: 0px; + border-bottom-right-radius: 0px; + } + + &--last { + border-top-left-radius: 0px; + border-bottom-left-radius: 0px; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; + } + } + + &__item { + @include flex; + flex: 1; + justify-content: center; + align-items: center; + // vue���������������������������������������������������������������������item������������������������ + position: relative; + + &--no-border-right { + border-right-width: 0 !important; + } + + &--first { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; + } + + &--last { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; + } + + &__text { + font-size: 12px; + line-height: 12px; + @include flex; + align-items: center; + transition-property: color; + transition-duration: 0.3s; + } + } +} +</style> diff --git a/uni_modules/uview-ui/components/u-swipe-action-item/index - backup.wxs b/uni_modules/uview-ui/components/u-swipe-action-item/index - backup.wxs new file mode 100644 index 0000000..04cab92 --- /dev/null +++ b/uni_modules/uview-ui/components/u-swipe-action-item/index - backup.wxs @@ -0,0 +1,256 @@ +/** + * ������wxs������������������APP-VUE������������QQ���������������H5������ + * wxs���������������es6���������������������������var��������������������������������������������������� + */ + +// ������������ +function touchstart(event, ownerInstance) { + // ������������������������ComponentDescriptor������ + var instance = event.instance + // wxs������������������������������������������������������������������touchstart���touchmove��������������������������������������� + var state = instance.getState() + if (state.disable) return + var touches = event.touches + // ������������������������������������������������������ + if (touches && touches.length > 1) return + // ������������������������������ + state.moving = true + // ��������������������������������� + state.startX = touches[0].pageX + state.startY = touches[0].pageY +} + +// ������������ +function touchmove(event, ownerInstance) { + // ������������������������ComponentDescriptor������ + var instance = event.instance + // wxs������������������������ + var state = instance.getState() + if (state.disabled || !state.moving) return + + var touches = event.touches + var pageX = touches[0].pageX + var pageY = touches[0].pageY + var moveX = pageX - state.startX + var moveY = pageY - state.startY + var buttonsWidth = state.buttonsWidth + + // ���������X���������������Y���������������������������������������������������X���������������45��������������������������� + if (Math.abs(moveX) > Math.abs(moveY) || Math.abs(moveX) > state.threshold) { + event.preventDefault() + event.stopPropagation() + } + // ���������������X���������������Y���������������������������������������������������������Y���������������45��������������������������������������������������������������������� + if (Math.abs(moveX) < Math.abs(moveY)) return + + // ���������������������������������������������������������������������������X������������������0������������������ + // ������������������return������������������������������������������������������������������������������������������������ + // ������������������������0 + if (state.status === 'open') { + // ��������������������������������������������� + if (moveX < 0) moveX = 0 + // ������������������������������������������������������������������ + if (moveX > buttonsWidth) moveX = buttonsWidth + // ������������������������������������������������������������������������ + moveSwipeAction(-buttonsWidth + moveX, instance, ownerInstance) + } else { + // ������������������������������������ + if (moveX > 0) moveX = 0 + // ��������������������������������������������������������������������������������������������������������������������������������� + if (Math.abs(moveX) > buttonsWidth) moveX = -buttonsWidth + // ������������������������������������������������������������������������������������������������������ + moveSwipeAction(moveX, instance, ownerInstance) + } +} + +// ������������ +function touchend(event, ownerInstance) { + // ������������������������ComponentDescriptor������ + var instance = event.instance + // wxs������������������������ + var state = instance.getState() + if (!state.moving || state.disabled) return + var touches = event.changedTouches ? event.changedTouches[0] : {} + var pageX = touches.pageX + var pageY = touches.pageY + var moveX = pageX - state.startX + if (state.status === 'open') { + // ��������������������������������������������������� + if (moveX < 0) return + // ������������������������������������������������moveX���0������������������������������������������������������������ + if (moveX === 0) { + return closeSwipeAction(instance, ownerInstance) + } + // ��������������������������������������������������������������������������������������������������������� + if (Math.abs(moveX) < state.threshold) { + openSwipeAction(instance, ownerInstance) + } else { + // ������������������������������������������������������ + closeSwipeAction(instance, ownerInstance) + } + } else { + // ��������������������������������������������� + if (moveX > 0) return + // ������������ + if (Math.abs(moveX) < state.threshold) { + closeSwipeAction(instance, ownerInstance) + } else { + openSwipeAction(instance, ownerInstance) + } + } +} + +// ������������������ +function getDuration(value) { + if (value.toString().indexOf('s') >= 0) return value + return value > 30 ? value + 'ms' : value + 's' +} + +// ������������������������������������ +function getMoveDirection(instance, ownerInstance) { + var state = instance.getState() +} + +// ��������������������������������������������������������������������� +function moveSwipeAction(moveX, instance, ownerInstance) { + var state = instance.getState() + // ��������������������������������������������������������������������� + var buttons = ownerInstance.selectAllComponents('.u-swipe-action-item__right__button') + var len = buttons.length + var previewButtonsMoveX = 0 + + // ��������������������������������� + instance.requestAnimationFrame(function() { + instance.setStyle({ + // ������translateX������ + 'transition': 'none', + transform: 'translateX(' + moveX + 'px)', + '-webkit-transform': 'translateX(' + moveX + 'px)' + }) + // ������������������ + for (var i = len - 1; i >= 0; i--) { + // ��������������������������������������������������� + var translateX = state.buttons[i].width / state.buttonsWidth * moveX + // ��������������������������������������������������������������������������������������������������������������������� + var realTranslateX = translateX + previewButtonsMoveX + buttons[i].setStyle({ + // ��������������������������������������������������������������������������������������������������������������������������������������������������� + 'transition': 'none', + 'transform': 'translateX(' + realTranslateX + 'px)', + '-webkit-transform': 'translateX(' + realTranslateX + 'px)' + }) + // ��������������������������������������������������������� + previewButtonsMoveX += translateX + } + }) +} + +// ��������������������������� +function openSwipeAction(instance, ownerInstance) { + var state = instance.getState() + // ��������������������������������������������������������������������� + var buttons = ownerInstance.selectAllComponents('.u-swipe-action-item__right__button') + var len = buttons.length + // ������duration������������ + const duration = getDuration(state.duration) + // ������������������������������������������X������������������������ + var buttonsWidth = -state.buttonsWidth + var previewButtonsMoveX = 0 + instance.requestAnimationFrame(function() { + // ������������������������ + instance.setStyle({ + 'transition': 'transform ' + duration, + 'transform': 'translateX(' + buttonsWidth + 'px)', + '-webkit-transform': 'translateX(' + buttonsWidth + 'px)', + }) + // ��������������������������������������������� + for (var i = len - 1; i >= 0; i--) { + // ��������������������������������������������������� + var translateX = state.buttons[i].width / state.buttonsWidth * buttonsWidth + // ��������������������������������������������������������������������������������������������������������������������� + var realTranslateX = translateX + previewButtonsMoveX + buttons[i].setStyle({ + // ������������������������������������������ + 'transition': 'transform ' + duration, + 'transform': 'translateX(' + realTranslateX + 'px)', + '-webkit-transform': 'translateX(' + realTranslateX + 'px)' + }) + // ��������������������������������������������������������� + previewButtonsMoveX += translateX + } + }) + setStatus('open', instance) +} + +// ������������������������������open-���������������close-������������ +function setStatus(status, instance) { + var state = instance.getState() + state.status = status +} + +// ��������������������������� +function closeSwipeAction(instance, ownerInstance) { + var state = instance.getState() + // ��������������������������������������������������������������������� + var buttons = ownerInstance.selectAllComponents('.u-swipe-action-item__right__button') + var len = buttons.length + // ������duration������������ + const duration = getDuration(state.duration) + instance.requestAnimationFrame(function() { + // ������������������������ + instance.setStyle({ + 'transition': 'transform ' + duration, + 'transform': 'translateX(0px)', + '-webkit-transform': 'translateX(0px)' + }) + // ��������������������������������������������� + for (var i = len - 1; i >= 0; i--) { + buttons[i].setStyle({ + 'transition': 'transform ' + duration, + 'transform': 'translateX(0px)', + '-webkit-transform': 'translateX(0px)' + }) + } + }) + setStatus('close', instance) +} + +// show��������������������� +function showChange(newValue, oldValue, ownerInstance, instance) { + var state = instance.getState() + if (state.disabled) return + // ������������������������ + if (newValue) { + openSwipeAction(instance, ownerInstance) + } else { + closeSwipeAction(instance, ownerInstance) + } +} + +// ������������������������ +function sizeChange(newValue, oldValue, ownerInstance, instance) { + // wxs������������������������ + var state = instance.getState() + state.disabled = newValue.disabled + state.duration = newValue.duration + state.show = newValue.show + state.threshold = newValue.threshold + state.buttons = newValue.buttons + + var len = state.buttons.length + if (len) { + var buttonsWidth = 0 + var buttons = newValue.buttons + for (var i = 0; i < len; i++) { + buttonsWidth += buttons[i].width + } + } + state.buttonsWidth = buttonsWidth +} + +module.exports = { + touchstart: touchstart, + touchmove: touchmove, + touchend: touchend, + sizeChange: sizeChange +} diff --git a/uni_modules/uview-ui/components/u-swipe-action-item/index.wxs b/uni_modules/uview-ui/components/u-swipe-action-item/index.wxs new file mode 100644 index 0000000..728275f --- /dev/null +++ b/uni_modules/uview-ui/components/u-swipe-action-item/index.wxs @@ -0,0 +1,225 @@ +/** + * ������wxs������������������APP-VUE������������QQ���������������H5������ + * wxs���������������es6���������������������������var��������������������������������������������������� + */ + +// ������������ +function touchstart(event, ownerInstance) { + // ������������������������ComponentDescriptor������ + var instance = event.instance + // wxs������������������������������������������������������������������touchstart���touchmove��������������������������������������� + var state = instance.getState() + if (state.disabled) return + var touches = event.touches + // ������������������������������������������������������ + if (touches && touches.length > 1) return + // ������������������������������ + state.moving = true + // ��������������������������������� + state.startX = touches[0].pageX + state.startY = touches[0].pageY + + ownerInstance.callMethod('closeOther') +} + +// ������������ +function touchmove(event, ownerInstance) { + // ������������������������ComponentDescriptor������ + var instance = event.instance + // wxs������������������������ + var state = instance.getState() + if (state.disabled || !state.moving) return + var touches = event.touches + var pageX = touches[0].pageX + var pageY = touches[0].pageY + var moveX = pageX - state.startX + var moveY = pageY - state.startY + var buttonsWidth = state.buttonsWidth + + // ���������X���������������Y���������������������������������������������������X���������������45��������������������������� + if (Math.abs(moveX) > Math.abs(moveY) || Math.abs(moveX) > state.threshold) { + event.preventDefault && event.preventDefault() + event.stopPropagation && event.stopPropagation() + } + // ���������������X���������������Y���������������������������������������������������������Y���������������45��������������������������������������������������������������������� + if (Math.abs(moveX) < Math.abs(moveY)) return + + // ���������������������������������������������������������������������������X������������������0������������������ + // ������������������return������������������������������������������������������������������������������������������������ + // ������������������������0 + if (state.status === 'open') { + // ��������������������������������������������� + if (moveX < 0) moveX = 0 + // ������������������������������������������������������������������ + if (moveX > buttonsWidth) moveX = buttonsWidth + // ������������������������������������������������������������������������ + moveSwipeAction(-buttonsWidth + moveX, instance, ownerInstance) + } else { + // ������������������������������������ + if (moveX > 0) moveX = 0 + // ��������������������������������������������������������������������������������������������������������������������������������� + if (Math.abs(moveX) > buttonsWidth) moveX = -buttonsWidth + // ������������������������������������������������������������������������������������������������������ + moveSwipeAction(moveX, instance, ownerInstance) + } +} + +// ������������ +function touchend(event, ownerInstance) { + // ������������������������ComponentDescriptor������ + var instance = event.instance + // wxs������������������������ + var state = instance.getState() + if (!state.moving || state.disabled) return + var touches = event.changedTouches ? event.changedTouches[0] : {} + var pageX = touches.pageX + var pageY = touches.pageY + var moveX = pageX - state.startX + if (state.status === 'open') { + // ��������������������������������������������������� + if (moveX < 0) return + // ������������������������������������������������moveX���0������������������������������������������������������������ + if (moveX === 0) { + return closeSwipeAction(instance, ownerInstance) + } + // ��������������������������������������������������������������������������������������������������������� + if (Math.abs(moveX) < state.threshold) { + openSwipeAction(instance, ownerInstance) + } else { + // ������������������������������������������������������ + closeSwipeAction(instance, ownerInstance) + } + } else { + // ��������������������������������������������� + if (moveX > 0) return + // ������������ + if (Math.abs(moveX) < state.threshold) { + closeSwipeAction(instance, ownerInstance) + } else { + openSwipeAction(instance, ownerInstance) + } + } +} + +// ������������������ +function getDuration(value) { + if (value.toString().indexOf('s') >= 0) return value + return value > 30 ? value + 'ms' : value + 's' +} + +// ������������������������������������ +function getMoveDirection(instance, ownerInstance) { + var state = instance.getState() +} + +// ��������������������������������������������������������������������� +function moveSwipeAction(moveX, instance, ownerInstance) { + var state = instance.getState() + // ��������������������������������������������������������������������� + var buttons = ownerInstance.selectAllComponents('.u-swipe-action-item__right__button') + + // ��������������������������������� + instance.requestAnimationFrame(function() { + instance.setStyle({ + // ������translateX������ + 'transition': 'none', + transform: 'translateX(' + moveX + 'px)', + '-webkit-transform': 'translateX(' + moveX + 'px)' + }) + }) +} + +// ��������������������������� +function openSwipeAction(instance, ownerInstance) { + var state = instance.getState() + // ��������������������������������������������������������������������� + var buttons = ownerInstance.selectAllComponents('.u-swipe-action-item__right__button') + // ������duration������������ + var duration = getDuration(state.duration) + // ������������������������������������������X������������������������ + var buttonsWidth = -state.buttonsWidth + instance.requestAnimationFrame(function() { + // ������������������������ + instance.setStyle({ + 'transition': 'transform ' + duration, + 'transform': 'translateX(' + buttonsWidth + 'px)', + '-webkit-transform': 'translateX(' + buttonsWidth + 'px)', + }) + }) + setStatus('open', instance, ownerInstance) +} + +// ������������������������������open-���������������close-������������ +function setStatus(status, instance, ownerInstance) { + var state = instance.getState() + state.status = status + ownerInstance.callMethod('setState', status) +} + +// ��������������������������� +function closeSwipeAction(instance, ownerInstance) { + var state = instance.getState() + // ��������������������������������������������������������������������� + var buttons = ownerInstance.selectAllComponents('.u-swipe-action-item__right__button') + var len = buttons.length + // ������duration������������ + var duration = getDuration(state.duration) + instance.requestAnimationFrame(function() { + // ������������������������ + instance.setStyle({ + 'transition': 'transform ' + duration, + 'transform': 'translateX(0px)', + '-webkit-transform': 'translateX(0px)' + }) + // ��������������������������������������������� + for (var i = len - 1; i >= 0; i--) { + buttons[i].setStyle({ + 'transition': 'transform ' + duration, + 'transform': 'translateX(0px)', + '-webkit-transform': 'translateX(0px)' + }) + } + }) + setStatus('close', instance, ownerInstance) +} + +// status��������������������� +function statusChange(newValue, oldValue, ownerInstance, instance) { + var state = instance.getState() + if (state.disabled) return + // ������������������������ + if (newValue === 'close' && state.status === 'open') { + closeSwipeAction(instance, ownerInstance) + } else if(newValue === 'open' && state.status === 'close') { + openSwipeAction(instance, ownerInstance) + } +} + +// ������������������������ +function sizeChange(newValue, oldValue, ownerInstance, instance) { + // wxs������������������������ + var state = instance.getState() + state.disabled = newValue.disabled + state.duration = newValue.duration + state.show = newValue.show + state.threshold = newValue.threshold + state.buttons = newValue.buttons + + if (state.buttons) { + var len = state.buttons.length + var buttonsWidth = 0 + var buttons = newValue.buttons + for (var i = 0; i < len; i++) { + buttonsWidth += buttons[i].width + } + } + state.buttonsWidth = buttonsWidth +} + +module.exports = { + touchstart: touchstart, + touchmove: touchmove, + touchend: touchend, + sizeChange: sizeChange, + statusChange: statusChange +} diff --git a/uni_modules/uview-ui/components/u-swipe-action-item/nvue - backup.js b/uni_modules/uview-ui/components/u-swipe-action-item/nvue - backup.js new file mode 100644 index 0000000..6b9f116 --- /dev/null +++ b/uni_modules/uview-ui/components/u-swipe-action-item/nvue - backup.js @@ -0,0 +1,270 @@ +// nvue������dom���������������������dom��������������� +const dom = uni.requireNativePlugin('dom') +// nvue���������������������������������������������uni.animation������������uni.animation������������nvue +const animation = uni.requireNativePlugin('animation') + +export default { + data() { + return { + // ��������������� + moving: false, + // ���������open-���������������close-������������ + status: 'close', + // ������������������X���Y��������� + startX: 0, + startY: 0, + // ��������������������������������������� + buttons: [], + // ������������������������ + buttonsWidth: 0, + // ��������������������������������� + moveX: 0, + // ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ + lastX: 0 + } + }, + computed: { + // ������������������ + getDuratin() { + let duration = String(this.duration) + // ������ms������������������ms��������������� + if (duration.indexOf('ms') >= 0) return parseInt(duration) + // ������s������������������������ms������������������������1000 + if (duration.indexOf('s') >= 0) return parseInt(duration) * 1000 + // ���������������������������������30������������s������ + duration = Number(duration) + return duration < 30 ? duration * 1000 : duration + } + }, + watch: { + show: { + immediate: true, + handler(n) { + // if(n === true) { + // uni.$u.sleep(50).then(() => { + // this.openSwipeAction() + // }) + // } else { + // this.closeSwipeAction() + // } + } + } + }, + mounted() { + uni.$u.sleep(20).then(() => { + this.queryRect() + }) + }, + methods: { + close() { + this.closeSwipeAction() + }, + // ��������������� + touchstart(event) { + if (this.disabled) return + this.closeOther() + const { touches } = event + // ��������������������������������� + this.startX = touches[0].pageX + this.startY = touches[0].pageY + }, + // // ������������ + touchmove(event) { + if (this.disabled) return + const { touches } = event + const { pageX } = touches[0] + const { pageY } = touches[0] + let moveX = pageX - this.startX + const moveY = pageY - this.startY + const { buttonsWidth } = this + const len = this.buttons.length + + // ������������������������������������������������������������������������������������ + if (Math.abs(pageX - this.lastX) < 0.3) return + this.lastX = pageX + + // ���������X���������������Y���������������������������������������������������X���������������45��������������������������� + if (Math.abs(moveX) > Math.abs(moveY) || Math.abs(moveX) > this.threshold) { + event.stopPropagation() + } + // ���������������X���������������Y���������������������������������������������������������Y���������������45��������������������������������������������������������������������� + if (Math.abs(moveX) < Math.abs(moveY)) return + + // ���������������������������������������������������������������������������X������������������0������������������ + // ������������������return������������������������������������������������������������������������������������������������ + // ������������������������0 + if (this.status === 'open') { + // ��������������������������������������������� + if (moveX < 0) moveX = 0 + // ������������������������������������������������������������������ + if (moveX > buttonsWidth) moveX = buttonsWidth + // ������������������������������������������������������������������������ + this.moveSwipeAction(-buttonsWidth + moveX) + } else { + // ������������������������������������ + if (moveX > 0) moveX = 0 + // ��������������������������������������������������������������������������������������������������������������������������������� + if (Math.abs(moveX) > buttonsWidth) moveX = -buttonsWidth + // ������������������������������������������������������������������������������������������������������ + this.moveSwipeAction(moveX) + } + }, + // ��������������������� + touchend(event) { + if (this.disabled) return + const touches = event.changedTouches ? event.changedTouches[0] : {} + const { pageX } = touches + const { pageY } = touches + const { buttonsWidth } = this + this.moveX = pageX - this.startX + if (this.status === 'open') { + // ��������������������������������������������������� + if (this.moveX < 0) this.moveX = 0 + if (this.moveX > buttonsWidth) this.moveX = buttonsWidth + // ������������������������������������������������moveX���0������������������������������������������������������������ + if (this.moveX === 0) { + return this.closeSwipeAction() + } + // ��������������������������������������������������������������������������������������������������������� + if (Math.abs(this.moveX) < this.threshold) { + this.openSwipeAction() + } else { + // ������������������������������������������������������ + this.closeSwipeAction() + } + } else { + // ��������������������������������������������� + if (this.moveX >= 0) this.moveX = 0 + if (this.moveX <= -buttonsWidth) this.moveX = -buttonsWidth + // ������������ + if (Math.abs(this.moveX) < this.threshold) { + this.closeSwipeAction() + } else { + this.openSwipeAction() + } + } + }, + // ��������������������������������������������������������������������� + moveSwipeAction(moveX) { + if (this.moving) return + this.moving = true + + let previewButtonsMoveX = 0 + const len = this.buttons.length + animation.transition(this.$refs['u-swipe-action-item__content'].ref, { + styles: { + transform: `translateX(${moveX}px)` + }, + timingFunction: 'linear' + }, () => { + this.moving = false + }) + // ��������������������� + for (let i = len - 1; i >= 0; i--) { + const buttonRef = this.$refs[`u-swipe-action-item__right__button-${i}`][0].ref + // ��������������������������������������������������� + const translateX = this.buttons[i].width / this.buttonsWidth * moveX + // ��������������������������������������������������������������������������������������������������������������������� + const realTranslateX = translateX + previewButtonsMoveX + animation.transition(buttonRef, { + styles: { + transform: `translateX(${realTranslateX}px)` + }, + duration: 0, + delay: 0, + timingFunction: 'linear' + }, () => {}) + // ��������������������������������������������������������� + previewButtonsMoveX += translateX + } + }, + // ������������ + closeSwipeAction() { + if (this.status === 'close') return + this.moving = true + const { buttonsWidth } = this + animation.transition(this.$refs['u-swipe-action-item__content'].ref, { + styles: { + transform: 'translateX(0px)' + }, + duration: this.getDuratin, + timingFunction: 'ease-in-out' + }, () => { + this.status = 'close' + this.moving = false + this.closeHandler() + }) + // ��������������������� + const len = this.buttons.length + for (let i = len - 1; i >= 0; i--) { + const buttonRef = this.$refs[`u-swipe-action-item__right__button-${i}`][0].ref + // ������������������������������������ + if (this.buttons.length === 0 || !this.buttons[i] || !this.buttons[i].width) return + + animation.transition(buttonRef, { + styles: { + transform: 'translateX(0px)' + }, + duration: this.getDuratin, + timingFunction: 'ease-in-out' + }, () => {}) + } + }, + // ������������ + openSwipeAction() { + if (this.status === 'open') return + this.moving = true + const buttonsWidth = -this.buttonsWidth + let previewButtonsMoveX = 0 + animation.transition(this.$refs['u-swipe-action-item__content'].ref, { + styles: { + transform: `translateX(${buttonsWidth}px)` + }, + duration: this.getDuratin, + timingFunction: 'ease-in-out' + }, () => { + this.status = 'open' + this.moving = false + this.openHandler() + }) + // ��������������������� + const len = this.buttons.length + for (let i = len - 1; i >= 0; i--) { + const buttonRef = this.$refs[`u-swipe-action-item__right__button-${i}`][0].ref + // ������������������������������������ + if (this.buttons.length === 0 || !this.buttons[i] || !this.buttons[i].width) return + // ��������������������������������������������������� + const translateX = this.buttons[i].width / this.buttonsWidth * buttonsWidth + // ��������������������������������������������������������������������������������������������������������������������� + const realTranslateX = translateX + previewButtonsMoveX + animation.transition(buttonRef, { + styles: { + transform: `translateX(${realTranslateX}px)` + }, + duration: this.getDuratin, + timingFunction: 'ease-in-out' + }, () => {}) + previewButtonsMoveX += translateX + } + }, + // ������������������������ + queryRect() { + // ���������������������������������getRectByDom������������promise + const promiseAll = this.rightOptions.map((item, index) => this.getRectByDom(this.$refs[`u-swipe-action-item__right__button-${index}`][0])) + // ������promise.all������������������������������������������������������������������ + Promise.all(promiseAll).then((sizes) => { + this.buttons = sizes + // ��������������������������� + this.buttonsWidth = sizes.reduce((sum, cur) => sum + cur.width, 0) + }) + }, + // ������nvue���dom��������������������������� + getRectByDom(ref) { + return new Promise((resolve) => { + dom.getComponentRect(ref, (res) => { + resolve(res.size) + }) + }) + } + } +} diff --git a/uni_modules/uview-ui/components/u-swipe-action-item/nvue.js b/uni_modules/uview-ui/components/u-swipe-action-item/nvue.js new file mode 100644 index 0000000..118e4cf --- /dev/null +++ b/uni_modules/uview-ui/components/u-swipe-action-item/nvue.js @@ -0,0 +1,174 @@ +// nvue������dom���������������������dom��������������� +const dom = uni.requireNativePlugin('dom'); +const bindingX = uni.requireNativePlugin('bindingx'); +const animation = uni.requireNativePlugin('animation'); + +export default { + data() { + return { + // ������������������������ + buttonsWidth: 0, + // ��������������������� + moving: false + } + }, + computed: { + // ������������������ + getDuratin() { + let duration = String(this.duration) + // ������ms������������������ms��������������� + if (duration.indexOf('ms') >= 0) return parseInt(duration) + // ������s������������������������ms������������������������1000 + if (duration.indexOf('s') >= 0) return parseInt(duration) * 1000 + // ���������������������������������30������������s������ + duration = Number(duration) + return duration < 30 ? duration * 1000 : duration + } + }, + watch: { + show(n) { + if(n) { + this.moveCellByAnimation('open') + } else { + this.moveCellByAnimation('close') + } + } + }, + mounted() { + this.initialize() + }, + methods: { + initialize() { + this.queryRect() + }, + // ��������������������������������������������������������������������������� + closeHandler() { + if(this.status === 'open') { + // ��������������������������������������������������������������������� + return this.moveCellByAnimation('close') && this.unbindBindingX() + } + }, + // ��������������� + clickHandler() { + // ������������������������������������������ + if(this.moving) return + // ������������������������������������ + this.parent && this.parent.closeOther(this) + if(this.status === 'open') { + // ��������������������������������������������������������������������� + return this.moveCellByAnimation('close') && this.unbindBindingX() + } + }, + // ��������������� + onTouchstart(e) { + // ������������������������������������disabled������������������ + if(this.moving || this.disabled) { + return this.unbindBindingX() + } + if(this.status === 'open') { + // ��������������������������������������������������������������������� + return this.moveCellByAnimation('close') && this.unbindBindingX() + } + // ������������������e������������������������ + e?.stopPropagation && e.stopPropagation() + e?.preventDefault && e.preventDefault() + this.moving = true + // ������������ref + const content = this.getContentRef() + let expression = `min(max(${-this.buttonsWidth}, x), 0)` + // ������������������������������������ + this.parent && this.parent.closeOther(this) + + // ������������KPI������������BindingX + this.panEvent = bindingX.bind({ + anchor: content, + eventType: 'pan', + props: [{ + element: content, + // ������width��������������������������� + property: 'transform.translateX', + expression + }] + }, (res) => { + this.moving = false + if (res.state === 'end' || res.state === 'exit') { + const deltaX = res.deltaX + if(deltaX <= -this.buttonsWidth || deltaX >= 0) { + // ���������������������������������������������������������������������������0������������������������������������������������������������������ + // ��������������������������������� + this.$nextTick(() => { + this.status = deltaX <= -this.buttonsWidth ? 'open' : 'close' + }) + } else if(Math.abs(deltaX) > uni.$u.getPx(this.threshold)) { + // ��������������������������������������������������������������������������������������� + // ������������������0��������������������������������� + if(Math.abs(deltaX) < this.buttonsWidth) { + this.moveCellByAnimation(deltaX > 0 ? 'close' : 'open') + } + } else { + // ���������������������������������������(������������������������������������������bindingX) + this.moveCellByAnimation('close') + } + } + }) + }, + // ������bindingX + unbindBindingX() { + // ������������������������ + if (this?.panEvent?.token != 0) { + bindingX.unbind({ + token: this.panEvent?.token, + // pan��������������� + eventType: 'pan' + }) + } + }, + // ������������������������ + queryRect() { + // ���������������������������������getRectByDom������������promise + const promiseAll = this.options.map((item, index) => { + return this.getRectByDom(this.$refs[`u-swipe-action-item__right__button-${index}`][0]) + }) + // ������promise.all������������������������������������������������������������������ + Promise.all(promiseAll).then(sizes => { + this.buttons = sizes + // ��������������������������� + this.buttonsWidth = sizes.reduce((sum, cur) => sum + cur.width, 0) + }) + }, + // ������nvue���dom��������������������������� + getRectByDom(ref) { + return new Promise(resolve => { + dom.getComponentRect(ref, res => { + resolve(res.size) + }) + }) + }, + // ������������������������������������������ + moveCellByAnimation(status = 'open') { + if(this.moving) return + // ������������������ + this.moveing = true + const content = this.getContentRef() + const x = status === 'open' ? -this.buttonsWidth : 0 + animation.transition(content, { + styles: { + transform: `translateX(${x}px)`, + }, + duration: uni.$u.getDuration(this.duration, false), + timingFunction: 'ease-in-out' + }, () => { + this.moving = false + this.status = status + this.unbindBindingX() + }) + }, + // ������������ref + getContentRef() { + return this.$refs['u-swipe-action-item__content'].ref + }, + beforeDestroy() { + this.unbindBindingX() + } + } +} diff --git a/uni_modules/uview-ui/components/u-swipe-action-item/props.js b/uni_modules/uview-ui/components/u-swipe-action-item/props.js new file mode 100644 index 0000000..ed82a42 --- /dev/null +++ b/uni_modules/uview-ui/components/u-swipe-action-item/props.js @@ -0,0 +1,41 @@ +export default { + props: { + // ������������������������ + show: { + type: Boolean, + default: uni.$u.props.swipeActionItem.show + }, + // ���������������������v-for���������index��������� + name: { + type: [String, Number], + default: uni.$u.props.swipeActionItem.name + }, + // ������������ + disabled: { + type: Boolean, + default: uni.$u.props.swipeActionItem.disabled + }, + // ������������������������swipe��������� + autoClose: { + type: Boolean, + default: uni.$u.props.swipeActionItem.autoClose + }, + // ������������������������������������������������������������������������ + threshold: { + type: Number, + default: uni.$u.props.swipeActionItem.threshold + }, + // ������������������ + options: { + type: Array, + default() { + return uni.$u.props.swipeActionItem.rightOptions + } + }, + // ���������������������������ms + duration: { + type: [String, Number], + default: uni.$u.props.swipeActionItem.duration + } + } +} diff --git a/uni_modules/uview-ui/components/u-swipe-action-item/u-swipe-action-item.vue b/uni_modules/uview-ui/components/u-swipe-action-item/u-swipe-action-item.vue new file mode 100644 index 0000000..1fab304 --- /dev/null +++ b/uni_modules/uview-ui/components/u-swipe-action-item/u-swipe-action-item.vue @@ -0,0 +1,190 @@ +<template> + <view class="u-swipe-action-item" ref="u-swipe-action-item"> + <view class="u-swipe-action-item__right"> + <slot name="button"> + <view v-for="(item,index) in options" :key="index" class="u-swipe-action-item__right__button" + :ref="`u-swipe-action-item__right__button-${index}`" :style="[{ + alignItems: item.style && item.style.borderRadius ? 'center' : 'stretch' + }]" @tap="buttonClickHandler(item, index)"> + <view class="u-swipe-action-item__right__button__wrapper" :style="[{ + backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD', + borderRadius: item.style && item.style.borderRadius ? item.style.borderRadius : '0', + padding: item.style && item.style.borderRadius ? '0' : '0 15px', + }, item.style]"> + <u-icon v-if="item.icon" :name="item.icon" + :color="item.style && item.style.color ? item.style.color : '#ffffff'" + :size="item.iconSize ? $u.addUnit(item.iconSize) : item.style && item.style.fontSize ? $u.getPx(item.style.fontSize) * 1.2 : 17" + :customStyle="{ + marginRight: item.text ? '2px' : 0 + }"></u-icon> + <text v-if="item.text" class="u-swipe-action-item__right__button__wrapper__text u-line-1" + :style="[{ + color: item.style && item.style.color ? item.style.color : '#ffffff', + fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px', + lineHeight: item.style && item.style.fontSize ? item.style.fontSize : '16px', + }]">{{ item.text }}</text> + </view> + </view> + </slot> + </view> + <!-- #ifdef APP-VUE || MP-WEIXIN || H5 || MP-QQ --> + <view class="u-swipe-action-item__content" @touchstart="wxs.touchstart" @touchmove="wxs.touchmove" + @touchend="wxs.touchend" :status="status" :change:status="wxs.statusChange" :size="size" + :change:size="wxs.sizeChange"> + <!-- #endif --> + <!-- #ifdef APP-NVUE --> + <view class="u-swipe-action-item__content" ref="u-swipe-action-item__content" @panstart="onTouchstart" + @tap="clickHandler"> + <!-- #endif --> + <slot /> + </view> + </view> +</template> +<!-- #ifdef APP-VUE || MP-WEIXIN || H5 || MP-QQ --> +<script src="./index.wxs" module="wxs" lang="wxs"></script> +<!-- #endif --> +<script> + import touch from '../../libs/mixin/touch.js' + import props from './props.js'; + // #ifdef APP-NVUE + import nvue from './nvue.js'; + // #endif + // #ifdef APP-VUE || MP-WEIXIN || H5 || MP-QQ + import wxs from './wxs.js'; + // #endif + /** + * SwipeActionItem ������������������������ + * @description ��������������������������������������������������������������������������������������������� + * @tutorial https://www.uviewui.com/components/swipeAction.html + * @property {Boolean} show ��������������������������������� false ��� + * @property {String | Number} index ���������������������v-for���������index������ + * @property {Boolean} disabled ��������������������� false ��� + * @property {Boolean} autoClose ������������������������swipe������������������ true ��� + * @property {Number} threshold ��������������������������������������������������������������������������������� 30 ��� + * @property {Array} options ������������������ + * @property {String | Number} duration ���������������������������ms��������� 350 ��� + * @event {Function(index)} open ��������������������� + * @event {Function(index)} close ��������������������� + * @example <u-swipe-action><u-swipe-action-item :options="options1" ></u-swipe-action-item></u-swipe-action> + */ + export default { + name: 'u-swipe-action-item', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props, touch], + // #ifdef APP-NVUE + mixins: [uni.$u.mpMixin, uni.$u.mixin, props, nvue, touch], + // #endif + // #ifdef APP-VUE || MP-WEIXIN || H5 || MP-QQ + mixins: [uni.$u.mpMixin, uni.$u.mixin, props, touch, wxs], + // #endif + data() { + return { + // ��������������������� + size: {}, + // ���������u-swipe-action��������� + parentData: { + autoClose: true, + }, + // ���������������open-���������close-������ + status: 'close', + } + }, + watch: { + // ������wxs��������������������������������������������������������������������������������������� + wxsInit(newValue, oldValue) { + this.queryRect() + } + }, + computed: { + wxsInit() { + return [this.disabled, this.autoClose, this.threshold, this.options, this.duration] + } + }, + mounted() { + this.init() + }, + methods: { + init() { + // ������������������������ + this.updateParentData() + // #ifndef APP-NVUE + uni.$u.sleep().then(() => { + this.queryRect() + }) + // #endif + }, + updateParentData() { + // ������������mixin��� + this.getParentData('u-swipe-action') + }, + // #ifndef APP-NVUE + // ������������ + queryRect() { + this.$uGetRect('.u-swipe-action-item__right__button', true).then(buttons => { + this.size = { + buttons, + show: this.show, + disabled: this.disabled, + threshold: this.threshold, + duration: this.duration + } + }) + }, + // #endif + // ��������������� + buttonClickHandler(item, index) { + this.$emit('click', { + index, + name: this.name + }) + } + }, + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-swipe-action-item { + position: relative; + overflow: hidden; + /* #ifndef APP-NVUE || MP-WEIXIN */ + touch-action: pan-y; + /* #endif */ + + &__content { + background-color: #FFFFFF; + z-index: 10; + } + + &__right { + position: absolute; + top: 0; + bottom: 0; + right: 0; + @include flex; + + &__button { + @include flex; + justify-content: center; + overflow: hidden; + align-items: center; + + &__wrapper { + @include flex; + align-items: center; + justify-content: center; + padding: 0 15px; + + &__text { + @include flex; + align-items: center; + color: #FFFFFF; + font-size: 15px; + text-align: center; + justify-content: center; + } + } + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-swipe-action-item/wxs.js b/uni_modules/uview-ui/components/u-swipe-action-item/wxs.js new file mode 100644 index 0000000..ee49c10 --- /dev/null +++ b/uni_modules/uview-ui/components/u-swipe-action-item/wxs.js @@ -0,0 +1,15 @@ +export default { + methods: { + // ��������������� + closeHandler() { + this.status = 'close' + }, + setState(status) { + this.status = status + }, + closeOther() { + // ������������������������������������ + this.parent && this.parent.closeOther(this) + } + } +} diff --git a/uni_modules/uview-ui/components/u-swipe-action/props.js b/uni_modules/uview-ui/components/u-swipe-action/props.js new file mode 100644 index 0000000..3a84536 --- /dev/null +++ b/uni_modules/uview-ui/components/u-swipe-action/props.js @@ -0,0 +1,9 @@ +export default { + props: { + // ������������������������swipe��������� + autoClose: { + type: Boolean, + default: uni.$u.props.swipeAction.autoClose + } + } +} diff --git a/uni_modules/uview-ui/components/u-swipe-action/u-swipe-action.vue b/uni_modules/uview-ui/components/u-swipe-action/u-swipe-action.vue new file mode 100644 index 0000000..ad8f019 --- /dev/null +++ b/uni_modules/uview-ui/components/u-swipe-action/u-swipe-action.vue @@ -0,0 +1,67 @@ +<template> + <view class="u-swipe-action"> + <slot></slot> + </view> +</template> + +<script> + import props from './props.js'; + /** + * SwipeAction ��������������� + * @description ��������������������������������������������������������������������������������������������� + * @tutorial https://www.uviewui.com/components/swipeAction.html + * @property {Boolean} autoClose ������������������������swipe��������� + * @event {Function(index)} click ��������������������� + * @example <u-swipe-action><u-swipe-action-item :rightOptions="options1" ></u-swipe-action-item></u-swipe-action> + */ + export default { + name: 'u-swipe-action', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return {} + }, + provide() { + return { + swipeAction: this + } + }, + computed: { + // ������computed���������������������������u-swipe-action-item��������������������������������������������������������������������������������������������������������������� + // ������������������������������������������������������parentData������������watch���������������������������������������������������������������(u-swipe-action-item) + // ��������������������������������������� + parentData() { + return [this.autoClose] + } + }, + watch: { + // ��������������������������������������������������������������������������������������� + parentData() { + if (this.children.length) { + this.children.map(child => { + // ���������������(u-swipe-action-item)���������updateParentData���������������������������(������������������������������������������������������������������) + typeof(child.updateParentData) === 'function' && child.updateParentData() + }) + } + }, + }, + created() { + this.children = [] + }, + methods: { + closeOther(child) { + if (this.autoClose) { + // ������������������������������������������������������������������������������ + this.children.map((item, index) => { + if (child !== item) { + item.closeHandler() + } + }) + } + } + } + } +</script> + +<style lang="scss" scoped> + +</style> diff --git a/uni_modules/uview-ui/components/u-swiper-indicator/props.js b/uni_modules/uview-ui/components/u-swiper-indicator/props.js new file mode 100644 index 0000000..302aca7 --- /dev/null +++ b/uni_modules/uview-ui/components/u-swiper-indicator/props.js @@ -0,0 +1,29 @@ +export default { + props: { + // ��������������� + length: { + type: [String, Number], + default: uni.$u.props.swiperIndicator.length + }, + // ������������������������������������������ + current: { + type: [String, Number], + default: uni.$u.props.swiperIndicator.current + }, + // ������������������������ + indicatorActiveColor: { + type: String, + default: uni.$u.props.swiperIndicator.indicatorActiveColor + }, + // ������������������������ + indicatorInactiveColor: { + type: String, + default: uni.$u.props.swiperIndicator.indicatorInactiveColor + }, + // ������������������line-���������dot-������ + indicatorMode: { + type: String, + default: uni.$u.props.swiperIndicator.indicatorMode + } + } +} diff --git a/uni_modules/uview-ui/components/u-swiper-indicator/u-swiper-indicator.vue b/uni_modules/uview-ui/components/u-swiper-indicator/u-swiper-indicator.vue new file mode 100644 index 0000000..8923e13 --- /dev/null +++ b/uni_modules/uview-ui/components/u-swiper-indicator/u-swiper-indicator.vue @@ -0,0 +1,110 @@ +<template> + <view class="u-swiper-indicator"> + <view + class="u-swiper-indicator__wrapper" + v-if="indicatorMode === 'line'" + :class="[`u-swiper-indicator__wrapper--${indicatorMode}`]" + :style="{ + width: $u.addUnit(lineWidth * length), + backgroundColor: indicatorInactiveColor + }" + > + <view + class="u-swiper-indicator__wrapper--line__bar" + :style="[lineStyle]" + ></view> + </view> + <view + class="u-swiper-indicator__wrapper" + v-if="indicatorMode === 'dot'" + > + <view + class="u-swiper-indicator__wrapper__dot" + v-for="(item, index) in length" + :key="index" + :class="[index === current && 'u-swiper-indicator__wrapper__dot--active']" + :style="[dotStyle(index)]" + > + + </view> + </view> + </view> +</template> + +<script> + import props from './props.js'; + /** + * SwiperIndicator ������������������ + * @description ���������������������������������������������������������,������������������ + * @tutorial https://www.uviewui.com/components/swiper.html + * @property {String | Number} length ������������������������ 0 ��� + * @property {String | Number} current ��������������������������������������������������� 0 ��� + * @property {String} indicatorActiveColor ������������������������ + * @property {String} indicatorInactiveColor ������������������������ + * @property {String} indicatorMode ������������������������ 'line' ��� + * @example <u-swiper :list="list4" indicator keyName="url" :autoplay="false"></u-swiper> + */ + export default { + name: 'u-swiper-indicator', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + lineWidth: 22 + } + }, + computed: { + // ��������������������������� + lineStyle() { + let style = {} + style.width = uni.$u.addUnit(this.lineWidth) + style.transform = `translateX(${ uni.$u.addUnit(this.current * this.lineWidth) })` + style.backgroundColor = this.indicatorActiveColor + return style + }, + // ��������������������������� + dotStyle() { + return index => { + let style = {} + style.backgroundColor = index === this.current ? this.indicatorActiveColor : this.indicatorInactiveColor + return style + } + } + }, + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-swiper-indicator { + + &__wrapper { + @include flex; + + &--line { + border-radius: 100px; + height: 4px; + + &__bar { + width: 22px; + height: 4px; + border-radius: 100px; + background-color: #FFFFFF; + transition: transform 0.3s; + } + } + + &__dot { + width: 5px; + height: 5px; + border-radius: 100px; + margin: 0 4px; + + &--active { + width: 12px; + } + } + + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-swiper/props.js b/uni_modules/uview-ui/components/u-swiper/props.js new file mode 100644 index 0000000..bac6d31 --- /dev/null +++ b/uni_modules/uview-ui/components/u-swiper/props.js @@ -0,0 +1,125 @@ +export default { + props: { + // ������������������������������������������������������������keyName��������������������� + list: { + type: Array, + default: uni.$u.props.swiper.list + }, + // ��������������������������� + indicator: { + type: Boolean, + default: uni.$u.props.swiper.indicator + }, + // ������������������������ + indicatorActiveColor: { + type: String, + default: uni.$u.props.swiper.indicatorActiveColor + }, + // ������������������������ + indicatorInactiveColor: { + type: String, + default: uni.$u.props.swiper.indicatorInactiveColor + }, + // ���������������������������bottom���left���right������������ + indicatorStyle: { + type: [String, Object], + default: uni.$u.props.swiper.indicatorStyle + }, + // ������������������line-���������dot-������ + indicatorMode: { + type: String, + default: uni.$u.props.swiper.indicatorMode + }, + // ������������������ + autoplay: { + type: Boolean, + default: uni.$u.props.swiper.autoplay + }, + // ��������������������� index + current: { + type: [String, Number], + default: uni.$u.props.swiper.current + }, + // ��������������������� item-id ������������ current ��������������� + currentItemId: { + type: String, + default: uni.$u.props.swiper.currentItemId + }, + // ������������������������������ + interval: { + type: [String, Number], + default: uni.$u.props.swiper.interval + }, + // ������������������������������ + duration: { + type: [String, Number], + default: uni.$u.props.swiper.duration + }, + // ������������������������������������������ + circular: { + type: Boolean, + default: uni.$u.props.swiper.circular + }, + // ������������������������������������������������������nvue��������������������� + previousMargin: { + type: [String, Number], + default: uni.$u.props.swiper.previousMargin + }, + // ������������������������������������������������������nvue��������������������� + nextMargin: { + type: [String, Number], + default: uni.$u.props.swiper.nextMargin + }, + // ������������������������������������������������������������������������������ + acceleration: { + type: Boolean, + default: uni.$u.props.swiper.acceleration + }, + // ������������������������������nvue������������������������������ + displayMultipleItems: { + type: Number, + default: uni.$u.props.swiper.displayMultipleItems + }, + // ������swiper���������������������������������������default���linear���easeInCubic���easeOutCubic���easeInOutCubic + // ��������������������������� + easingFunction: { + type: String, + default: uni.$u.props.swiper.easingFunction + }, + // list��������������������������������������� + keyName: { + type: String, + default: uni.$u.props.swiper.keyName + }, + // ��������������������� + imgMode: { + type: String, + default: uni.$u.props.swiper.imgMode + }, + // ������������ + height: { + type: [String, Number], + default: uni.$u.props.swiper.height + }, + // ������������ + bgColor: { + type: String, + default: uni.$u.props.swiper.bgColor + }, + // ��������������������������������������������� + radius: { + type: [String, Number], + default: uni.$u.props.swiper.radius + }, + // ��������������� + loading: { + type: Boolean, + default: uni.$u.props.swiper.loading + }, + // ���������������������������������������������title������ + showTitle: { + type: Boolean, + default: uni.$u.props.swiper.showTitle + } + } +} diff --git a/uni_modules/uview-ui/components/u-swiper/u-swiper.vue b/uni_modules/uview-ui/components/u-swiper/u-swiper.vue new file mode 100644 index 0000000..0cfb229 --- /dev/null +++ b/uni_modules/uview-ui/components/u-swiper/u-swiper.vue @@ -0,0 +1,255 @@ +<template> + <view + class="u-swiper" + :style="{ + backgroundColor: bgColor, + height: $u.addUnit(height), + borderRadius: $u.addUnit(radius) + }" + > + <view + class="u-swiper__loading" + v-if="loading" + > + <u-loading-icon mode="circle"></u-loading-icon> + </view> + <swiper + v-else + class="u-swiper__wrapper" + :style="{ + height: $u.addUnit(height), + }" + @change="change" + :circular="circular" + :interval="interval" + :duration="duration" + :autoplay="autoplay" + :current="current" + :currentItemId="currentItemId" + :previousMargin="$u.addUnit(previousMargin)" + :nextMargin="$u.addUnit(nextMargin)" + :acceleration="acceleration" + :displayMultipleItems="displayMultipleItems" + :easingFunction="easingFunction" + > + <swiper-item + class="u-swiper__wrapper__item" + v-for="(item, index) in list" + :key="index" + > + <view + class="u-swiper__wrapper__item__wrapper" + :style="[itemStyle(index)]" + > + <!-- ���nvue������image���������������������������������������������������flex:1��������������������������������������������������� --> + <image + class="u-swiper__wrapper__item__wrapper__image" + v-if="getItemType(item) === 'image'" + :src="getSource(item)" + :mode="imgMode" + @tap="clickHandler(index)" + :style="{ + height: $u.addUnit(height), + borderRadius: $u.addUnit(radius) + }" + ></image> + <video + class="u-swiper__wrapper__item__wrapper__video" + v-if="getItemType(item) === 'video'" + :id="`video-${index}`" + :enable-progress-gesture="false" + :src="getSource(item)" + :poster="getPoster(item)" + :title="showTitle && $u.test.object(item) && item.title ? item.title : ''" + :style="{ + height: $u.addUnit(height) + }" + controls + @tap="clickHandler(index)" + ></video> + <text + v-if="showTitle && $u.test.object(item) && item.title && $u.test.image(getSource(item))" + class="u-swiper__wrapper__item__wrapper__title u-line-1" + >{{ item.title }}</text> + </view> + </swiper-item> + </swiper> + <view class="u-swiper__indicator" :style="[$u.addStyle(indicatorStyle)]"> + <slot name="indicator"> + <u-swiper-indicator + v-if="!loading && indicator && !showTitle" + :indicatorActiveColor="indicatorActiveColor" + :indicatorInactiveColor="indicatorInactiveColor" + :length="list.length" + :current="currentIndex" + :indicatorMode="indicatorMode" + ></u-swiper-indicator> + </slot> + </view> + </view> +</template> + +<script> + import props from './props.js'; + /** + * Swiper ��������� + * @description ���������������������������������������������������������,������������������ + * @tutorial https://www.uviewui.com/components/swiper.html + * @property {Array} list ��������������� + * @property {Boolean} indicator ������������������������������������ false ��� + * @property {String} indicatorActiveColor ��������������������������������� '#FFFFFF' ��� + * @property {String} indicatorInactiveColor ��������������������������������� 'rgba(255, 255, 255, 0.35)' ��� + * @property {String | Object} indicatorStyle ���������������������������bottom���left���right������������ + * @property {String} indicatorMode ������������������������ 'line' ��� + * @property {Boolean} autoplay ��������������������������� true ��� + * @property {String | Number} current ��������������������� index��������� 0 ��� + * @property {String} currentItemId ��������������������� item-id ������������ current ��������������� + * @property {String | Number} interval ���������������������������������ms������������ 3000 ��� + * @property {String | Number} duration ���������������������������������ms������������ 300 ��� + * @property {Boolean} circular ��������������������������������������������������� false ��� + * @property {String | Number} previousMargin ������������������������������������������������������nvue������������������������������ 0 ��� + * @property {String | Number} nextMargin ������������������������������������������������������nvue������������������������������ 0 ��� + * @property {Boolean} acceleration ��������������������������������������������������������������������������������������� false ��� + * @property {Number} displayMultipleItems ������������������������������nvue��������������������������������������� 1 ��� + * @property {String} easingFunction ������swiper��������������������������� ������������������������������������ 'default' ��� + * @property {String} keyName list������������������������������������������������ 'url' ��� + * @property {String} imgMode ������������������������������ 'aspectFill' ��� + * @property {String | Number} height ��������������������� 130 ��� + * @property {String} bgColor ��������������������� '#f3f4f6' ��� + * @property {String | Number} radius ������������������������������������������������������ 4 ��� + * @property {Boolean} loading ������������������������ false ��� + * @property {Boolean} showTitle ���������������������������������������������title��������������� false ��� + * @event {Function(index)} click ������������������������ index���������������������������������0������ + * @event {Function(index)} change ������������������������(������������������������) index������������������������������������0������ + * @example <u-swiper :list="list4" keyName="url" :autoplay="false"></u-swiper> + */ + export default { + name: 'u-swiper', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + currentIndex: 0 + } + }, + watch: { + current(val, preVal) { + if(val === preVal) return; + this.currentIndex = val; // ������������������������ + } + }, + computed: { + itemStyle() { + return index => { + const style = {} + // #ifndef APP-NVUE || MP-TOUTIAO + // ������������������������������������nvue��������� + // ������������������������������������������������������������������ + if (this.nextMargin && this.previousMargin) { + style.borderRadius = uni.$u.addUnit(this.radius) + if (index !== this.currentIndex) style.transform = 'scale(0.92)' + } + // #endif + return style + } + } + }, + methods: { + getItemType(item) { + if (typeof item === 'string') return uni.$u.test.video(this.getSource(item)) ? 'video' : 'image' + if (typeof item === 'object' && this.keyName) { + if (!item.type) return uni.$u.test.video(this.getSource(item)) ? 'video' : 'image' + if (item.type === 'image') return 'image' + if (item.type === 'video') return 'video' + return 'image' + } + }, + // ������������������������������������������������������������������������������������������������������������keyName + getSource(item) { + if (typeof item === 'string') return item + if (typeof item === 'object' && this.keyName) return item[this.keyName] + else uni.$u.error('������������������������������') + return '' + }, + // ������������������ + change(e) { + // ��������������������� + const { + current + } = e.detail + this.pauseVideo(this.currentIndex) + this.currentIndex = current + this.$emit('change', e.detail) + }, + // ������������������������������������ + pauseVideo(index) { + const lastItem = this.getSource(this.list[index]) + if (uni.$u.test.video(lastItem)) { + // ��������������������������������� + const video = uni.createVideoContext(`video-${index}`, this) + video.pause() + } + }, + // ���������������item��������������������������������������� + getPoster(item) { + return typeof item === 'object' && item.poster ? item.poster : '' + }, + // ������������item + clickHandler(index) { + this.$emit('click', index) + } + }, + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-swiper { + @include flex; + justify-content: center; + align-items: center; + position: relative; + overflow: hidden; + + &__wrapper { + flex: 1; + + &__item { + flex: 1; + + &__wrapper { + @include flex; + position: relative; + overflow: hidden; + transition: transform 0.3s; + flex: 1; + + &__image { + flex: 1; + } + + &__video { + flex: 1; + } + + &__title { + position: absolute; + background-color: rgba(0, 0, 0, 0.3); + bottom: 0; + left: 0; + right: 0; + font-size: 28rpx; + padding: 12rpx 24rpx; + color: #FFFFFF; + flex: 1; + } + } + } + } + + &__indicator { + position: absolute; + bottom: 10px; + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-switch/props.js b/uni_modules/uview-ui/components/u-switch/props.js new file mode 100644 index 0000000..4eef963 --- /dev/null +++ b/uni_modules/uview-ui/components/u-switch/props.js @@ -0,0 +1,54 @@ +export default { + props: { + // ������������������������ + loading: { + type: Boolean, + default: uni.$u.props.switch.loading + }, + // ��������������������� + disabled: { + type: Boolean, + default: uni.$u.props.switch.disabled + }, + // ���������������������px + size: { + type: [String, Number], + default: uni.$u.props.switch.size + }, + // ������������������������ + activeColor: { + type: String, + default: uni.$u.props.switch.activeColor + }, + // ������������������������ + inactiveColor: { + type: String, + default: uni.$u.props.switch.inactiveColor + }, + // ������v-model������������������ + value: { + type: [Boolean, String, Number], + default: uni.$u.props.switch.value + }, + // switch��������������� + activeValue: { + type: [String, Number, Boolean], + default: uni.$u.props.switch.activeValue + }, + // switch��������������� + inactiveValue: { + type: [String, Number, Boolean], + default: uni.$u.props.switch.inactiveValue + }, + // ��������������������������������������������������������������� + asyncChange: { + type: Boolean, + default: uni.$u.props.switch.asyncChange + }, + // ��������������������������� + space: { + type: [String, Number], + default: uni.$u.props.switch.space + } + } +} diff --git a/uni_modules/uview-ui/components/u-switch/u-switch.vue b/uni_modules/uview-ui/components/u-switch/u-switch.vue new file mode 100644 index 0000000..6f8577b --- /dev/null +++ b/uni_modules/uview-ui/components/u-switch/u-switch.vue @@ -0,0 +1,177 @@ +<template> + <view + class="u-switch" + :class="[disabled && 'u-switch--disabled']" + :style="[switchStyle, $u.addStyle(customStyle)]" + @tap="clickHandler" + > + <view + class="u-switch__bg" + :style="[bgStyle]" + > + </view> + <view + class="u-switch__node" + :class="[value && 'u-switch__node--on']" + :style="[nodeStyle]" + ref="u-switch__node" + > + <u-loading-icon + :show="loading" + mode="circle" + timingFunction='linear' + :color="value ? activeColor : '#AAABAD'" + :size="size * 0.6" + /> + </view> + </view> +</template> + +<script> + import props from './props.js'; + /** + * switch ��������������� + * @description ��������������������������������������������������������������������������� + * @tutorial https://www.uviewui.com/components/switch.html + * @property {Boolean} loading ������������������������������ false ��� + * @property {Boolean} disabled ��������������������� false ��� + * @property {String | Number} size ���������������������px ��������� 25 ��� + * @property {String} activeColor ��������������������� ��������� '#2979ff' ��� + * @property {String} inactiveColor ��������������������� ��������� '#ffffff' ��� + * @property {Boolean | String | Number} value ������v-model������������������ ��������� false ��� + * @property {Boolean | String | Number} activeValue ������������������������change������������������ ��������� true ��� + * @property {Boolean | String | Number} inactiveValue ������������������������change������������������ ��������� false ��� + * @property {Boolean} asyncChange ��������������������������������������������������������������� ��������� false ��� + * @property {String | Number} space ��������������������������� ��������� 0 ��� + * @property {Object} customStyle ��������������������������������� + * + * @event {Function} change ���switch������������������������ + * @example <u-switch v-model="checked" active-color="red" inactive-color="#eee"></u-switch> + */ + export default { + name: "u-switch", + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + watch: { + value: { + immediate: true, + handler(n) { + if(n !== this.inactiveValue && n !== this.activeValue) { + uni.$u.error('v-model���������������������inactiveValue���activeValue������������') + } + } + } + }, + data() { + return { + bgColor: '#ffffff' + } + }, + computed: { + isActive(){ + return this.value === this.activeValue; + }, + switchStyle() { + let style = {} + // ���������������2������������������������������������������������node������������������������������ + style.width = uni.$u.addUnit(this.size * 2 + 2) + style.height = uni.$u.addUnit(Number(this.size) + 2) + // style.borderColor = this.value ? 'rgba(0, 0, 0, 0)' : 'rgba(0, 0, 0, 0.12)' + // ������������������������������������������name���������������������������(������������������������) + // ������������������������������������������������������������������������������������������������������������ + if(this.customInactiveColor) { + style.borderColor = 'rgba(0, 0, 0, 0)' + } + style.backgroundColor = this.isActive ? this.activeColor : this.inactiveColor + return style; + }, + nodeStyle() { + let style = {} + // ������������������������������������node������������������������������������������������������������������������ + style.width = uni.$u.addUnit(this.size - this.space) + style.height = uni.$u.addUnit(this.size - this.space) + const translateX = this.isActive ? uni.$u.addUnit(this.space) : uni.$u.addUnit(this.size); + style.transform = `translateX(-${translateX})` + return style + }, + bgStyle() { + let style = {} + // ������������������������������������HTML������������������switch������������������������������������������������(���������������) + style.width = uni.$u.addUnit(Number(this.size) * 2 - this.size / 2) + style.height = uni.$u.addUnit(this.size) + style.backgroundColor = this.inactiveColor + // ��������������������������������������������� + style.transform = `scale(${this.isActive ? 0 : 1})` + return style + }, + customInactiveColor() { + // ���������������������������������������������������������������������������node��������������������������������������� + return this.inactiveColor !== '#fff' && this.inactiveColor !== '#ffffff' + } + }, + methods: { + clickHandler() { + if (!this.disabled && !this.loading) { + const oldValue = this.isActive ? this.inactiveValue : this.activeValue + if(!this.asyncChange) { + this.$emit('input', oldValue) + } + // ���������������������������������������������������value��������������������������������������������������� + this.$nextTick(() => { + this.$emit('change', oldValue) + }) + } + } + } + }; +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-switch { + @include flex(row); + /* #ifndef APP-NVUE */ + box-sizing: border-box; + /* #endif */ + position: relative; + background-color: #fff; + border-width: 1px; + border-radius: 100px; + transition: background-color 0.4s; + border-color: rgba(0, 0, 0, 0.12); + border-style: solid; + justify-content: flex-end; + align-items: center; + // ������weex���������������������KPI���������������bug������������������������������������ + // ���������iOS���������������������������������������������switch��������������� + overflow: hidden; + + &__node { + @include flex(row); + align-items: center; + justify-content: center; + border-radius: 100px; + background-color: #fff; + border-radius: 100px; + box-shadow: 1px 1px 1px 0 rgba(0, 0, 0, 0.25); + transition-property: transform; + transition-duration: 0.4s; + transition-timing-function: cubic-bezier(0.3, 1.05, 0.4, 1.05); + } + + &__bg { + position: absolute; + border-radius: 100px; + background-color: #FFFFFF; + transition-property: transform; + transition-duration: 0.4s; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + transition-timing-function: ease; + } + + &--disabled { + opacity: 0.6; + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-tabbar-item/props.js b/uni_modules/uview-ui/components/u-tabbar-item/props.js new file mode 100644 index 0000000..a2e6a24 --- /dev/null +++ b/uni_modules/uview-ui/components/u-tabbar-item/props.js @@ -0,0 +1,35 @@ +export default { + props: { + // item���������������������������u-tabbar���value������������������������ + name: { + type: [String, Number, null], + default: uni.$u.props.tabbarItem.name + }, + // uView��������������������������������������� + icon: { + icon: String, + default: uni.$u.props.tabbarItem.icon + }, + // ������������������������������ + badge: { + type: [String, Number, null], + default: uni.$u.props.tabbarItem.badge + }, + // ���������������������������������badge������ + dot: { + type: Boolean, + default: uni.$u.props.tabbarItem.dot + }, + // ������������ + text: { + type: String, + default: uni.$u.props.tabbarItem.text + }, + // ������������������������������������������������������������������top���right������ + badgeStyle: { + type: [Object, String], + default: uni.$u.props.tabbarItem.badgeStyle + } + + } +} diff --git a/uni_modules/uview-ui/components/u-tabbar-item/u-tabbar-item.vue b/uni_modules/uview-ui/components/u-tabbar-item/u-tabbar-item.vue new file mode 100644 index 0000000..8ee00cf --- /dev/null +++ b/uni_modules/uview-ui/components/u-tabbar-item/u-tabbar-item.vue @@ -0,0 +1,142 @@ +<template> + <view + class="u-tabbar-item" + :style="[$u.addStyle(customStyle)]" + @tap="clickHandler" + > + <view class="u-tabbar-item__icon"> + <u-icon + v-if="icon" + :name="icon" + :color="isActive? parentData.activeColor : parentData.inactiveColor" + :size="20" + ></u-icon> + <template v-else> + <slot + v-if="isActive" + name="active-icon" + /> + <slot + v-else + name="inactive-icon" + /> + </template> + <u-badge + absolute + :offset="[0, dot ? '34rpx' : badge > 9 ? '14rpx' : '20rpx']" + :customStyle="badgeStyle" + :isDot="dot" + :value="badge || (dot ? 1 : null)" + :show="dot || badge > 0" + ></u-badge> + </view> + + <slot name="text"> + <text + class="u-tabbar-item__text" + :style="{ + color: isActive? parentData.activeColor : parentData.inactiveColor + }" + >{{ text }}</text> + </slot> + </view> +</template> + +<script> + import props from './props.js'; + /** + * TabbarItem ������������������������ + * @description ���������������������������tabbar������������ + * @tutorial https://www.uviewui.com/components/tabbar.html + * @property {String | Number} name item���������������������������u-tabbar���value������������������������ + * @property {String} icon uView��������������������������������������� + * @property {String | Number} badge ������������������������������ + * @property {Boolean} dot ���������������������������������badge��������������� false ��� + * @property {String} text ������������ + * @property {Object | String} badgeStyle ������������������������������������������������������������������top���right��������������� 'top: 6px;right:2px;' ��� + * @property {Object} customStyle ��������������������������������� + * + * @example <u-tabbar :value="value2" :placeholder="false" @change="name => value2 = name" :fixed="false" :safeAreaInsetBottom="false"><u-tabbar-item text="������" icon="home" dot ></u-tabbar-item></u-tabbar> + */ + export default { + name: 'u-tabbar-item', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + isActive: false, // ������������������������ + parentData: { + value: null, + activeColor: '', + inactiveColor: '' + } + } + }, + created() { + this.init() + }, + methods: { + init() { + // ���������������������������provide/inject������������������������������������������������������created��������������������������� + this.updateParentData() + if (!this.parent) { + uni.$u.error('u-tabbar-item������������u-tabbar������������') + } + // ���������������u-tabbar���children������������������ + const index = this.parent.children.indexOf(this) + // ������������������name(������������������name���������index������)������������������������value������ + this.isActive = (this.name || index) === this.parentData.value + }, + updateParentData() { + // ������������mixin��� + this.getParentData('u-tabbar') + }, + // ���������������������������u-tabbar������ + updateFromParent() { + // ��������������� + this.init() + }, + clickHandler() { + this.$nextTick(() => { + const index = this.parent.children.indexOf(this) + const name = this.name || index + // ���������item���������������item���������change������ + if (name !== this.parent.value) { + this.parent.$emit('change', name) + } + this.$emit('click', name) + }) + } + }, + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-tabbar-item { + @include flex(column); + align-items: center; + justify-content: center; + flex: 1; + + &__icon { + @include flex; + position: relative; + width: 150rpx; + justify-content: center; + } + + &__text { + margin-top: 2px; + font-size: 12px; + color: $u-content-color; + } + } + + /* #ifdef MP */ + // ������������������������shadow DOM������������������������������������������flex: 1������������������ + :host { + flex: 1 + } + /* #endif */ +</style> diff --git a/uni_modules/uview-ui/components/u-tabbar/props.js b/uni_modules/uview-ui/components/u-tabbar/props.js new file mode 100644 index 0000000..7f8171c --- /dev/null +++ b/uni_modules/uview-ui/components/u-tabbar/props.js @@ -0,0 +1,44 @@ +export default { + props: { + // ������������������name + value: { + type: [String, Number, null], + default: uni.$u.props.tabbar.value + }, + // ���������iPhoneX������������������������ + safeAreaInsetBottom: { + type: Boolean, + default: uni.$u.props.tabbar.safeAreaInsetBottom + }, + // ������������������������ + border: { + type: Boolean, + default: uni.$u.props.tabbar.border + }, + // ������������z-index + zIndex: { + type: [String, Number], + default: uni.$u.props.tabbar.zIndex + }, + // ��������������������� + activeColor: { + type: String, + default: uni.$u.props.tabbar.activeColor + }, + // ������������������������ + inactiveColor: { + type: String, + default: uni.$u.props.tabbar.inactiveColor + }, + // ��������������������� + fixed: { + type: Boolean, + default: uni.$u.props.tabbar.fixed + }, + // fixed��������������������������������������������������������������������� + placeholder: { + type: Boolean, + default: uni.$u.props.tabbar.placeholder + } + } +} diff --git a/uni_modules/uview-ui/components/u-tabbar/u-tabbar.vue b/uni_modules/uview-ui/components/u-tabbar/u-tabbar.vue new file mode 100644 index 0000000..953f33a --- /dev/null +++ b/uni_modules/uview-ui/components/u-tabbar/u-tabbar.vue @@ -0,0 +1,141 @@ +<template> + <view class="u-tabbar"> + <view + class="u-tabbar__content" + ref="u-tabbar__content" + @touchmove.stop.prevent="noop" + :class="[border && 'u-border-top', fixed && 'u-tabbar--fixed']" + :style="[tabbarStyle]" + > + <view class="u-tabbar__content__item-wrapper"> + <slot /> + </view> + <u-safe-bottom v-if="safeAreaInsetBottom"></u-safe-bottom> + </view> + <view + class="u-tabbar__placeholder" + v-if="placeholder" + :style="{ + height: placeholderHeight + 'px', + }" + ></view> + </view> +</template> + +<script> + import props from './props.js'; + // #ifdef APP-NVUE + const dom = uni.requireNativePlugin('dom') + // #endif + /** + * Tabbar ��������������� + * @description ���������������������������tabbar������������ + * @tutorial https://www.uviewui.com/components/tabbar.html + * @property {String | Number} value ������������������name + * @property {Boolean} safeAreaInsetBottom ���������iPhoneX��������������������������������� true ��� + * @property {Boolean} border ��������������������������������� true ��� + * @property {String | Number} zIndex ������������z-index��������� 1 ��� + * @property {String} activeColor ������������������������������ '#1989fa' ��� + * @property {String} inactiveColor ��������������������������������� '#7d7e80' ��� + * @property {Boolean} fixed ������������������������������ true ��� + * @property {Boolean} placeholder fixed������������������������������������������������������������������������������ true ��� + * @property {Object} customStyle ��������������������������������� + * + * @example <u-tabbar :value="value2" :placeholder="false" @change="name => value2 = name" :fixed="false" :safeAreaInsetBottom="false"><u-tabbar-item text="������" icon="home" dot ></u-tabbar-item></u-tabbar> + */ + export default { + name: 'u-tabbar', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + placeholderHeight: 0 + } + }, + computed: { + tabbarStyle() { + const style = { + zIndex: this.zIndex + } + // ������������������������customStyle������ + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) + }, + // ���������������������������������������computed��������������������� + updateChild() { + return [this.value, this.activeColor, this.inactiveColor] + }, + updatePlaceholder() { + return [this.fixed, this.placeholder] + } + }, + watch: { + updateChild() { + // ������updateChildren��������������������������������������������������������������� + this.updateChildren() + }, + updatePlaceholder() { + // ������fixed���placeholder��������������������������������������������������������� + this.setPlaceholderHeight() + } + }, + created() { + this.children = [] + }, + mounted() { + this.setPlaceholderHeight() + }, + methods: { + updateChildren() { + // ���������������������������������������������updateFromParent������������������ + this.children.length && this.children.map(child => child.updateFromParent()) + }, + // ��������������������������������������� + async setPlaceholderHeight() { + if (!this.fixed || !this.placeholder) return + // ������������������ + await uni.$u.sleep(20) + // #ifndef APP-NVUE + this.$uGetRect('.u-tabbar__content').then(({height = 50}) => { + // ������IOS safearea bottom ��������������� + this.placeholderHeight = height + }) + // #endif + + // #ifdef APP-NVUE + dom.getComponentRect(this.$refs['u-tabbar__content'], (res) => { + const { + size + } = res + this.placeholderHeight = size.height + }) + // #endif + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-tabbar { + @include flex(column); + flex: 1; + justify-content: center; + + &__content { + @include flex(column); + background-color: #fff; + + &__item-wrapper { + height: 50px; + @include flex(row); + } + } + + &--fixed { + position: fixed; + bottom: 0; + left: 0; + right: 0; + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-table/props.js b/uni_modules/uview-ui/components/u-table/props.js new file mode 100644 index 0000000..7c11331 --- /dev/null +++ b/uni_modules/uview-ui/components/u-table/props.js @@ -0,0 +1,5 @@ +export default { + props: { + + } +} diff --git a/uni_modules/uview-ui/components/u-table/u-table.vue b/uni_modules/uview-ui/components/u-table/u-table.vue new file mode 100644 index 0000000..b64ce69 --- /dev/null +++ b/uni_modules/uview-ui/components/u-table/u-table.vue @@ -0,0 +1,29 @@ +<template> + <view class="u-table"> + + </view> +</template> + +<script> + import props from './props.js'; + /** + * Table ������ + * @description ������������������������������������������������������������ ���������������������HTML���table������������table���tr���th���td������������������ + * @tutorial https://www.uviewui.com/components/table.html + * @example <u-table><u-tr><u-th>������</u-th </u-tr> <u-tr><u-td>������������</u-td> </u-tr> <u-tr><u-td>������������</u-td> </u-tr></u-table> + */ + export default { + name: 'u-table', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + +</style> diff --git a/uni_modules/uview-ui/components/u-tabs-item/props.js b/uni_modules/uview-ui/components/u-tabs-item/props.js new file mode 100644 index 0000000..7c11331 --- /dev/null +++ b/uni_modules/uview-ui/components/u-tabs-item/props.js @@ -0,0 +1,5 @@ +export default { + props: { + + } +} diff --git a/uni_modules/uview-ui/components/u-tabs-item/u-tabs-item.vue b/uni_modules/uview-ui/components/u-tabs-item/u-tabs-item.vue new file mode 100644 index 0000000..effb796 --- /dev/null +++ b/uni_modules/uview-ui/components/u-tabs-item/u-tabs-item.vue @@ -0,0 +1,29 @@ +<template> + <swiper-item> + <slot /> + </swiper-item> +</template> + +<script> + import props from './props.js'; + /** + * TabsItem tabs������������������������ + * @description tabs��������������������������������������������������������������������������������������������������������������� ���������������������������������������������������������������tab������������������������������������������ + * @tutorial https://www.uviewui.com/components/tabs.html + * @property {type} prop_name + * @event {Function()} + * @example + */ + export default { + name: 'u-tabs-item', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + + } + } + } +</script> + +<style> +</style> diff --git a/uni_modules/uview-ui/components/u-tabs/props.js b/uni_modules/uview-ui/components/u-tabs/props.js new file mode 100644 index 0000000..2cfa41f --- /dev/null +++ b/uni_modules/uview-ui/components/u-tabs/props.js @@ -0,0 +1,64 @@ +export default { + props: { + // ������������������������������������ms + duration: { + type: Number, + default: uni.$u.props.tabs.duration + }, + // tabs������������ + list: { + type: Array, + default: uni.$u.props.tabs.list + }, + // ������������ + lineColor: { + type: String, + default: uni.$u.props.tabs.lineColor + }, + // ��������������������������� + activeStyle: { + type: [String, Object], + default: uni.$u.props.tabs.activeStyle + }, + // ��������������������������� + inactiveStyle: { + type: [String, Object], + default: uni.$u.props.tabs.inactiveStyle + }, + // ������������ + lineWidth: { + type: [String, Number], + default: uni.$u.props.tabs.lineWidth + }, + // ������������ + lineHeight: { + type: [String, Number], + default: uni.$u.props.tabs.lineHeight + }, + // ������������������������������������������������������������������ + lineBgSize: { + type: String, + default: uni.$u.props.tabs.lineBgSize + }, + // ������item��������� + itemStyle: { + type: [String, Object], + default: uni.$u.props.tabs.itemStyle + }, + // ��������������������� + scrollable: { + type: Boolean, + default: uni.$u.props.tabs.scrollable + }, + // ��������������������������� + current: { + type: [Number, String], + default: uni.$u.props.tabs.current + }, + // ��������������������� + keyName: { + type: String, + default: uni.$u.props.tabs.keyName + } + } +} diff --git a/uni_modules/uview-ui/components/u-tabs/u-tabs.vue b/uni_modules/uview-ui/components/u-tabs/u-tabs.vue new file mode 100644 index 0000000..9c54cc1 --- /dev/null +++ b/uni_modules/uview-ui/components/u-tabs/u-tabs.vue @@ -0,0 +1,354 @@ +<template> + <view class="u-tabs"> + <view class="u-tabs__wrapper"> + <slot name="left" /> + <view class="u-tabs__wrapper__scroll-view-wrapper"> + <scroll-view + :scroll-x="scrollable" + :scroll-left="scrollLeft" + scroll-with-animation + class="u-tabs__wrapper__scroll-view" + :show-scrollbar="false" + ref="u-tabs__wrapper__scroll-view" + > + <view + class="u-tabs__wrapper__nav" + ref="u-tabs__wrapper__nav" + > + <view + class="u-tabs__wrapper__nav__item" + v-for="(item, index) in list" + :key="index" + @tap="clickHandler(item, index)" + :ref="`u-tabs__wrapper__nav__item-${index}`" + :style="[$u.addStyle(itemStyle), {flex: scrollable ? '' : 1}]" + :class="[`u-tabs__wrapper__nav__item-${index}`, item.disabled && 'u-tabs__wrapper__nav__item--disabled']" + > + <text + :class="[item.disabled && 'u-tabs__wrapper__nav__item__text--disabled']" + class="u-tabs__wrapper__nav__item__text" + :style="[textStyle(index)]" + >{{ item[keyName] }}</text> + <u-badge + :show="!!(item.badge && (item.badge.show || item.badge.isDot || item.badge.value))" + :isDot="item.badge && item.badge.isDot || propsBadge.isDot" + :value="item.badge && item.badge.value || propsBadge.value" + :max="item.badge && item.badge.max || propsBadge.max" + :type="item.badge && item.badge.type || propsBadge.type" + :showZero="item.badge && item.badge.showZero || propsBadge.showZero" + :bgColor="item.badge && item.badge.bgColor || propsBadge.bgColor" + :color="item.badge && item.badge.color || propsBadge.color" + :shape="item.badge && item.badge.shape || propsBadge.shape" + :numberType="item.badge && item.badge.numberType || propsBadge.numberType" + :inverted="item.badge && item.badge.inverted || propsBadge.inverted" + customStyle="margin-left: 4px;" + ></u-badge> + </view> + <!-- #ifdef APP-NVUE --> + <view + class="u-tabs__wrapper__nav__line" + ref="u-tabs__wrapper__nav__line" + :style="[{ + width: $u.addUnit(lineWidth), + height: $u.addUnit(lineHeight), + background: lineColor, + backgroundSize: lineBgSize, + }]" + > + <!-- #endif --> + <!-- #ifndef APP-NVUE --> + <view + class="u-tabs__wrapper__nav__line" + ref="u-tabs__wrapper__nav__line" + :style="[{ + width: $u.addUnit(lineWidth), + transform: `translate(${lineOffsetLeft}px)`, + transitionDuration: `${firstTime ? 0 : duration}ms`, + height: $u.addUnit(lineHeight), + background: lineColor, + backgroundSize: lineBgSize, + }]" + > + <!-- #endif --> + </view> + </view> + </scroll-view> + </view> + <slot name="right" /> + </view> + </view> +</template> + +<script> + // #ifdef APP-NVUE + const animation = uni.requireNativePlugin('animation') + const dom = uni.requireNativePlugin('dom') + // #endif + import props from './props.js'; + /** + * Tabs ������ + * @description tabs��������������������������������������������������������������������������������������������������������������� ���������������������������������������������������������������tab������������������������������������������ + * @tutorial https://www.uviewui.com/components/tabs.html + * @property {String | Number} duration ������������������������������������������������������ 200 ��� + * @property {String | Number} swierWidth swiper������������������ '750rpx' ��� + * @property {String} keyName ���`list`��������������������������������������� 'name' ��� + * @event {Function(index)} change ��������������������� index: ������������������tab������������0������ + * @event {Function(index)} click ��������������������� index: ������������������tab������������0������ + * @example <u-tabs :list="list" :is-scroll="false" :current="current" @change="change"></u-tabs> + */ + export default { + name: 'u-tabs', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + firstTime: true, + scrollLeft: 0, + scrollViewWidth: 0, + lineOffsetLeft: 0, + tabsRect: { + left: 0 + }, + innerCurrent: 0, + moving: false, + } + }, + watch: { + current: { + immediate: true, + handler (newValue, oldValue) { + // ������������������������������������������������ + if (newValue !== this.innerCurrent) { + this.innerCurrent = newValue + this.$nextTick(() => { + this.resize() + }) + } + } + }, + // list������������������������list������������ + list() { + this.$nextTick(() => { + this.resize() + }) + } + }, + computed: { + textStyle() { + return index => { + const style = {} + // ������������������������������ + const customeStyle = index === this.innerCurrent ? uni.$u.addStyle(this.activeStyle) : uni.$u + .addStyle( + this.inactiveStyle) + // ���������������������������������������������������������������������������������������nvue���������������style���������������!import��������������������������� + if (this.list[index].disabled) { + style.color = '#c8c9cc' + } + return uni.$u.deepMerge(customeStyle, style) + } + }, + propsBadge() { + return uni.$u.props.badge + } + }, + async mounted() { + this.init() + }, + methods: { + setLineLeft() { + const tabItem = this.list[this.innerCurrent]; + if (!tabItem) { + return; + } + // ������������������������������ + let lineOffsetLeft = this.list + .slice(0, this.innerCurrent) + .reduce((total, curr) => total + curr.rect.width, 0); + // ������������������������px��������� + const lineWidth = uni.$u.getPx(this.lineWidth); + this.lineOffsetLeft = lineOffsetLeft + (tabItem.rect.width - lineWidth) / 2 + // #ifdef APP-NVUE + // ������������������������������������������ + this.animation(this.lineOffsetLeft, this.firstTime ? 0 : parseInt(this.duration)) + // #endif + + // ���������������������������������������������������������������������������������������tab item��������� + // ������������������������������������������nvue���������������������style���������������������������������������������������������������false(������������������������) + if (this.firstTime) { + setTimeout(() => { + this.firstTime = false + }, 10); + } + }, + // nvue������������������������ + animation(x, duration = 0) { + // #ifdef APP-NVUE + const ref = this.$refs['u-tabs__wrapper__nav__line'] + animation.transition(ref, { + styles: { + transform: `translateX(${x}px)` + }, + duration + }) + // #endif + }, + // ��������������������� + clickHandler(item, index) { + // ���������������������disabled���������������click������������������������������change��������������������������������������� + this.$emit('click', { + ...item, + index + }) + // ������disabled��������������� + if (item.disabled) return + this.innerCurrent = index + this.resize() + this.$emit('change', { + ...item, + index + }) + }, + init() { + uni.$u.sleep().then(() => { + this.resize() + }) + }, + setScrollLeft() { + // ������������tab���������������������tab���������width���left(������������������������������������������������)��������� + const tabRect = this.list[this.innerCurrent] + // ������������������item������������������ + const offsetLeft = this.list + .slice(0, this.innerCurrent) + .reduce((total, curr) => { + return total + curr.rect.width + }, 0) + // ��������������������� + const windowWidth = uni.$u.sys().windowWidth + // ������������tabs-item������������������������������������������scroll-view��������� + let scrollLeft = offsetLeft - (this.tabsRect.width - tabRect.rect.width) / 2 - (windowWidth - this.tabsRect + .right) / 2 + this.tabsRect.left / 2 + // ������������������������������scrollLeft���������������������scroll-view������������tabs��������������� + scrollLeft = Math.min(scrollLeft, this.scrollViewWidth - this.tabsRect.width) + this.scrollLeft = Math.max(0, scrollLeft) + }, + // ��������������������������� + resize() { + // ���������������list��������������� + if(this.list.length === 0) { + return + } + Promise.all([this.getTabsRect(), this.getAllItemRect()]).then(([tabsRect, itemRect = []]) => { + this.tabsRect = tabsRect + this.scrollViewWidth = 0 + itemRect.map((item, index) => { + // ������scroll-view������������������ + this.scrollViewWidth += item.width + // ���������������������item������������X��������� + this.list[index].rect = item + }) + // ���������tabs��������������������������������������� + this.setLineLeft() + this.setScrollLeft() + }) + }, + // ��������������������������� + getTabsRect() { + return new Promise(resolve => { + this.queryRect('u-tabs__wrapper__scroll-view').then(size => resolve(size)) + }) + }, + // ��������������������������� + getAllItemRect() { + return new Promise(resolve => { + const promiseAllArr = this.list.map((item, index) => this.queryRect( + `u-tabs__wrapper__nav__item-${index}`, true)) + Promise.all(promiseAllArr).then(sizes => resolve(sizes)) + }) + }, + // ��������������������������� + queryRect(el, item) { + // #ifndef APP-NVUE + // $uGetRect���uView���������������������������������������������������������https://www.uviewui.com/js/getRect.html + // ���������������������this.$uGetRect���������������uni.$u.getRect������������������������������������ + return new Promise(resolve => { + this.$uGetRect(`.${el}`).then(size => { + resolve(size) + }) + }) + // #endif + + // #ifdef APP-NVUE + // nvue������������dom������������������������ + // ������������promise���������������������������������������then������ + return new Promise(resolve => { + dom.getComponentRect(item ? this.$refs[el][0] : this.$refs[el], res => { + resolve(res.size) + }) + }) + // #endif + }, + }, + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-tabs { + + &__wrapper { + @include flex; + align-items: center; + + &__scroll-view-wrapper { + flex: 1; + /* #ifndef APP-NVUE */ + overflow: auto hidden; + /* #endif */ + } + + &__scroll-view { + @include flex; + flex: 1; + } + + &__nav { + @include flex; + position: relative; + + &__item { + padding: 0 11px; + @include flex; + align-items: center; + justify-content: center; + + &--disabled { + /* #ifndef APP-NVUE */ + cursor: not-allowed; + /* #endif */ + } + + &__text { + font-size: 15px; + color: $u-content-color; + + &--disabled { + color: $u-disabled-color !important; + } + } + } + + &__line { + height: 3px; + background: $u-primary; + width: 30px; + position: absolute; + bottom: 2px; + border-radius: 100px; + transition-property: transform; + transition-duration: 300ms; + } + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-tag/props.js b/uni_modules/uview-ui/components/u-tag/props.js new file mode 100644 index 0000000..6bffaa2 --- /dev/null +++ b/uni_modules/uview-ui/components/u-tag/props.js @@ -0,0 +1,84 @@ +export default { + props: { + // ������������info���primary���success���warning���error + type: { + type: String, + default: uni.$u.props.tag.type + }, + // ��������� + disabled: { + type: [Boolean, String], + default: uni.$u.props.tag.disabled + }, + // ������������������large���medium���mini + size: { + type: String, + default: uni.$u.props.tag.size + }, + // tag������������circle���������������������, square������������������������ + shape: { + type: String, + default: uni.$u.props.tag.shape + }, + // ������������ + text: { + type: [String, Number], + default: uni.$u.props.tag.text + }, + // ��������������������������������������������������� + bgColor: { + type: String, + default: uni.$u.props.tag.bgColor + }, + // ��������������������������������������������������������� + color: { + type: String, + default: uni.$u.props.tag.color + }, + // ��������������������� + borderColor: { + type: String, + default: uni.$u.props.tag.borderColor + }, + // ��������������������������� + closeColor: { + type: String, + default: uni.$u.props.tag.closeColor + }, + // ��������������������������������������������������������������������������������� + name: { + type: [String, Number], + default: uni.$u.props.tag.name + }, + // // ���������������dark|light|plain + // mode: { + // type: String, + // default: 'light' + // }, + // ������������������������������ + plainFill: { + type: Boolean, + default: uni.$u.props.tag.plainFill + }, + // ������������ + plain: { + type: Boolean, + default: uni.$u.props.tag.plain + }, + // ��������������� + closable: { + type: Boolean, + default: uni.$u.props.tag.closable + }, + // ������������ + show: { + type: Boolean, + default: uni.$u.props.tag.show + }, + // ��������������������������������������� + icon: { + type: String, + default: uni.$u.props.tag.icon + } + } +} diff --git a/uni_modules/uview-ui/components/u-tag/u-tag.vue b/uni_modules/uview-ui/components/u-tag/u-tag.vue new file mode 100644 index 0000000..95f33c4 --- /dev/null +++ b/uni_modules/uview-ui/components/u-tag/u-tag.vue @@ -0,0 +1,358 @@ +<template> + <u-transition + mode="fade" + :show="show" + > + <view class="u-tag-wrapper"> + <view + class="u-tag" + :class="[`u-tag--${shape}`, !plain && `u-tag--${type}`, plain && `u-tag--${type}--plain`, `u-tag--${size}`, plain && plainFill && `u-tag--${type}--plain--fill`]" + @tap.stop="clickHandler" + :style="[{ + marginRight: closable ? '10px' : 0, + marginTop: closable ? '10px' : 0, + }, style]" + > + <slot name="icon"> + <view + class="u-tag__icon" + v-if="icon" + > + <image + v-if="$u.test.image(icon)" + :src="icon" + :style="[imgStyle]" + ></image> + <u-icon + v-else + :color="elIconColor" + :name="icon" + :size="iconSize" + ></u-icon> + </view> + </slot> + <text + class="u-tag__text" + :style="[textColor]" + :class="[`u-tag__text--${type}`, plain && `u-tag__text--${type}--plain`, `u-tag__text--${size}`]" + >{{ text }}</text> + </view> + <view + class="u-tag__close" + :class="[`u-tag__close--${size}`]" + v-if="closable" + @tap.stop="closeHandler" + :style="{backgroundColor: closeColor}" + > + <u-icon + name="close" + :size="closeSize" + color="#ffffff" + ></u-icon> + </view> + </view> + </u-transition> +</template> + +<script> + import props from './props.js'; + /** + * Tag ������ + * @description tag��������������������������������������������������������������������������������������������������������������������������� + * @tutorial https://www.uviewui.com/components/tag.html + * @property {String} type ������������info���primary���success���warning���error ��������� 'primary' ��� + * @property {Boolean | String} disabled ������������������ false ��� + * @property {String} size ������������������large���medium���mini ��������� 'medium' ��� + * @property {String} shape tag������������circle���������������������, square��������������������������������� 'square' ��� + * @property {String | Number} text ��������������������� + * @property {String} bgColor ��������������������������������������������������� + * @property {String} color ��������������������������������������������������������� + * @property {String} borderColor ��������������������������������� + * @property {String} closeColor ������������������������������������ #C6C7CB��� + * @property {String | Number} name ��������������������������������������������������������������������������������� + * @property {Boolean} plainFill ��������������������������������������� false ��� + * @property {Boolean} plain ��������������������� false ��� + * @property {Boolean} closable ���������������������������true��������������������������������������������������� false ��� + * @property {Boolean} show ��������������������������� true ��� + * @property {String} icon ��������������������������������������� + * @event {Function(index)} click ��������������������� index: ���������index��������� + * @event {Function(index)} close closable���true������������������������������������ index: ���������index��������� + * @example <u-tag text="������" type="error" plain plainFill></u-tag> + */ + export default { + name: 'u-tag', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + + } + }, + computed: { + style() { + const style = {} + if (this.bgColor) { + style.backgroundColor = this.bgColor + } + if (this.color) { + style.color = this.color + } + if(this.borderColor) { + style.borderColor = this.borderColor + } + return style + }, + // nvue��������������������������������������� + textColor() { + const style = {} + if (this.color) { + style.color = this.color + } + return style + }, + imgStyle() { + const width = this.size === 'large' ? '17px' : this.size === 'medium' ? '15px' : '13px' + return { + width, + height: width + } + }, + // ��������������� + closeSize() { + const size = this.size === 'large' ? 15 : this.size === 'medium' ? 13 : 12 + return size + }, + // ������������ + iconSize() { + const size = this.size === 'large' ? 21 : this.size === 'medium' ? 19 : 16 + return size + }, + // ������������ + elIconColor() { + return this.iconColor ? this.iconColor : this.plain ? this.type : '#ffffff' + } + }, + methods: { + // ������������������ + closeHandler() { + this.$emit('close', this.name) + }, + // ������������ + clickHandler() { + this.$emit('click', this.name) + } + } + } +</script> + +<style + lang="scss" + scoped +> + @import "../../libs/css/components.scss"; + + .u-tag-wrapper { + position: relative; + } + + .u-tag { + @include flex; + align-items: center; + border-style: solid; + + &--circle { + border-radius: 100px; + } + + &--square { + border-radius: 3px; + } + + &__icon { + margin-right: 4px; + } + + &__text { + &--mini { + font-size: 12px; + line-height: 12px; + } + + &--medium { + font-size: 13px; + line-height: 13px; + } + + &--large { + font-size: 15px; + line-height: 15px; + } + } + + &--mini { + height: 22px; + line-height: 22px; + padding: 0 5px; + } + + &--medium { + height: 26px; + line-height: 22px; + padding: 0 10px; + } + + &--large { + height: 32px; + line-height: 32px; + padding: 0 15px; + } + + &--primary { + background-color: $u-primary; + border-width: 1px; + border-color: $u-primary; + } + + &--primary--plain { + border-width: 1px; + border-color: $u-primary; + } + + &--primary--plain--fill { + background-color: #ecf5ff; + } + + &__text--primary { + color: #FFFFFF; + } + + &__text--primary--plain { + color: $u-primary; + } + + &--error { + background-color: $u-error; + border-width: 1px; + border-color: $u-error; + } + + &--error--plain { + border-width: 1px; + border-color: $u-error; + } + + &--error--plain--fill { + background-color: #fef0f0; + } + + &__text--error { + color: #FFFFFF; + } + + &__text--error--plain { + color: $u-error; + } + + &--warning { + background-color: $u-warning; + border-width: 1px; + border-color: $u-warning; + } + + &--warning--plain { + border-width: 1px; + border-color: $u-warning; + } + + &--warning--plain--fill { + background-color: #fdf6ec; + } + + &__text--warning { + color: #FFFFFF; + } + + &__text--warning--plain { + color: $u-warning; + } + + &--success { + background-color: $u-success; + border-width: 1px; + border-color: $u-success; + } + + &--success--plain { + border-width: 1px; + border-color: $u-success; + } + + &--success--plain--fill { + background-color: #f5fff0; + } + + &__text--success { + color: #FFFFFF; + } + + &__text--success--plain { + color: $u-success; + } + + &--info { + background-color: $u-info; + border-width: 1px; + border-color: $u-info; + } + + &--info--plain { + border-width: 1px; + border-color: $u-info; + } + + &--info--plain--fill { + background-color: #f4f4f5; + } + + &__text--info { + color: #FFFFFF; + } + + &__text--info--plain { + color: $u-info; + } + + &__close { + position: absolute; + z-index: 999; + top: 10px; + right: 10px; + border-radius: 100px; + background-color: #C6C7CB; + @include flex(row); + align-items: center; + justify-content: center; + /* #ifndef APP-NVUE */ + transform: scale(0.6) translate(80%, -80%); + /* #endif */ + /* #ifdef APP-NVUE */ + transform: scale(0.6) translate(50%, -50%); + /* #endif */ + + &--mini { + width: 18px; + height: 18px; + } + + &--medium { + width: 22px; + height: 22px; + } + + &--large { + width: 25px; + height: 25px; + } + } + + } +</style> diff --git a/uni_modules/uview-ui/components/u-td/props.js b/uni_modules/uview-ui/components/u-td/props.js new file mode 100644 index 0000000..7c11331 --- /dev/null +++ b/uni_modules/uview-ui/components/u-td/props.js @@ -0,0 +1,5 @@ +export default { + props: { + + } +} diff --git a/uni_modules/uview-ui/components/u-td/u-td.vue b/uni_modules/uview-ui/components/u-td/u-td.vue new file mode 100644 index 0000000..600dce5 --- /dev/null +++ b/uni_modules/uview-ui/components/u-td/u-td.vue @@ -0,0 +1,31 @@ +<template> + <view class="u-td"> + + </view> +</template> + +<script> + import props from './props.js'; + /** + * Td ��������������������� + * @description + * @tutorial url + * @property {String | Number} + * @event {Function} + * @example + */ + export default { + name: 'u-td', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + +</style> diff --git a/uni_modules/uview-ui/components/u-text/props.js b/uni_modules/uview-ui/components/u-text/props.js new file mode 100644 index 0000000..d330075 --- /dev/null +++ b/uni_modules/uview-ui/components/u-text/props.js @@ -0,0 +1,110 @@ +export default { + props: { + // ������������ + type: { + type: String, + default: uni.$u.props.text.type + }, + // ������������ + show: { + type: Boolean, + default: uni.$u.props.text.show + }, + // ������������ + text: { + type: [String, Number], + default: uni.$u.props.text.text + }, + // ������������ + prefixIcon: { + type: String, + default: uni.$u.props.text.prefixIcon + }, + // ������������ + suffixIcon: { + type: String, + default: uni.$u.props.text.suffixIcon + }, + // ��������������������������� + // text-���������������price-���������phone-������������name-���������date-���������link-��������� + mode: { + type: String, + default: uni.$u.props.text.mode + }, + // mode=link��������������������� + href: { + type: String, + default: uni.$u.props.text.href + }, + // ��������������� + format: { + type: [String, Function], + default: uni.$u.props.text.format + }, + // mode=phone������������������������������������ + call: { + type: Boolean, + default: uni.$u.props.text.call + }, + // ������������������������ + openType: { + type: String, + default: uni.$u.props.text.openType + }, + // ���������������������normal + bold: { + type: Boolean, + default: uni.$u.props.text.bold + }, + // ������������ + block: { + type: Boolean, + default: uni.$u.props.text.block + }, + // ������������������������������������������������������������������������������ + lines: { + type: [String, Number], + default: uni.$u.props.text.lines + }, + // ������������ + color: { + type: String, + default: uni.$u.props.text.color + }, + // ������������ + size: { + type: [String, Number], + default: uni.$u.props.text.size + }, + // ��������������� + iconStyle: { + type: [Object, String], + default: uni.$u.props.text.iconStyle + }, + // ��������������������������������������������������� none|underline|line-through + decoration: { + type: String, + default: uni.$u.props.text.decoration + }, + // ��������������������������������������������������� + margin: { + type: [Object, String, Number], + default: uni.$u.props.text.margin + }, + // ������������ + lineHeight: { + type: [String, Number], + default: uni.$u.props.text.lineHeight + }, + // ������������������������������left|center|right + align: { + type: String, + default: uni.$u.props.text.align + }, + // ������������������������break-word|normal|anywhere + wordWrap: { + type: String, + default: uni.$u.props.text.wordWrap + } + } +} diff --git a/uni_modules/uview-ui/components/u-text/u-text.vue b/uni_modules/uview-ui/components/u-text/u-text.vue new file mode 100644 index 0000000..99d0809 --- /dev/null +++ b/uni_modules/uview-ui/components/u-text/u-text.vue @@ -0,0 +1,223 @@ +<template> + <view + class="u-text" + :class="[]" + v-if="show" + :style="{ + margin: margin, + justifyContent: align === 'left' ? 'flex-start' : align === 'center' ? 'center' : 'flex-end' + }" + @tap="clickHandler" + > + <text + :class="['u-text__price', type && `u-text__value--${type}`]" + v-if="mode === 'price'" + :style="[valueStyle]" + >���</text + > + <view class="u-text__prefix-icon" v-if="prefixIcon"> + <u-icon + :name="prefixIcon" + :customStyle="$u.addStyle(iconStyle)" + ></u-icon> + </view> + <u-link + v-if="mode === 'link'" + :text="value" + :href="href" + underLine + ></u-link> + <template v-else-if="openType && isMp"> + <button + class="u-reset-button u-text__value" + :style="[valueStyle]" + :data-index="index" + :openType="openType" + @getuserinfo="onGetUserInfo" + @contact="onContact" + @getphonenumber="onGetPhoneNumber" + @error="onError" + @launchapp="onLaunchApp" + @opensetting="onOpenSetting" + :lang="lang" + :session-from="sessionFrom" + :send-message-title="sendMessageTitle" + :send-message-path="sendMessagePath" + :send-message-img="sendMessageImg" + :show-message-card="showMessageCard" + :app-parameter="appParameter" + > + {{ value }} + </button> + </template> + <text + v-else + class="u-text__value" + :style="[valueStyle]" + :class="[ + type && `u-text__value--${type}`, + lines && `u-line-${lines}` + ]" + >{{ value }}</text + > + <view class="u-text__suffix-icon" v-if="suffixIcon"> + <u-icon + :name="suffixIcon" + :customStyle="$u.addStyle(iconStyle)" + ></u-icon> + </view> + </view> +</template> + +<script> +import value from './value.js' +import button from '../../libs/mixin/button.js' +import openType from '../../libs/mixin/openType.js' +import props from './props.js' +/** + * Text ������ + * @description ���������������������������������������������������������������������������������������������������������*������������������...������������ ������������������������������������������������������text��������������������������������������������������� + * @tutorial https://www.uviewui.com/components/loading.html + * @property {String} type ������������ + * @property {Boolean} show ��������������������� true ��� + * @property {String | Number} text ������������ + * @property {String} prefixIcon ������������ + * @property {String} suffixIcon ������������ + * @property {String} mode ��������������������������� text-���������������price-���������phone-������������name-���������date-���������link-��������� + * @property {String} href mode=link��������������������� + * @property {String | Function} format ��������������� + * @property {Boolean} call mode=phone��������������������������������������������� false ��� + * @property {String} openType ������������������������ + * @property {Boolean} bold ���������������������normal��������� false ��� + * @property {Boolean} block ��������������������� false ��� + * @property {String | Number} lines ������������������������������������������������������������������������������ + * @property {String} color ��������������������� '#303133' ��� + * @property {String | Number} size ��������������������� 15 ��� + * @property {Object | String} iconStyle ��������������� ��������� {fontSize: '15px'} ��� + * @property {String} decoration ��������������������������������������������������� none|underline|line-through��������� 'none' ��� + * @property {Object | String | Number} margin ������������������������������������������������������������ 0 ��� + * @property {String | Number} lineHeight ������������ + * @property {String} align ������������������������������left|center|right��������� 'left' ��� + * @property {String} wordWrap ������������������������break-word|normal|anywhere��������� 'normal' ��� + * @event {Function} click ������������������ + * @example <u--text text="������������������,������������������"></u--text> + */ +export default { + name: 'u--text', + // #ifdef MP + mixins: [uni.$u.mpMixin, uni.$u.mixin, value, button, openType, props], + // #endif + // #ifndef MP + mixins: [uni.$u.mpMixin, uni.$u.mixin, value, props], + // #endif + computed: { + valueStyle() { + const style = { + textDecoration: this.decoration, + fontWeight: this.bold ? 'bold' : 'normal', + wordWrap: this.wordWrap, + fontSize: uni.$u.addUnit(this.size) + } + !this.type && (style.color = this.color) + this.isNvue && this.lines && (style.lines = this.lines) + this.lineHeight && + (style.lineHeight = uni.$u.addUnit(this.lineHeight)) + !this.isNvue && this.block && (style.display = 'block') + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) + }, + isNvue() { + let nvue = false + // #ifdef APP-NVUE + nvue = true + // #endif + return nvue + }, + isMp() { + let mp = false + // #ifdef MP + mp = true + // #endif + return mp + } + }, + data() { + return {} + }, + methods: { + clickHandler() { + // ��������������������������������������� + if (this.call && this.mode === 'phone') { + uni.makePhoneCall({ + phoneNumber: this.text + }) + } + this.$emit('click') + } + } +} +</script> + +<style lang="scss" scoped> +@import '../../libs/css/components.scss'; + +.u-text { + @include flex(row); + align-items: center; + flex-wrap: nowrap; + flex: 1; + /* #ifndef APP-NVUE */ + width: 100%; + /* #endif */ + + &__price { + font-size: 14px; + color: $u-content-color; + } + + &__value { + font-size: 14px; + @include flex; + color: $u-content-color; + flex-wrap: wrap; + // flex: 1; + text-overflow: ellipsis; + align-items: center; + + &--primary { + color: $u-primary; + } + + &--warning { + color: $u-warning; + } + + &--success { + color: $u-success; + } + + &--info { + color: $u-info; + } + + &--error { + color: $u-error; + } + + &--main { + color: $u-main-color; + } + + &--content { + color: $u-content-color; + } + + &--tips { + color: $u-tips-color; + } + + &--light { + color: $u-light-color; + } + } +} +</style> diff --git a/uni_modules/uview-ui/components/u-text/value.js b/uni_modules/uview-ui/components/u-text/value.js new file mode 100644 index 0000000..9859bbb --- /dev/null +++ b/uni_modules/uview-ui/components/u-text/value.js @@ -0,0 +1,85 @@ +export default { + computed: { + // ������������������������������ + value() { + const { + text, + mode, + format, + href + } = this + // ������������ + if (mode === 'price') { + // ������text������������������������ + if (!/^\d+(\.\d+)?$/.test(text)) { + uni.$u.error('������������������text���������������������������'); + } + // ���������������������������������������format���������������������������������������������������format������������������������������������������ + if (uni.$u.test.func(format)) { + // ������������������������������������������������������ + return format(text) + } + // ������format��������������������������������������������������������������������������� + return uni.$u.priceFormat(text, 2) + } if (mode === 'date') { + // ������������������������������������������ + !uni.$u.test.date(text) && uni.$u.error('������������������text���������������������������������������') + // ���������������������������������������format���������������������������������������������������format������������������������������������ + if (uni.$u.test.func(format)) { + // ������������������������������������������������������ + return format(text) + } if (format) { + // ������format��������������������������������������������������������������������������� + return uni.$u.timeFormat(text, format) + } + // ������������������format��������������������������������������������� + return uni.$u.timeFormat(text, 'yyyy-mm-dd') + } if (mode === 'phone') { + // ������������������������������ + // !uni.$u.test.mobile(text) && uni.$u.error('���������������������text���������������������������������') + if (uni.$u.test.func(format)) { + // ������������������������������������������������������ + return format(text) + } if (format === 'encrypt') { + // ������format���encrypt������������������������������������������ + return `${text.substr(0, 3)}****${text.substr(7)}` + } + return text + } if (mode === 'name') { + // ������������������������������ + !(typeof (text) === 'string') && uni.$u.error('������������������text������������������������������') + if (uni.$u.test.func(format)) { + // ������������������������������������������������������ + return format(text) + } if (format === 'encrypt') { + // ������format���encrypt��������������������������������������� + return this.formatName(text) + } + return text + } if (mode === 'link') { + // ������������������������������ + !uni.$u.test.url(href) && uni.$u.error('���������������������href���������������URL������') + return text + } + return text + } + }, + methods: { + // ��������������������������� + formatName(name) { + let value = '' + if (name.length === 2) { + value = name.substr(0, 1) + '*' + } else if (name.length > 2) { + let char = '' + for (let i = 0, len = name.length - 2; i < len; i++) { + char += '*' + } + value = name.substr(0, 1) + char + name.substr(-1, 1) + } else { + value = name + } + return value + } + } +} diff --git a/uni_modules/uview-ui/components/u-textarea/props.js b/uni_modules/uview-ui/components/u-textarea/props.js new file mode 100644 index 0000000..d0e16d5 --- /dev/null +++ b/uni_modules/uview-ui/components/u-textarea/props.js @@ -0,0 +1,119 @@ +export default { + props: { + // ������������������ + value: { + type: [String, Number], + default: uni.$u.props.textarea.value + }, + // ��������������������������� + placeholder: { + type: [String, Number], + default: uni.$u.props.textarea.placeholder + }, + // ������placeholder���������������������������������������style���������scoped���������������������������/deep/ + placeholderClass: { + type: String, + default: uni.$u.props.input.placeholderClass + }, + // ������placeholder��������� + placeholderStyle: { + type: [String, Object], + default: uni.$u.props.input.placeholderStyle + }, + // ��������������� + height: { + type: [String, Number], + default: uni.$u.props.textarea.height + }, + // ������������������������������������������������������������App-vue���H5������ + confirmType: { + type: String, + default: uni.$u.props.textarea.confirmType + }, + // ������������ + disabled: { + type: Boolean, + default: uni.$u.props.textarea.disabled + }, + // ������������������������ + count: { + type: Boolean, + default: uni.$u.props.textarea.count + }, + // ���������������������������nvue������������H5��������������������������� + focus: { + type: Boolean, + default: uni.$u.props.textarea.focus + }, + // ������������������������ + autoHeight: { + type: Boolean, + default: uni.$u.props.textarea.autoHeight + }, + // ������textarea������������position:fixed������������������������������������fixed���true + fixed: { + type: Boolean, + default: uni.$u.props.textarea.fixed + }, + // ������������������������������ + cursorSpacing: { + type: Number, + default: uni.$u.props.textarea.cursorSpacing + }, + // ������focus������������������ + cursor: { + type: [String, Number], + default: uni.$u.props.textarea.cursor + }, + // ������������������������������������������������������������ + showConfirmBar: { + type: Boolean, + default: uni.$u.props.textarea.showConfirmBar + }, + // ���������������������������������������������������selection-end������������ + selectionStart: { + type: Number, + default: uni.$u.props.textarea.selectionStart + }, + // ���������������������������������������������������selection-start������������ + selectionEnd: { + type: Number, + default: uni.$u.props.textarea.selectionEnd + }, + // ������������������������������������������ + adjustPosition: { + type: Boolean, + default: uni.$u.props.textarea.adjustPosition + }, + // ������������ iOS ������������������������������������������������ + disableDefaultPadding: { + type: Boolean, + default: uni.$u.props.textarea.disableDefaultPadding + }, + // focus��������������������������������������������������������������������� + holdKeyboard: { + type: Boolean, + default: uni.$u.props.textarea.holdKeyboard + }, + // ������������������������������ -1 ������������������������������ + maxlength: { + type: [String, Number], + default: uni.$u.props.textarea.maxlength + }, + // ���������������surround-���������������bottom-������������ + border: { + type: String, + default: uni.$u.props.textarea.border + }, + // ������������������������������������������������ + formatter: { + type: [Function, null], + default: uni.$u.props.textarea.formatter + }, + // ��������������������������������������������������������� + ignoreCompositionEvent: { + type: Boolean, + default: true + } + } +} diff --git a/uni_modules/uview-ui/components/u-textarea/u-textarea.vue b/uni_modules/uview-ui/components/u-textarea/u-textarea.vue new file mode 100644 index 0000000..2cd5fdc --- /dev/null +++ b/uni_modules/uview-ui/components/u-textarea/u-textarea.vue @@ -0,0 +1,239 @@ +<template> + <view class="u-textarea" :class="textareaClass" :style="[textareaStyle]"> + <textarea + class="u-textarea__field" + :value="innerValue" + :style="{ height: $u.addUnit(height) }" + :placeholder="placeholder" + :placeholder-style="$u.addStyle(placeholderStyle, 'string')" + :placeholder-class="placeholderClass" + :disabled="disabled" + :focus="focus" + :autoHeight="autoHeight" + :fixed="fixed" + :cursorSpacing="cursorSpacing" + :cursor="cursor" + :showConfirmBar="showConfirmBar" + :selectionStart="selectionStart" + :selectionEnd="selectionEnd" + :adjustPosition="adjustPosition" + :disableDefaultPadding="disableDefaultPadding" + :holdKeyboard="holdKeyboard" + :maxlength="maxlength" + :confirmType="confirmType" + :ignoreCompositionEvent="ignoreCompositionEvent" + @focus="onFocus" + @blur="onBlur" + @linechange="onLinechange" + @input="onInput" + @confirm="onConfirm" + @keyboardheightchange="onKeyboardheightchange" + ></textarea> + <text + class="u-textarea__count" + :style="{ + 'background-color': disabled ? 'transparent' : '#fff', + }" + v-if="count" + >{{ innerValue.length }}/{{ maxlength }}</text + > + </view> +</template> + +<script> +import props from "./props.js"; +/** + * Textarea ��������� + * @description ������������������������������������������������������������������������������������������������������������������������ + * @tutorial https://www.uviewui.com/components/textarea.html + * + * @property {String | Number} value ������������������ + * @property {String | Number} placeholder ��������������������������� + * @property {String} placeholderClass ������placeholder���������������������������������������style���������scoped���������������������������/deep/ ��� ������ 'input-placeholder' ��� + * @property {String | Object} placeholderStyle ������placeholder���������������������/������������������"color: red;" + * @property {String | Number} height ������������������������ 70 ��� + * @property {String} confirmType ������������������������������������������������������������App-vue���H5��������������� 'done' ��� + * @property {Boolean} disabled ��������������������� false ��� + * @property {Boolean} count ��������������������������������� false ��� + * @property {Boolean} focus ���������������������������nvue������������H5������������������������������������ false ��� + * @property {Boolean | Function} autoHeight ��������������������������������� false ��� + * @property {Boolean} fixed ������textarea������������position:fixed������������������������������������fixed���true��������� false ��� + * @property {Number} cursorSpacing ��������������������������������������� 0 ��� + * @property {String | Number} cursor ������focus������������������ + * @property {Function} formatter ������������������ + * @property {Boolean} showConfirmBar ��������������������������������������������������������������������� true ��� + * @property {Number} selectionStart ���������������������������������������������������selection-end������������������������ -1 ��� + * @property {Number | Number} selectionEnd ���������������������������������������������������selection-start��������������������� -1 ��� + * @property {Boolean} adjustPosition ��������������������������������������������������� true ��� + * @property {Boolean | Number} disableDefaultPadding ������������ iOS ��������������������������������������������������������� false ��� + * @property {Boolean} holdKeyboard focus������������������������������������������������������������������������������ false ��� + * @property {String | Number} maxlength ������������������������������ -1 ��������������������������������������� 140 ��� + * @property {String} border ���������������surround-���������������none-������������bottom-��������������������� 'surround' ��� + * @property {Boolean} ignoreCompositionEvent ��������������������������������������������������������� + * + * @event {Function(e)} focus ���������������������������event.detail = { value, height }���height ��������������� + * @event {Function(e)} blur ���������������������������������event.detail = {value, cursor} + * @event {Function(e)} linechange ���������������������������������event.detail = {height: 0, heightRpx: 0, lineCount: 0} + * @event {Function(e)} input ��������������������������� input ������ + * @event {Function(e)} confirm ������������������ ������ confirm ������ + * @event {Function(e)} keyboardheightchange ������������������������������������������������ + * @example <u--textarea v-model="value1" placeholder="���������������" ></u--textarea> + */ +export default { + name: "u-textarea", + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + // ��������������� + innerValue: "", + // ������������������������������ + focused: false, + // value���������������������������watch������������������immediate������������������������������������������������������value��������������� + firstChange: true, + // value��������������������������������������������������� + changeFromInner: false, + // ������������������ + innerFormatter: value => value + } + }, + watch: { + value: { + immediate: true, + handler(newVal, oldVal) { + this.innerValue = newVal; + /* #ifdef H5 */ + // ���H5������������value������������������input������������������������@input������������������������������������������ + if ( + this.firstChange === false && + this.changeFromInner === false + ) { + this.valueChange(); + } + /* #endif */ + this.firstChange = false; + // ������changeFromInner���������false������������������������������������������������ + this.changeFromInner = false; + }, + }, + }, + computed: { + // ��������������� + textareaClass() { + let classes = [], + { border, disabled, shape } = this; + border === "surround" && + (classes = classes.concat(["u-border", "u-textarea--radius"])); + border === "bottom" && + (classes = classes.concat([ + "u-border-bottom", + "u-textarea--no-radius", + ])); + disabled && classes.push("u-textarea--disabled"); + return classes.join(" "); + }, + // ��������������� + textareaStyle() { + const style = {}; + // #ifdef APP-NVUE + // ������textarea���������nvue��������������������������������������������������� + if (uni.$u.os() === "android") { + style.paddingTop = "6px"; + style.paddingLeft = "9px"; + style.paddingBottom = "3px"; + style.paddingRight = "6px"; + } + // #endif + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)); + }, + }, + methods: { + // ������������������������������������������������props������������������������ref������������ + setFormatter(e) { + this.innerFormatter = e + }, + onFocus(e) { + this.$emit("focus", e); + }, + onBlur(e) { + this.$emit("blur", e); + // ������������u-form��������������� + uni.$u.formValidate(this, "blur"); + }, + onLinechange(e) { + this.$emit("linechange", e); + }, + onInput(e) { + let { value = "" } = e.detail || {}; + // ��������������������� + const formatter = this.formatter || this.innerFormatter + const formatValue = formatter(value) + // ������������props���������������������������������������innerValue������������������������������$nextTick��������������������������������������� + this.innerValue = value + this.$nextTick(() => { + this.innerValue = formatValue; + this.valueChange(); + }) + }, + // ��������������������������������� + valueChange() { + const value = this.innerValue; + this.$nextTick(() => { + this.$emit("input", value); + // ������value��������������������������������� + this.changeFromInner = true; + this.$emit("change", value); + // ������������u-form��������������� + uni.$u.formValidate(this, "change"); + }); + }, + onConfirm(e) { + this.$emit("confirm", e); + }, + onKeyboardheightchange(e) { + this.$emit("keyboardheightchange", e); + }, + }, +}; +</script> + +<style lang="scss" scoped> +@import "../../libs/css/components.scss"; + +.u-textarea { + border-radius: 4px; + background-color: #fff; + position: relative; + @include flex; + flex: 1; + padding: 9px; + + &--radius { + border-radius: 4px; + } + + &--no-radius { + border-radius: 0; + } + + &--disabled { + background-color: #f5f7fa; + } + + &__field { + flex: 1; + font-size: 15px; + color: $u-content-color; + width: 100%; + } + + &__count { + position: absolute; + right: 5px; + bottom: 2px; + font-size: 12px; + color: $u-tips-color; + background-color: #ffffff; + padding: 1px 4px; + } +} +</style> diff --git a/uni_modules/uview-ui/components/u-toast/u-toast.vue b/uni_modules/uview-ui/components/u-toast/u-toast.vue new file mode 100644 index 0000000..f194830 --- /dev/null +++ b/uni_modules/uview-ui/components/u-toast/u-toast.vue @@ -0,0 +1,291 @@ +<template> + <view class="u-toast"> + <u-overlay + :show="isShow" + :custom-style="overlayStyle" + > + <view + class="u-toast__content" + :style="[contentStyle]" + :class="['u-type-' + tmpConfig.type, (tmpConfig.type === 'loading' || tmpConfig.loading) ? 'u-toast__content--loading' : '']" + > + <u-loading-icon + v-if="tmpConfig.type === 'loading'" + mode="circle" + color="rgb(255, 255, 255)" + inactiveColor="rgb(120, 120, 120)" + size="25" + ></u-loading-icon> + <u-icon + v-else-if="tmpConfig.type !== 'defalut' && iconName" + :name="iconName" + size="17" + :color="tmpConfig.type" + :customStyle="iconStyle" + ></u-icon> + <u-gap + v-if="tmpConfig.type === 'loading' || tmpConfig.loading" + height="12" + bgColor="transparent" + ></u-gap> + <text + class="u-toast__content__text" + :class="['u-toast__content__text--' + tmpConfig.type]" + style="max-width: 400rpx;" + >{{ tmpConfig.message }}</text> + </view> + </u-overlay> + </view> +</template> + +<script> + /** + * toast ������������ + * @description ���������������������������uni���uni.showToastAPI������������������������������ + * @tutorial https://www.uviewui.com/components/toast.html + * @property {String | Number} zIndex toast������������zIndex��� (������ 10090 ) + * @property {Boolean} loading ��������������� ��������� false ��� + * @property {String | Number} message ��������������������� + * @property {String} icon ������������������������������������ + * @property {String} type ������������ ��������� default��� + * @property {Boolean} show ��������������������� ��������� false��� + * @property {Boolean} overlay ��������������������������������������������� ��������� false ��� + * @property {String} position ������ ��������� 'center' ��� + * @property {Object} params ��������������� + * @property {String | Number} duration ���������������������ms ��������� 2000 ��� + * @property {Boolean} isTab ������������������tab������ ��������� false ��� + * @property {String} url toast������������������������������������������������������������back������ + * @property {Function} complete ��������������������������� + * @property {Boolean} back ������toast��������������������������� ��������� false ��� + * @property {Object} customStyle ������������������������������ + * @event {Function} show ������toast���������������������������������toast���������onReady������������������ + * @example <u-toast ref="uToast" /> + */ + export default { + name: 'u-toast', + mixins: [uni.$u.mpMixin, uni.$u.mixin], + data() { + return { + isShow: false, + timer: null, // ��������� + config: { + message: '', // ������������ + type: '', // ���������������primary���success���error���warning���black + duration: 2000, // ������������������������ + icon: true, // ��������������� + position: 'center', // toast��������������� + complete: null, // ��������������������������� + overlay: false, // ������������������������ + loading: false, // ��������������������� + }, + tmpConfig: {}, // ������������������������������������������������������������ + } + }, + computed: { + iconName() { + // ������������none���������type���error|warning|succes|info������������������������ + if(!this.tmpConfig.icon || this.tmpConfig.icon == 'none') { + return ''; + } + if (['error', 'warning', 'success', 'primary'].includes(this.tmpConfig.type)) { + return uni.$u.type2icon(this.tmpConfig.type) + } else { + return '' + } + }, + overlayStyle() { + const style = { + justifyContent: 'center', + alignItems: 'center', + display: 'flex' + } + // ������������������100%������������������������������������ + style.backgroundColor = 'rgba(0, 0, 0, 0)' + return style + }, + iconStyle() { + const style = {} + // ��������������������������������������������������������������������� + style.marginRight = '4px' + // #ifdef APP-NVUE + // iOSAPP���������������1px������������������������������������ + if (uni.$u.os() === 'ios') { + style.marginTop = '-1px' + } + // #endif + return style + }, + loadingIconColor() { + let color = 'rgb(255, 255, 255)' + if (['error', 'warning', 'success', 'primary'].includes(this.tmpConfig.type)) { + // loading-icon������������������color��������������������������������������������������������������������� + // ���������rgb��������������������������������������� + color = uni.$u.hexToRgb(uni.$u.color[this.tmpConfig.type]) + } + return color + }, + // ��������������������� + contentStyle() { + const windowHeight = uni.$u.sys().windowHeight, style = {} + let value = 0 + // ������top���bottom������Y��������������������������������������� + if(this.tmpConfig.position === 'top') { + value = - windowHeight * 0.25 + } else if(this.tmpConfig.position === 'bottom') { + value = windowHeight * 0.25 + } + style.transform = `translateY(${value}px)` + return style + } + }, + created() { + // ���������������������������toast��������������������������� + ['primary', 'success', 'error', 'warning', 'default', 'loading'].map(item => { + this[item] = message => this.show({ + type: item, + message + }) + }) + }, + methods: { + // ������toast���������������������������this.$refs.xxx.show(options)������������ + show(options) { + // ���������������������this.config���������������������������u-toast������������������������������ + this.tmpConfig = uni.$u.deepMerge(this.config, options) + // ��������������� + this.clearTimer() + this.isShow = true + this.timer = setTimeout(() => { + // ������������������������������������������toast������ + this.clearTimer() + // ������������������callback������������������������������ + typeof(this.tmpConfig.complete) === 'function' && this.tmpConfig.complete() + }, this.tmpConfig.duration) + }, + // ������toast���������������������������this.$refs.xxx.hide()������������ + hide() { + this.clearTimer() + }, + clearTimer() { + this.isShow = false + // ��������������� + clearTimeout(this.timer) + this.timer = null + } + }, + beforeDestroy() { + this.clearTimer() + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + $u-toast-color:#fff !default; + $u-toast-border-radius:4px !default; + $u-toast-border-background-color:#585858 !default; + $u-toast-border-font-size:14px !default; + $u-toast-border-padding:12px 20px !default; + $u-toast-loading-border-padding: 20px 20px !default; + $u-toast-content-text-color:#fff !default; + $u-toast-content-text-font-size:15px !default; + $u-toast-u-icon:10rpx !default; + $u-toast-u-type-primary-color:$u-primary !default; + $u-toast-u-type-primary-background-color:#ecf5ff !default; + $u-toast-u-type-primary-border-color:rgb(215, 234, 254) !default; + $u-toast-u-type-primary-border-width:1px !default; + $u-toast-u-type-success-color: $u-success !default; + $u-toast-u-type-success-background-color: #dbf1e1 !default; + $u-toast-u-type-success-border-color: #BEF5C8 !default; + $u-toast-u-type-success-border-width: 1px !default; + $u-toast-u-type-error-color:$u-error !default; + $u-toast-u-type-error-background-color:#fef0f0 !default; + $u-toast-u-type-error-border-color:#fde2e2 !default; + $u-toast-u-type-error-border-width: 1px !default; + $u-toast-u-type-warning-color:$u-warning !default; + $u-toast-u-type-warning-background-color:#fdf6ec !default; + $u-toast-u-type-warning-border-color:#faecd8 !default; + $u-toast-u-type-warning-border-width: 1px !default; + $u-toast-u-type-default-color:#fff !default; + $u-toast-u-type-default-background-color:#585858 !default; + + .u-toast { + &__content { + @include flex; + padding: $u-toast-border-padding; + border-radius: $u-toast-border-radius; + background-color: $u-toast-border-background-color; + color: $u-toast-color; + align-items: center; + /* #ifndef APP-NVUE */ + max-width: 600rpx; + /* #endif */ + position: relative; + + &--loading { + flex-direction: column; + padding: $u-toast-loading-border-padding; + } + + &__text { + color: $u-toast-content-text-color; + font-size: $u-toast-content-text-font-size; + line-height: $u-toast-content-text-font-size; + + &--default { + color: $u-toast-content-text-color; + } + + &--error { + color: $u-error; + } + + &--primary { + color: $u-primary; + } + + &--success { + color: $u-success; + } + + &--warning { + color: $u-warning; + } + } + } + } + + .u-type-primary { + color: $u-toast-u-type-primary-color; + background-color: $u-toast-u-type-primary-background-color; + border-color: $u-toast-u-type-primary-border-color; + border-width: $u-toast-u-type-primary-border-width; + } + + .u-type-success { + color: $u-toast-u-type-success-color; + background-color: $u-toast-u-type-success-background-color; + border-color: $u-toast-u-type-success-border-color; + border-width: 1px; + } + + .u-type-error { + color: $u-toast-u-type-error-color; + background-color: $u-toast-u-type-error-background-color; + border-color: $u-toast-u-type-error-border-color; + border-width: $u-toast-u-type-error-border-width; + } + + .u-type-warning { + color: $u-toast-u-type-warning-color; + background-color: $u-toast-u-type-warning-background-color; + border-color: $u-toast-u-type-warning-border-color; + border-width: 1px; + } + + .u-type-default { + color: $u-toast-u-type-default-color; + background-color: $u-toast-u-type-default-background-color; + } +</style> diff --git a/uni_modules/uview-ui/components/u-toolbar/props.js b/uni_modules/uview-ui/components/u-toolbar/props.js new file mode 100644 index 0000000..1b72966 --- /dev/null +++ b/uni_modules/uview-ui/components/u-toolbar/props.js @@ -0,0 +1,34 @@ +export default { + props: { + // ��������������������� + show: { + type: Boolean, + default: uni.$u.props.toolbar.show + }, + // ��������������������� + cancelText: { + type: String, + default: uni.$u.props.toolbar.cancelText + }, + // ��������������������� + confirmText: { + type: String, + default: uni.$u.props.toolbar.confirmText + }, + // ��������������������� + cancelColor: { + type: String, + default: uni.$u.props.toolbar.cancelColor + }, + // ��������������������� + confirmColor: { + type: String, + default: uni.$u.props.toolbar.confirmColor + }, + // ������������ + title: { + type: String, + default: uni.$u.props.toolbar.title + } + } +} diff --git a/uni_modules/uview-ui/components/u-toolbar/u-toolbar.vue b/uni_modules/uview-ui/components/u-toolbar/u-toolbar.vue new file mode 100644 index 0000000..290b771 --- /dev/null +++ b/uni_modules/uview-ui/components/u-toolbar/u-toolbar.vue @@ -0,0 +1,102 @@ +<template> + <view + class="u-toolbar" + @touchmove.stop.prevent="noop" + v-if="show" + > + <view + class="u-toolbar__cancel__wrapper" + hover-class="u-hover-class" + > + <text + class="u-toolbar__wrapper__cancel" + @tap="cancel" + :style="{ + color: cancelColor + }" + >{{ cancelText }}</text> + </view> + <text + class="u-toolbar__title u-line-1" + v-if="title" + >{{ title }}</text> + <view + class="u-toolbar__confirm__wrapper" + hover-class="u-hover-class" + > + <text + class="u-toolbar__wrapper__confirm" + @tap="confirm" + :style="{ + color: confirmColor + }" + >{{ confirmText }}</text> + </view> + </view> +</template> + +<script> + import props from './props.js'; + /** + * Toolbar ��������� + * @description + * @tutorial https://www.uviewui.com/components/toolbar.html + * @property {Boolean} show ������������������������������ true ��� + * @property {String} cancelText ������������������������������ '������' ��� + * @property {String} confirmText ������������������������������ '������' ��� + * @property {String} cancelColor ������������������������������ '#909193' ��� + * @property {String} confirmColor ������������������������������ '#3c9cff' ��� + * @property {String} title ������������ + * @event {Function} + * @example + */ + export default { + name: 'u-toolbar', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + methods: { + // ������������������ + cancel() { + this.$emit('cancel') + }, + // ������������������ + confirm() { + this.$emit('confirm') + } + }, + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-toolbar { + height: 42px; + @include flex; + justify-content: space-between; + align-items: center; + + &__wrapper { + &__cancel { + color: $u-tips-color; + font-size: 15px; + padding: 0 15px; + } + } + + &__title { + color: $u-main-color; + padding: 0 60rpx; + font-size: 16px; + flex: 1; + text-align: center; + } + + &__wrapper { + &__confirm { + color: $u-primary; + font-size: 15px; + padding: 0 15px; + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-tooltip/clipboard.min.js b/uni_modules/uview-ui/components/u-tooltip/clipboard.min.js new file mode 100644 index 0000000..b7bff12 --- /dev/null +++ b/uni_modules/uview-ui/components/u-tooltip/clipboard.min.js @@ -0,0 +1,58 @@ +/*! + * clipboard.js v1.6.1 + * https://zenorocha.github.io/clipboard.js + * + * Licensed MIT �� Zeno Rocha + */ +!(function (e) { if (typeof exports === 'object' && typeof module !== 'undefined')module.exports = e(); else if (typeof define === 'function' && define.amd)define([], e); else { let t; t = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this, t.Clipboard = e() } }(() => { + let e; let t; let n; return (function e(t, n, o) { function i(a, c) { if (!n[a]) { if (!t[a]) { const l = typeof require === 'function' && require; if (!c && l) return l(a, !0); if (r) return r(a, !0); const u = new Error(`Cannot find module '${a}'`); throw u.code = 'MODULE_NOT_FOUND', u } const s = n[a] = { exports: {} }; t[a][0].call(s.exports, (e) => { const n = t[a][1][e]; return i(n || e) }, s, s.exports, e, t, n, o) } return n[a].exports } for (var r = typeof require === 'function' && require, a = 0; a < o.length; a++)i(o[a]); return i }({ + 1: [function (e, t, n) { function o(e, t) { for (;e && e.nodeType !== i;) { if (e.matches(t)) return e; e = e.parentNode } } var i = 9; if (typeof Element !== 'undefined' && !Element.prototype.matches) { const r = Element.prototype; r.matches = r.matchesSelector || r.mozMatchesSelector || r.msMatchesSelector || r.oMatchesSelector || r.webkitMatchesSelector }t.exports = o }, {}], + 2: [function (e, t, n) { function o(e, t, n, o, r) { const a = i.apply(this, arguments); return e.addEventListener(n, a, r), { destroy() { e.removeEventListener(n, a, r) } } } function i(e, t, n, o) { return function (n) { n.delegateTarget = r(n.target, t), n.delegateTarget && o.call(e, n) } } var r = e('./closest'); t.exports = o }, { './closest': 1 }], + 3: [function (e, t, n) { n.node = function (e) { return void 0 !== e && e instanceof HTMLElement && e.nodeType === 1 }, n.nodeList = function (e) { const t = Object.prototype.toString.call(e); return void 0 !== e && (t === '[object NodeList]' || t === '[object HTMLCollection]') && 'length' in e && (e.length === 0 || n.node(e[0])) }, n.string = function (e) { return typeof e === 'string' || e instanceof String }, n.fn = function (e) { const t = Object.prototype.toString.call(e); return t === '[object Function]' } }, {}], + 4: [function (e, t, n) { function o(e, t, n) { if (!e && !t && !n) throw new Error('Missing required arguments'); if (!c.string(t)) throw new TypeError('Second argument must be a String'); if (!c.fn(n)) throw new TypeError('Third argument must be a Function'); if (c.node(e)) return i(e, t, n); if (c.nodeList(e)) return r(e, t, n); if (c.string(e)) return a(e, t, n); throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList') } function i(e, t, n) { return e.addEventListener(t, n), { destroy() { e.removeEventListener(t, n) } } } function r(e, t, n) { return Array.prototype.forEach.call(e, (e) => { e.addEventListener(t, n) }), { destroy() { Array.prototype.forEach.call(e, (e) => { e.removeEventListener(t, n) }) } } } function a(e, t, n) { return l(document.body, e, t, n) } var c = e('./is'); var l = e('delegate'); t.exports = o }, { './is': 3, delegate: 2 }], + 5: [function (e, t, n) { function o(e) { let t; if (e.nodeName === 'SELECT')e.focus(), t = e.value; else if (e.nodeName === 'INPUT' || e.nodeName === 'TEXTAREA') { const n = e.hasAttribute('readonly'); n || e.setAttribute('readonly', ''), e.select(), e.setSelectionRange(0, e.value.length), n || e.removeAttribute('readonly'), t = e.value } else { e.hasAttribute('contenteditable') && e.focus(); const o = window.getSelection(); const i = document.createRange(); i.selectNodeContents(e), o.removeAllRanges(), o.addRange(i), t = o.toString() } return t }t.exports = o }, {}], + 6: [function (e, t, n) { + function o() {}o.prototype = { + on(e, t, n) { const o = this.e || (this.e = {}); return (o[e] || (o[e] = [])).push({ fn: t, ctx: n }), this }, once(e, t, n) { function o() { i.off(e, o), t.apply(n, arguments) } var i = this; return o._ = t, this.on(e, o, n) }, emit(e) { const t = [].slice.call(arguments, 1); const n = ((this.e || (this.e = {}))[e] || []).slice(); let o = 0; const i = n.length; for (o; o < i; o++)n[o].fn.apply(n[o].ctx, t); return this }, off(e, t) { const n = this.e || (this.e = {}); const o = n[e]; const i = []; if (o && t) for (let r = 0, a = o.length; r < a; r++)o[r].fn !== t && o[r].fn._ !== t && i.push(o[r]); return i.length ? n[e] = i : delete n[e], this } + }, t.exports = o + }, {}], + 7: [function (t, n, o) { + !(function (i, r) { if (typeof e === 'function' && e.amd)e(['module', 'select'], r); else if (typeof o !== 'undefined')r(n, t('select')); else { const a = { exports: {} }; r(a, i.select), i.clipboardAction = a.exports } }(this, (e, t) => { + 'use strict' + + function n(e) { return e && e.__esModule ? e : { default: e } } function o(e, t) { if (!(e instanceof t)) throw new TypeError('Cannot call a class as a function') } const i = n(t); const r = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? function (e) { return typeof e } : function (e) { return e && typeof Symbol === 'function' && e.constructor === Symbol && e !== Symbol.prototype ? 'symbol' : typeof e }; const a = (function () { function e(e, t) { for (let n = 0; n < t.length; n++) { const o = t[n]; o.enumerable = o.enumerable || !1, o.configurable = !0, 'value' in o && (o.writable = !0), Object.defineProperty(e, o.key, o) } } return function (t, n, o) { return n && e(t.prototype, n), o && e(t, o), t } }()); const c = (function () { + function e(t) { o(this, e), this.resolveOptions(t), this.initSelection() } return a(e, [{ key: 'resolveOptions', value: function e() { const t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}; this.action = t.action, this.emitter = t.emitter, this.target = t.target, this.text = t.text, this.trigger = t.trigger, this.selectedText = '' } }, { key: 'initSelection', value: function e() { this.text ? this.selectFake() : this.target && this.selectTarget() } }, { key: 'selectFake', value: function e() { const t = this; const n = document.documentElement.getAttribute('dir') == 'rtl'; this.removeFake(), this.fakeHandlerCallback = function () { return t.removeFake() }, this.fakeHandler = document.body.addEventListener('click', this.fakeHandlerCallback) || !0, this.fakeElem = document.createElement('textarea'), this.fakeElem.style.fontSize = '12pt', this.fakeElem.style.border = '0', this.fakeElem.style.padding = '0', this.fakeElem.style.margin = '0', this.fakeElem.style.position = 'absolute', this.fakeElem.style[n ? 'right' : 'left'] = '-9999px'; const o = window.pageYOffset || document.documentElement.scrollTop; this.fakeElem.style.top = `${o}px`, this.fakeElem.setAttribute('readonly', ''), this.fakeElem.value = this.text, document.body.appendChild(this.fakeElem), this.selectedText = (0, i.default)(this.fakeElem), this.copyText() } }, { key: 'removeFake', value: function e() { this.fakeHandler && (document.body.removeEventListener('click', this.fakeHandlerCallback), this.fakeHandler = null, this.fakeHandlerCallback = null), this.fakeElem && (document.body.removeChild(this.fakeElem), this.fakeElem = null) } }, { key: 'selectTarget', value: function e() { this.selectedText = (0, i.default)(this.target), this.copyText() } }, { key: 'copyText', value: function e() { let t = void 0; try { t = document.execCommand(this.action) } catch (e) { t = !1 } this.handleResult(t) } }, { + key: 'handleResult', + value: function e(t) { + this.emitter.emit(t ? 'success' : 'error', { + action: this.action, text: this.selectedText, trigger: this.trigger, clearSelection: this.clearSelection.bind(this) + }) + } + }, { key: 'clearSelection', value: function e() { this.target && this.target.blur(), window.getSelection().removeAllRanges() } }, { key: 'destroy', value: function e() { this.removeFake() } }, { key: 'action', set: function e() { const t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : 'copy'; if (this._action = t, this._action !== 'copy' && this._action !== 'cut') throw new Error('Invalid "action" value, use either "copy" or "cut"') }, get: function e() { return this._action } }, { key: 'target', set: function e(t) { if (void 0 !== t) { if (!t || (typeof t === 'undefined' ? 'undefined' : r(t)) !== 'object' || t.nodeType !== 1) throw new Error('Invalid "target" value, use a valid Element'); if (this.action === 'copy' && t.hasAttribute('disabled')) throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute'); if (this.action === 'cut' && (t.hasAttribute('readonly') || t.hasAttribute('disabled'))) throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes'); this._target = t } }, get: function e() { return this._target } }]), e + }()); e.exports = c + })) + }, { select: 5 }], + 8: [function (t, n, o) { + !(function (i, r) { if (typeof e === 'function' && e.amd)e(['module', './clipboard-action', 'tiny-emitter', 'good-listener'], r); else if (typeof o !== 'undefined')r(n, t('./clipboard-action'), t('tiny-emitter'), t('good-listener')); else { const a = { exports: {} }; r(a, i.clipboardAction, i.tinyEmitter, i.goodListener), i.clipboard = a.exports } }(this, (e, t, n, o) => { + 'use strict' + + function i(e) { return e && e.__esModule ? e : { default: e } } function r(e, t) { if (!(e instanceof t)) throw new TypeError('Cannot call a class as a function') } function a(e, t) { if (!e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return !t || typeof t !== 'object' && typeof t !== 'function' ? e : t } function c(e, t) { + if (typeof t !== 'function' && t !== null) throw new TypeError(`Super expression must either be null or a function, not ${typeof t}`); e.prototype = Object.create(t && t.prototype, { + constructor: { + value: e, enumerable: !1, writable: !0, configurable: !0 + } + }), t && (Object.setPrototypeOf ? Object.setPrototypeOf(e, t) : e.__proto__ = t) + } function l(e, t) { const n = `data-clipboard-${e}`; if (t.hasAttribute(n)) return t.getAttribute(n) } const u = i(t); const s = i(n); const f = i(o); const d = (function () { function e(e, t) { for (let n = 0; n < t.length; n++) { const o = t[n]; o.enumerable = o.enumerable || !1, o.configurable = !0, 'value' in o && (o.writable = !0), Object.defineProperty(e, o.key, o) } } return function (t, n, o) { return n && e(t.prototype, n), o && e(t, o), t } }()); const h = (function (e) { + function t(e, n) { r(this, t); const o = a(this, (t.__proto__ || Object.getPrototypeOf(t)).call(this)); return o.resolveOptions(n), o.listenClick(e), o } return c(t, e), d(t, [{ key: 'resolveOptions', value: function e() { const t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}; this.action = typeof t.action === 'function' ? t.action : this.defaultAction, this.target = typeof t.target === 'function' ? t.target : this.defaultTarget, this.text = typeof t.text === 'function' ? t.text : this.defaultText } }, { key: 'listenClick', value: function e(t) { const n = this; this.listener = (0, f.default)(t, 'click', (e) => n.onClick(e)) } }, { + key: 'onClick', + value: function e(t) { + const n = t.delegateTarget || t.currentTarget; this.clipboardAction && (this.clipboardAction = null), this.clipboardAction = new u.default({ + action: this.action(n), target: this.target(n), text: this.text(n), trigger: n, emitter: this + }) + } + }, { key: 'defaultAction', value: function e(t) { return l('action', t) } }, { key: 'defaultTarget', value: function e(t) { const n = l('target', t); if (n) return document.querySelector(n) } }, { key: 'defaultText', value: function e(t) { return l('text', t) } }, { key: 'destroy', value: function e() { this.listener.destroy(), this.clipboardAction && (this.clipboardAction.destroy(), this.clipboardAction = null) } }], [{ key: 'isSupported', value: function e() { const t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : ['copy', 'cut']; const n = typeof t === 'string' ? [t] : t; let o = !!document.queryCommandSupported; return n.forEach((e) => { o = o && !!document.queryCommandSupported(e) }), o } }]), t + }(s.default)); e.exports = h + })) + }, { './clipboard-action': 7, 'good-listener': 4, 'tiny-emitter': 6 }] + }, {}, [8]))(8) +})) diff --git a/uni_modules/uview-ui/components/u-tooltip/props.js b/uni_modules/uview-ui/components/u-tooltip/props.js new file mode 100644 index 0000000..16aecbc --- /dev/null +++ b/uni_modules/uview-ui/components/u-tooltip/props.js @@ -0,0 +1,59 @@ +export default { + props: { + // ��������������������������� + text: { + type: [String, Number], + default: uni.$u.props.tooltip.text + }, + // ���������������������������������������������������������text��� + copyText: { + type: [String, Number], + default: uni.$u.props.tooltip.copyText + }, + // ������������ + size: { + type: [String, Number], + default: uni.$u.props.tooltip.size + }, + // ������������ + color: { + type: String, + default: uni.$u.props.tooltip.color + }, + // ��������������������������������������� + bgColor: { + type: String, + default: uni.$u.props.tooltip.bgColor + }, + // ������������������������top-���������bottom-������ + direction: { + type: String, + default: uni.$u.props.tooltip.direction + }, + // ���������������z-index���nvue������ + zIndex: { + type: [String, Number], + default: uni.$u.props.tooltip.zIndex + }, + // ������������������������ + showCopy: { + type: Boolean, + default: uni.$u.props.tooltip.showCopy + }, + // ������������������ + buttons: { + type: Array, + default: uni.$u.props.tooltip.buttons + }, + // ��������������������������������������������� + overlay: { + type: Boolean, + default: uni.$u.props.tooltip.overlay + }, + // ���������������������������������������toast + showToast: { + type: Boolean, + default: uni.$u.props.tooltip.showToast + } + } +} diff --git a/uni_modules/uview-ui/components/u-tooltip/u-tooltip.vue b/uni_modules/uview-ui/components/u-tooltip/u-tooltip.vue new file mode 100644 index 0000000..4bd8fc9 --- /dev/null +++ b/uni_modules/uview-ui/components/u-tooltip/u-tooltip.vue @@ -0,0 +1,365 @@ +<template> + <view + class="u-tooltip" + :style="[$u.addStyle(customStyle)]" + > + <u-overlay + :show="showTooltip && tooltipTop !== -10000 && overlay" + customStyle="backgroundColor: rgba(0, 0, 0, 0)" + @click="overlayClickHandler" + ></u-overlay> + <view class="u-tooltip__wrapper"> + <text + class="u-tooltip__wrapper__text" + :id="textId" + :ref="textId" + :userSelect="false" + :selectable="false" + @longpress.stop="longpressHandler" + :style="{ + color: color, + backgroundColor: bgColor && showTooltip && tooltipTop !== -10000 ? bgColor : 'transparent' + }" + >{{ text }}</text> + <u-transition + mode="fade" + :show="showTooltip" + duration="300" + :customStyle="{ + position: 'absolute', + top: $u.addUnit(tooltipTop), + zIndex: zIndex, + ...tooltipStyle + }" + > + <view + class="u-tooltip__wrapper__popup" + :id="tooltipId" + :ref="tooltipId" + > + <view + class="u-tooltip__wrapper__popup__indicator" + hover-class="u-tooltip__wrapper__popup__indicator--hover" + v-if="showCopy || buttons.length" + :style="[indicatorStyle, { + width: $u.addUnit(indicatorWidth), + height: $u.addUnit(indicatorWidth), + }]" + > + <!-- ������nvue������������������������������������������������������������������45deg������������������������������ --> + </view> + <view class="u-tooltip__wrapper__popup__list"> + <view + v-if="showCopy" + class="u-tooltip__wrapper__popup__list__btn" + hover-class="u-tooltip__wrapper__popup__list__btn--hover" + @tap="setClipboardData" + > + <text + class="u-tooltip__wrapper__popup__list__btn__text" + >������</text> + </view> + <u-line + direction="column" + color="#8d8e90" + v-if="showCopy && buttons.length > 0" + length="18" + ></u-line> + <block v-for="(item , index) in buttons" :key="index"> + <view + class="u-tooltip__wrapper__popup__list__btn" + hover-class="u-tooltip__wrapper__popup__list__btn--hover" + > + <text + class="u-tooltip__wrapper__popup__list__btn__text" + @tap="btnClickHandler(index)" + >{{ item }}</text> + </view> + <u-line + direction="column" + color="#8d8e90" + v-if="index < buttons.length - 1" + length="18" + ></u-line> + </block> + </view> + </view> + </u-transition> + </view> + </view> +</template> + +<script> + import props from './props.js'; + // #ifdef APP-NVUE + const dom = uni.requireNativePlugin('dom') + // #endif + // #ifdef H5 + import ClipboardJS from "./clipboard.min.js" + // #endif + /** + * Tooltip + * @description + * @tutorial https://www.uviewui.com/components/tooltip.html + * @property {String | Number} text ��������������������������� + * @property {String | Number} copyText ���������������������������������������������������������text��� + * @property {String | Number} size ��������������������� 14 ��� + * @property {String} color ��������������������� '#606266' ��� + * @property {String} bgColor ������������������������������������������������ 'transparent' ��� + * @property {String} direction ������������������������top-���������bottom-��������������� 'top' ��� + * @property {String | Number} zIndex ���������������z-index���nvue��������������� 10071 ��� + * @property {Boolean} showCopy ��������������������������������� true ��� + * @property {Array} buttons ������������������ + * @property {Boolean} overlay ������������������������������������������������������ true ��� + * @property {Object} customStyle ��������������������������������� + * + * @event {Function} + * @example + */ + export default { + name: 'u-tooltip', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + // ������������������ + showTooltip: true, + // ������������id������������������������������������������������ + textId: uni.$u.guid(), + tooltipId: uni.$u.guid(), + // ��������������������������������������������������������������������������������������� + tooltipTop: -10000, + // ��������������������� + tooltipInfo: { + width: 0, + left: 0 + }, + // ��������������������� + textInfo: { + width: 0, + left: 0 + }, + // ��������������������������� + indicatorStyle: {}, + // ������������������������������������������������������������������������������������������ + screenGap: 12, + // ��������������������������������������������������������������������������������������������������������������������������������� + indicatorWidth: 14, + } + }, + watch: { + propsChange() { + this.getElRect() + } + }, + computed: { + // ������������H5������������������H5���������������������������������������������H5������ + // ������������������������������������������������������������������������������������ + propsChange() { + return [this.text, this.buttons] + }, + // ��������������������������������������� + tooltipStyle() { + const style = { + transform: `translateY(${this.direction === 'top' ? '-100%' : '100%'})`, + }, + sys = uni.$u.sys(), + getPx = uni.$u.getPx, + addUnit = uni.$u.addUnit + if (this.tooltipInfo.width / 2 > this.textInfo.left + this.textInfo.width / 2 - this.screenGap) { + this.indicatorStyle = {} + style.left = `-${addUnit(this.textInfo.left - this.screenGap)}` + this.indicatorStyle.left = addUnit(this.textInfo.width / 2 - getPx(style.left) - this.indicatorWidth / + 2) + } else if (this.tooltipInfo.width / 2 > sys.windowWidth - this.textInfo.right + this.textInfo.width / 2 - + this.screenGap) { + this.indicatorStyle = {} + style.right = `-${addUnit(sys.windowWidth - this.textInfo.right - this.screenGap)}` + this.indicatorStyle.right = addUnit(this.textInfo.width / 2 - getPx(style.right) - this + .indicatorWidth / 2) + } else { + const left = Math.abs(this.textInfo.width / 2 - this.tooltipInfo.width / 2) + style.left = this.textInfo.width > this.tooltipInfo.width ? addUnit(left) : -addUnit(left) + this.indicatorStyle = {} + } + if (this.direction === 'top') { + style.marginTop = '-10px' + this.indicatorStyle.bottom = '-4px' + } else { + style.marginBottom = '-10px' + this.indicatorStyle.top = '-4px' + } + return style + } + }, + mounted() { + this.init() + }, + methods: { + init() { + this.getElRect() + }, + // ������������������ + async longpressHandler() { + this.tooltipTop = 0 + this.showTooltip = true + }, + // ������������������ + overlayClickHandler() { + this.showTooltip = false + }, + // ������������������ + btnClickHandler(index) { + this.showTooltip = false + // ���������������������������������������index���������1��������������������������������������� + this.$emit('click', this.showCopy ? index + 1 : index) + }, + // ������������������ + queryRect(ref) { + // #ifndef APP-NVUE + // $uGetRect���uView���������������������������������������������������������https://www.uviewui.com/js/getRect.html + // ���������������������this.$uGetRect���������������uni.$u.getRect������������������������������������ + return new Promise(resolve => { + this.$uGetRect(`#${ref}`).then(size => { + resolve(size) + }) + }) + // #endif + + // #ifdef APP-NVUE + // nvue������������dom������������������������ + // ������������promise���������������������������������������then������ + return new Promise(resolve => { + dom.getComponentRect(this.$refs[ref], res => { + resolve(res.size) + }) + }) + // #endif + }, + // ������������ + getElRect() { + // ��������������������������������������������������������������������� + this.showTooltip = true + this.tooltipTop = -10000 + uni.$u.sleep(500).then(() => { + this.queryRect(this.tooltipId).then(size => { + this.tooltipInfo = size + // ������������������������������������������������������������������������������������������������������������������ + this.showTooltip = false + }) + this.queryRect(this.textId).then(size => { + this.textInfo = size + }) + }) + }, + // ������������������������ + setClipboardData() { + // ������������ + this.showTooltip = false + this.$emit('click', 0) + // #ifndef H5 + uni.setClipboardData({ + // ������������copyText���������������������������������������text��������������������������� + data: this.copyText || this.text, + success: () => { + this.showToast && uni.$u.toast('������������') + }, + fail: () => { + this.showToast && uni.$u.toast('������������') + }, + complete: () => { + this.showTooltip = false + } + }) + // #endif + + // #ifdef H5 + let event = window.event || e || {} + let clipboard = new ClipboardJS('', { + text: () => this.copyText || this.text + }) + clipboard.on('success', (e) => { + this.showToast && uni.$u.toast('������������') + clipboard.off('success') + clipboard.off('error') + // ���������������������������������DOM��������� + clipboard.destroy() + }) + clipboard.on('error', (e) => { + this.showToast && uni.$u.toast('������������') + clipboard.off('success') + clipboard.off('error') + // ���������������������������������DOM��������� + clipboard.destroy() + }) + clipboard.onClick(event) + // #endif + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-tooltip { + position: relative; + @include flex; + + &__wrapper { + @include flex; + justify-content: center; + /* #ifndef APP-NVUE */ + white-space: nowrap; + /* #endif */ + + &__text { + font-size: 14px; + } + + &__popup { + @include flex; + justify-content: center; + + &__list { + background-color: #060607; + position: relative; + flex: 1; + border-radius: 5px; + padding: 0px 0; + @include flex(row); + align-items: center; + overflow: hidden; + + &__btn { + padding: 11px 13px; + + &--hover { + background-color: #58595B; + } + + &__text { + line-height: 12px; + font-size: 13px; + color: #FFFFFF; + } + } + } + + &__indicator { + position: absolute; + background-color: #060607; + width: 14px; + height: 14px; + bottom: -4px; + transform: rotate(45deg); + border-radius: 2px; + z-index: -1; + + &--hover { + background-color: #58595B; + } + } + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-tr/props.js b/uni_modules/uview-ui/components/u-tr/props.js new file mode 100644 index 0000000..7c11331 --- /dev/null +++ b/uni_modules/uview-ui/components/u-tr/props.js @@ -0,0 +1,5 @@ +export default { + props: { + + } +} diff --git a/uni_modules/uview-ui/components/u-tr/u-tr.vue b/uni_modules/uview-ui/components/u-tr/u-tr.vue new file mode 100644 index 0000000..dbbca08 --- /dev/null +++ b/uni_modules/uview-ui/components/u-tr/u-tr.vue @@ -0,0 +1,31 @@ +<template> + <view class="u-tr"> + + </view> +</template> + +<script> + import props from './props.js'; + /** + * Tr + * @description + * @tutorial url + * @property {String} + * @event {Function} + * @example + */ + export default { + name: 'u-tr', + mixins: [uni.$u.mpMixin, uni.$u.mixin,props], + data() { + return { + + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + +</style> diff --git a/uni_modules/uview-ui/components/u-transition/nvue.ani-map.js b/uni_modules/uview-ui/components/u-transition/nvue.ani-map.js new file mode 100644 index 0000000..b86b962 --- /dev/null +++ b/uni_modules/uview-ui/components/u-transition/nvue.ani-map.js @@ -0,0 +1,68 @@ +export default { + fade: { + enter: { opacity: 0 }, + 'enter-to': { opacity: 1 }, + leave: { opacity: 1 }, + 'leave-to': { opacity: 0 } + }, + 'fade-up': { + enter: { opacity: 0, transform: 'translateY(100%)' }, + 'enter-to': { opacity: 1, transform: 'translateY(0)' }, + leave: { opacity: 1, transform: 'translateY(0)' }, + 'leave-to': { opacity: 0, transform: 'translateY(100%)' } + }, + 'fade-down': { + enter: { opacity: 0, transform: 'translateY(-100%)' }, + 'enter-to': { opacity: 1, transform: 'translateY(0)' }, + leave: { opacity: 1, transform: 'translateY(0)' }, + 'leave-to': { opacity: 0, transform: 'translateY(-100%)' } + }, + 'fade-left': { + enter: { opacity: 0, transform: 'translateX(-100%)' }, + 'enter-to': { opacity: 1, transform: 'translateY(0)' }, + leave: { opacity: 1, transform: 'translateY(0)' }, + 'leave-to': { opacity: 0, transform: 'translateX(-100%)' } + }, + 'fade-right': { + enter: { opacity: 0, transform: 'translateX(100%)' }, + 'enter-to': { opacity: 1, transform: 'translateY(0)' }, + leave: { opacity: 1, transform: 'translateY(0)' }, + 'leave-to': { opacity: 0, transform: 'translateX(100%)' } + }, + 'slide-up': { + enter: { transform: 'translateY(100%)' }, + 'enter-to': { transform: 'translateY(0)' }, + leave: { transform: 'translateY(0)' }, + 'leave-to': { transform: 'translateY(100%)' } + }, + 'slide-down': { + enter: { transform: 'translateY(-100%)' }, + 'enter-to': { transform: 'translateY(0)' }, + leave: { transform: 'translateY(0)' }, + 'leave-to': { transform: 'translateY(-100%)' } + }, + 'slide-left': { + enter: { transform: 'translateX(-100%)' }, + 'enter-to': { transform: 'translateY(0)' }, + leave: { transform: 'translateY(0)' }, + 'leave-to': { transform: 'translateX(-100%)' } + }, + 'slide-right': { + enter: { transform: 'translateX(100%)' }, + 'enter-to': { transform: 'translateY(0)' }, + leave: { transform: 'translateY(0)' }, + 'leave-to': { transform: 'translateX(100%)' } + }, + zoom: { + enter: { transform: 'scale(0.95)' }, + 'enter-to': { transform: 'scale(1)' }, + leave: { transform: 'scale(1)' }, + 'leave-to': { transform: 'scale(0.95)' } + }, + 'fade-zoom': { + enter: { opacity: 0, transform: 'scale(0.95)' }, + 'enter-to': { opacity: 1, transform: 'scale(1)' }, + leave: { opacity: 1, transform: 'scale(1)' }, + 'leave-to': { opacity: 0, transform: 'scale(0.95)' } + } +} diff --git a/uni_modules/uview-ui/components/u-transition/props.js b/uni_modules/uview-ui/components/u-transition/props.js new file mode 100644 index 0000000..f7b1c22 --- /dev/null +++ b/uni_modules/uview-ui/components/u-transition/props.js @@ -0,0 +1,24 @@ +export default { + props: { + // ������������������ + show: { + type: Boolean, + default: uni.$u.props.transition.show + }, + // ��������������������� + mode: { + type: String, + default: uni.$u.props.transition.mode + }, + // ������������������������������ms + duration: { + type: [String, Number], + default: uni.$u.props.transition.duration + }, + // ��������������������������� + timingFunction: { + type: String, + default: uni.$u.props.transition.timingFunction + } + } +} diff --git a/uni_modules/uview-ui/components/u-transition/transition.js b/uni_modules/uview-ui/components/u-transition/transition.js new file mode 100644 index 0000000..92e5681 --- /dev/null +++ b/uni_modules/uview-ui/components/u-transition/transition.js @@ -0,0 +1,157 @@ +// ������������������������������������������promise������������nextTick���������������������������then������ +const nextTick = () => new Promise(resolve => setTimeout(resolve, 1000 / 50)) +// nvue��������������������������������������������� +import animationMap from './nvue.ani-map.js' + +// #ifndef APP-NVUE +// ������������������������������������������������������������������������css������������ +const getClassNames = (name) => ({ + enter: `u-${name}-enter u-${name}-enter-active`, + 'enter-to': `u-${name}-enter-to u-${name}-enter-active`, + leave: `u-${name}-leave u-${name}-leave-active`, + 'leave-to': `u-${name}-leave-to u-${name}-leave-active` +}) +// #endif + +// #ifdef APP-NVUE +// ������nvue(weex)���animation��������������������������� +// https://weex.apache.org/zh/docs/modules/animation.html#transition +const animation = uni.requireNativePlugin('animation') +const getStyle = (name) => animationMap[name] +// #endif + +export default { + methods: { + // ��������������������������� + clickHandler() { + this.$emit('click') + }, + // #ifndef APP-NVUE + // vue��������������������������� + vueEnter() { + // ������������������������ + const classNames = getClassNames(this.mode) + // ������������������������������������������ + this.status = 'enter' + this.$emit('beforeEnter') + this.inited = true + this.display = true + this.classes = classNames.enter + this.$nextTick(async () => { + // #ifdef H5 + await uni.$u.sleep(20) + // #endif + // ������������������������ + this.$emit('enter') + this.transitionEnded = false + // ������������������������������������ + this.$emit('afterEnter') + // ������������enter-to������ + this.classes = classNames['enter-to'] + }) + }, + // ������������������ + vueLeave() { + // ��������������������������������������������� + if (!this.display) return + const classNames = getClassNames(this.mode) + // ��������������������������������� + this.status = 'leave' + this.$emit('beforeLeave') + // ������������ + this.classes = classNames.leave + + this.$nextTick(() => { + // ��������������������������� + this.transitionEnded = false + this.$emit('leave') + // ������������������������������������������������������������������������������ + setTimeout(this.onTransitionEnd, this.duration) + this.classes = classNames['leave-to'] + }) + }, + // #endif + // #ifdef APP-NVUE + // nvue������������������ + nvueEnter() { + // ��������������������� + const currentStyle = getStyle(this.mode) + // ��������������������������������� + this.status = 'enter' + this.$emit('beforeEnter') + // ������������������������ + this.inited = true + this.display = true + // ���nvue��������������������������������������������������������������������������������������������������������������� + // ��������������������������������������������������������������������������������������������������������������������������������������������������������� + this.viewStyle = { + opacity: 0 + } + // ������������������������������ + this.$nextTick(() => { + // ������������ + this.viewStyle = currentStyle.enter + Promise.resolve() + .then(nextTick) + .then(() => { + // ������������������������������ + this.$emit('enter') + // nvue���transition������������������������ref������������������������������ref���������vue���this.$refs['u-transition']������ + animation.transition(this.$refs['u-transition'].ref, { + styles: currentStyle['enter-to'], + duration: this.duration, + timingFunction: this.timingFunction, + needLayout: false, + delay: 0 + }, () => { + // ��������������������������������� + this.$emit('afterEnter') + }) + }) + .catch(() => {}) + }) + }, + nvueLeave() { + if (!this.display) { + return + } + const currentStyle = getStyle(this.mode) + // ��������������������� + this.status = 'leave' + this.$emit('beforeLeave') + // ������������ + this.viewStyle = currentStyle.leave + // ������promise��������������������� + Promise.resolve() + .then(nextTick) // ������������ms + .then(() => { + this.transitionEnded = false + // ��������������������������� + this.$emit('leave') + animation.transition(this.$refs['u-transition'].ref, { + styles: currentStyle['leave-to'], + duration: this.duration, + timingFunction: this.timingFunction, + needLayout: false, + delay: 0 + }, () => { + this.onTransitionEnd() + }) + }) + .catch(() => {}) + }, + // #endif + // ��������������������� + onTransitionEnd() { + // ������������������������������������������������ + if (this.transitionEnded) return + this.transitionEnded = true + // ������������������������������������ + this.$emit(this.status === 'leave' ? 'afterLeave' : 'afterEnter') + if (!this.show && this.display) { + this.display = false + this.inited = false + } + } + } +} diff --git a/uni_modules/uview-ui/components/u-transition/u-transition.vue b/uni_modules/uview-ui/components/u-transition/u-transition.vue new file mode 100644 index 0000000..22831dc --- /dev/null +++ b/uni_modules/uview-ui/components/u-transition/u-transition.vue @@ -0,0 +1,92 @@ +<template> + <view + v-if="inited" + class="u-transition" + ref="u-transition" + @tap="clickHandler" + :class="classes" + :style="[mergeStyle]" + @touchmove="noop" + > + <slot /> + </view> +</template> + +<script> +import props from './props.js'; +// ���������methods���������������������������������������������������������mixin������ +import transition from "./transition.js"; +/** + * transition ������������ + * @description + * @tutorial + * @property {String} show ������������������ ��������� false ��� + * @property {String} mode ��������������������� ��������� 'fade' ��� + * @property {String | Number} duration ������������������������������ms ��������� '300' ��� + * @property {String} timingFunction ��������������������������� ��������� 'ease-out' ��� + * @property {Object} customStyle ��������������� + * @event {Function} before-enter ��������������� + * @event {Function} enter ��������������� + * @event {Function} after-enter ��������������� + * @event {Function} before-leave ��������������� + * @event {Function} leave ��������������� + * @event {Function} after-leave ��������������� + * @example + */ +export default { + name: 'u-transition', + data() { + return { + inited: false, // ������������/������������ + viewStyle: {}, // ��������������������� + status: '', // ��������������������������� + transitionEnded: false, // ��������������������������� + display: false, // ������������������ + classes: '', // ��������������� + } + }, + computed: { + mergeStyle() { + const { viewStyle, customStyle } = this + return { + // #ifndef APP-NVUE + transitionDuration: `${this.duration}ms`, + // display: `${this.display ? '' : 'none'}`, + transitionTimingFunction: this.timingFunction, + // #endif + // ���������������������������������������������������������viewStyle������ + ...uni.$u.addStyle(customStyle), + ...viewStyle + } + } + }, + // ���mixin���������������������uni.$u.mixin������������������vue������������ + mixins: [uni.$u.mpMixin, uni.$u.mixin, transition, props], + watch: { + show: { + handler(newVal) { + // vue���nvue��������������������������� + // #ifdef APP-NVUE + newVal ? this.nvueEnter() : this.nvueLeave() + // #endif + // #ifndef APP-NVUE + newVal ? this.vueEnter() : this.vueLeave() + // #endif + }, + // ���������������������������������props���show��������� + immediate: true + } + } +} +</script> + +<style lang="scss" scoped> +@import '../../libs/css/components.scss'; + +/* #ifndef APP-NVUE */ +// vue������������������������������������������������ +@import './vue.ani-style.scss'; +/* #endif */ + +.u-transition {} +</style> diff --git a/uni_modules/uview-ui/components/u-transition/vue.ani-style.scss b/uni_modules/uview-ui/components/u-transition/vue.ani-style.scss new file mode 100644 index 0000000..a31d88b --- /dev/null +++ b/uni_modules/uview-ui/components/u-transition/vue.ani-style.scss @@ -0,0 +1,113 @@ +/** + * vue��������������������������������������������� + * fade��������� + * zoom��������� + * fade-zoom��������������� + * fade-up��������������� + * fade-down��������������� + * fade-left��������������� + * fade-right��������������� + * slide-up��������������� + * slide-down��������������� + * slide-left��������������� + * slide-right��������������� + */ + +$u-zoom-scale: scale(0.95); + +.u-fade-enter-active, +.u-fade-leave-active { + transition-property: opacity; +} + +.u-fade-enter, +.u-fade-leave-to { + opacity: 0 +} + +.u-fade-zoom-enter, +.u-fade-zoom-leave-to { + transform: $u-zoom-scale; + opacity: 0; +} + +.u-fade-zoom-enter-active, +.u-fade-zoom-leave-active { + transition-property: transform, opacity; +} + +.u-fade-down-enter-active, +.u-fade-down-leave-active, +.u-fade-left-enter-active, +.u-fade-left-leave-active, +.u-fade-right-enter-active, +.u-fade-right-leave-active, +.u-fade-up-enter-active, +.u-fade-up-leave-active { + transition-property: opacity, transform; +} + +.u-fade-up-enter, +.u-fade-up-leave-to { + transform: translate3d(0, 100%, 0); + opacity: 0 +} + +.u-fade-down-enter, +.u-fade-down-leave-to { + transform: translate3d(0, -100%, 0); + opacity: 0 +} + +.u-fade-left-enter, +.u-fade-left-leave-to { + transform: translate3d(-100%, 0, 0); + opacity: 0 +} + +.u-fade-right-enter, +.u-fade-right-leave-to { + transform: translate3d(100%, 0, 0); + opacity: 0 +} + +.u-slide-down-enter-active, +.u-slide-down-leave-active, +.u-slide-left-enter-active, +.u-slide-left-leave-active, +.u-slide-right-enter-active, +.u-slide-right-leave-active, +.u-slide-up-enter-active, +.u-slide-up-leave-active { + transition-property: transform; +} + +.u-slide-up-enter, +.u-slide-up-leave-to { + transform: translate3d(0, 100%, 0) +} + +.u-slide-down-enter, +.u-slide-down-leave-to { + transform: translate3d(0, -100%, 0) +} + +.u-slide-left-enter, +.u-slide-left-leave-to { + transform: translate3d(-100%, 0, 0) +} + +.u-slide-right-enter, +.u-slide-right-leave-to { + transform: translate3d(100%, 0, 0) +} + +.u-zoom-enter-active, +.u-zoom-leave-active { + transition-property: transform +} + +.u-zoom-enter, +.u-zoom-leave-to { + transform: $u-zoom-scale +} diff --git a/uni_modules/uview-ui/components/u-upload/mixin.js b/uni_modules/uview-ui/components/u-upload/mixin.js new file mode 100644 index 0000000..410c775 --- /dev/null +++ b/uni_modules/uview-ui/components/u-upload/mixin.js @@ -0,0 +1,21 @@ +export default { + watch: { + // ������accept��������������������������������������������� + // ��������������������������������������������������������������������������������������������� + accept: { + immediate: true, + handler(val) { + // #ifndef MP-WEIXIN + if (val === 'all' || val === 'media') { + uni.$u.error('���������������������������������accept���������all���media������') + } + // #endif + // #ifndef H5 || MP-WEIXIN + if (val === 'file') { + uni.$u.error('������������������������H5(HX2.9.9)������������accept���������file') + } + // #endif + } + } + } +} diff --git a/uni_modules/uview-ui/components/u-upload/props.js b/uni_modules/uview-ui/components/u-upload/props.js new file mode 100644 index 0000000..b106ae7 --- /dev/null +++ b/uni_modules/uview-ui/components/u-upload/props.js @@ -0,0 +1,124 @@ +export default { + props: { + // ���������������������, ������������all media image file video + accept: { + type: String, + default: uni.$u.props.upload.accept + }, + // ���������������������������������accept���image���������������capture������������camera��������������������������� + capture: { + type: [String, Array], + default: uni.$u.props.upload.capture + }, + // ���accept���video������������������������������������������true + compressed: { + type: Boolean, + default: uni.$u.props.upload.compressed + }, + // ���accept���video������������������������back���front + camera: { + type: String, + default: uni.$u.props.upload.camera + }, + // ���accept���video������������������������������������������������������ + maxDuration: { + type: Number, + default: uni.$u.props.upload.maxDuration + }, + // ������������������������������������������ + uploadIcon: { + type: String, + default: uni.$u.props.upload.uploadIcon + }, + // ��������������������������������������� + uploadIconColor: { + type: String, + default: uni.$u.props.upload.uploadIconColor + }, + // ��������������������������������� + useBeforeRead: { + type: Boolean, + default: uni.$u.props.upload.useBeforeRead + }, + // ������������������������ + afterRead: { + type: Function, + default: null + }, + // ������������������������ + beforeRead: { + type: Function, + default: null + }, + // ��������������������������������������������� + previewFullImage: { + type: Boolean, + default: uni.$u.props.upload.previewFullImage + }, + // ������������������ + maxCount: { + type: [String, Number], + default: uni.$u.props.upload.maxCount + }, + // ������������ + disabled: { + type: Boolean, + default: uni.$u.props.upload.disabled + }, + // ���������������������������������������������image������mode������������ + imageMode: { + type: String, + default: uni.$u.props.upload.imageMode + }, + // ������������������������������������������������������������ + name: { + type: String, + default: uni.$u.props.upload.name + }, + // ������������������������, ������������original compressed + sizeType: { + type: Array, + default: uni.$u.props.upload.sizeType + }, + // ������������������������������������������������������ + multiple: { + type: Boolean, + default: uni.$u.props.upload.multiple + }, + // ������������������������ + deletable: { + type: Boolean, + default: uni.$u.props.upload.deletable + }, + // ������������������������������byte + maxSize: { + type: [String, Number], + default: uni.$u.props.upload.maxSize + }, + // ������������������������������ + fileList: { + type: Array, + default: uni.$u.props.upload.fileList + }, + // ��������������������������� + uploadText: { + type: String, + default: uni.$u.props.upload.uploadText + }, + // ������������������������������������������������������������ + width: { + type: [String, Number], + default: uni.$u.props.upload.width + }, + // ������������������������������������������������������������ + height: { + type: [String, Number], + default: uni.$u.props.upload.height + }, + // ��������������������������������������� + previewImage: { + type: Boolean, + default: uni.$u.props.upload.previewImage + } + } +} diff --git a/uni_modules/uview-ui/components/u-upload/u-upload.vue b/uni_modules/uview-ui/components/u-upload/u-upload.vue new file mode 100644 index 0000000..1dac8a7 --- /dev/null +++ b/uni_modules/uview-ui/components/u-upload/u-upload.vue @@ -0,0 +1,558 @@ +<template> + <view class="u-upload" :style="[$u.addStyle(customStyle)]"> + <view class="u-upload__wrap" > + <template v-if="previewImage"> + <view + class="u-upload__wrap__preview" + v-for="(item, index) in lists" + :key="index" + > + <image + v-if="item.isImage || (item.type && item.type === 'image')" + :src="item.thumb || item.url" + :mode="imageMode" + class="u-upload__wrap__preview__image" + @tap="onPreviewImage(item)" + :style="[{ + width: $u.addUnit(width), + height: $u.addUnit(height) + }]" + /> + <view + v-else + class="u-upload__wrap__preview__other" + > + <u-icon + color="#80CBF9" + size="26" + :name="item.isVideo || (item.type && item.type === 'video') ? 'movie' : 'folder'" + ></u-icon> + <text class="u-upload__wrap__preview__other__text">{{item.isVideo || (item.type && item.type === 'video') ? '������' : '������'}}</text> + </view> + <view + class="u-upload__status" + v-if="item.status === 'uploading' || item.status === 'failed'" + > + <view class="u-upload__status__icon"> + <u-icon + v-if="item.status === 'failed'" + name="close-circle" + color="#ffffff" + size="25" + /> + <u-loading-icon + size="22" + mode="circle" + color="#ffffff" + v-else + /> + </view> + <text + v-if="item.message" + class="u-upload__status__message" + >{{ item.message }}</text> + </view> + <view + class="u-upload__deletable" + v-if="item.status !== 'uploading' && (deletable || item.deletable)" + @tap.stop="deleteItem(index)" + > + <view class="u-upload__deletable__icon"> + <u-icon + name="close" + color="#ffffff" + size="10" + ></u-icon> + </view> + </view> + <view + class="u-upload__success" + v-if="item.status === 'success'" + > + <!-- #ifdef APP-NVUE --> + <image + :src="successIcon" + class="u-upload__success__icon" + ></image> + <!-- #endif --> + <!-- #ifndef APP-NVUE --> + <view class="u-upload__success__icon"> + <u-icon + name="checkmark" + color="#ffffff" + size="12" + ></u-icon> + </view> + <!-- #endif --> + </view> + </view> + + </template> + + <template v-if="isInCount"> + <view + v-if="$slots.default || $slots.$default" + @tap="chooseFile" + > + <slot /> + </view> + <view + v-else + class="u-upload__button" + :hover-class="!disabled ? 'u-upload__button--hover' : ''" + hover-stay-time="150" + @tap="chooseFile" + :class="[disabled && 'u-upload__button--disabled']" + :style="[{ + width: $u.addUnit(width), + height: $u.addUnit(height) + }]" + > + <u-icon + :name="uploadIcon" + size="26" + :color="uploadIconColor" + ></u-icon> + <text + v-if="uploadText" + class="u-upload__button__text" + >{{ uploadText }}</text> + </view> + </template> + </view> + + </view> +</template> + +<script> + import { + chooseFile + } from './utils'; + import mixin from './mixin.js'; + import props from './props.js'; + + /** + * upload ������ + * @description ��������������������������������� + * @tutorial https://uviewui.com/components/upload.html + * @property {String} accept ���������������������, ������������all media image file video ��������� 'image' ��� + * @property {String | Array} capture ���������������������������������accept���image���������������capture������������camera������������������������������������ ['album', 'camera'] ��� + * @property {Boolean} compressed ���accept���video������������������������������������������true��������� true ��� + * @property {String} camera ���accept���video������������������������back���front��������� 'back' ��� + * @property {Number} maxDuration ���accept���video��������������������������������������������������������������� 60 ��� + * @property {String} uploadIcon ��������������������������������������������������� 'camera-fill' ��� + * @property {String} uploadIconColor ������������������������������������������������������������������ #D3D4D6 ��� + * @property {Boolean} useBeforeRead ������������������������������������������ false ��� + * @property {Boolean} previewFullImage ������������������������������������������������������ true ��� + * @property {String | Number} maxCount ��������������������������� 52 ��� + * @property {Boolean} disabled ��������������������� false ��� + * @property {String} imageMode ���������������������������������������������image������mode��������������������� 'aspectFill' ��� + * @property {String} name ������������������������������������������������������������ + * @property {Array} sizeType ������������������������, ������������original compressed��������� ['original', 'compressed'] ��� + * @property {Boolean} multiple ������������������������������������������������������ ��������� false ��� + * @property {Boolean} deletable ��������������������������������� true ��� + * @property {String | Number} maxSize ������������������������������byte ��������� Number.MAX_VALUE ��� + * @property {Array} fileList ������������������������������ + * @property {String} uploadText ��������������������������� + * @property {String | Number} width ��������������������������������������������������������������������� 80 ��� + * @property {String | Number} height ��������������������������������������������������������������������� 80 ��� + * @property {Object} customStyle ������������������������������ + * @event {Function} afterRead ������������������������ + * @event {Function} beforeRead ������������������������ + * @event {Function} oversize ������������������������ + * @event {Function} clickPreview ������������������ + * @event {Function} delete ������������ + * @example <u-upload :action="action" :fileList="fileList" ></u-upload> + */ + export default { + name: "u-upload", + mixins: [uni.$u.mpMixin, uni.$u.mixin, mixin,props], + data() { + return { + // #ifdef APP-NVUE + successIcon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAKKADAAQAAAABAAAAKAAAAAB65masAAACP0lEQVRYCc3YXygsURwH8K/dpcWyG3LF5u/6/+dKVylSypuUl6uUPMifKMWL8oKEB1EUT1KeUPdR3uTNUsSLxb2udG/cbvInNuvf2rVnazZ/ZndmZ87snjM1Z+Z3zpzfp9+Z5mEAhlvjRtZgCKs+gnPAOcAkkMOR4jEHfItjDvgRxxSQD8cM0BuOCaAvXNCBQrigAsXgggYUiwsK0B9cwIH+4gIKlIILGFAqLiBAOTjFgXJxigJp4BQD0sIpAqSJow6kjSNAFTnRaHJwLenD6Mud52VQAcrBfTd2oyq+HtGaGGWAcnAVcXWoM3bCZrdi+ncPfaAcXE5UKVpdW/vitGPqqAtn98d0gXJwX7Qp6MmegUYVhvmTIezdmHlxJCjpHRTCFerLkRRu4k0aqdajN3sWOo0BK//msHa+xDuPC/oNFMKRhTtM4xjIX0SCNpXL4+7VIaHuyiWEp2L7ahWLf8fejfPdqPmC3mJicORZUp1CQzm+GiphvljGk+PBvWRbxii+xVTj5M6CiZ/tsDufvaXyxEUDxeLIyvu3m0iOyEFWVAkydcVYdyFrE9tQk9iMq6f/GNlvwt3LjQfh60LUrw9/cFyyMJUW/XkLSNMV4Mi6C5ML+ui4x5ClAX9sB9w0wV6wglJwJCv5fOxcr6EstgbGiEw4XcfUry4cWrcEUW8n+ARKxXEJHhw2WG43UKSvwI/TSZgvl7kh0b3XLZaLEy0QmMgLZAVH7J+ALOE+AVnDvQOyiPMAWcW5gSzjCPAV+78S5WE0GrQAAAAASUVORK5CYII=', + // #endif + lists: [], + isInCount: true, + } + }, + watch: { + // ������������������������������������������������������ + fileList: { + immediate: true, + handler() { + this.formatFileList() + } + }, + }, + methods: { + formatFileList() { + const { + fileList = [], maxCount + } = this; + const lists = fileList.map((item) => + Object.assign(Object.assign({}, item), { + // ������item.url������������������blob���������������������������������video������image���������������������accept��������������� + isImage: this.accept === 'image' || uni.$u.test.image(item.url || item.thumb), + isVideo: this.accept === 'video' || uni.$u.test.video(item.url || item.thumb), + deletable: typeof(item.deletable) === 'boolean' ? item.deletable : this.deletable, + }) + ); + this.lists = lists + this.isInCount = lists.length < maxCount + }, + chooseFile() { + const { + maxCount, + multiple, + lists, + disabled + } = this; + if (disabled) return; + // ������������������������������������������������������������ + let capture; + try { + capture = uni.$u.test.array(this.capture) ? this.capture : this.capture.split(','); + }catch(e) { + capture = []; + } + chooseFile( + Object.assign({ + accept: this.accept, + multiple: this.multiple, + capture: capture, + compressed: this.compressed, + maxDuration: this.maxDuration, + sizeType: this.sizeType, + camera: this.camera, + }, { + maxCount: maxCount - lists.length, + }) + ) + .then((res) => { + this.onBeforeRead(multiple ? res : res[0]); + }) + .catch((error) => { + this.$emit('error', error); + }); + }, + // ������������������ + onBeforeRead(file) { + const { + beforeRead, + useBeforeRead, + } = this; + let res = true + // beforeRead��������������������� + if (uni.$u.test.func(beforeRead)) { + // ��������������������������������������������������������������������������������������� + res = beforeRead(file, this.getDetail()); + } + if (useBeforeRead) { + res = new Promise((resolve, reject) => { + this.$emit( + 'beforeRead', + Object.assign(Object.assign({ + file + }, this.getDetail()), { + callback: (ok) => { + ok ? resolve() : reject(); + }, + }) + ); + }); + } + if (!res) { + return; + } + if (uni.$u.test.promise(res)) { + res.then((data) => this.onAfterRead(data || file)); + } else { + this.onAfterRead(file); + } + }, + getDetail(index) { + return { + name: this.name, + index: index == null ? this.fileList.length : index, + }; + }, + onAfterRead(file) { + const { + maxSize, + afterRead + } = this; + const oversize = Array.isArray(file) ? + file.some((item) => item.size > maxSize) : + file.size > maxSize; + if (oversize) { + this.$emit('oversize', Object.assign({ + file + }, this.getDetail())); + return; + } + if (typeof afterRead === 'function') { + afterRead(file, this.getDetail()); + } + this.$emit('afterRead', Object.assign({ + file + }, this.getDetail())); + }, + deleteItem(index) { + this.$emit( + 'delete', + Object.assign(Object.assign({}, this.getDetail(index)), { + file: this.fileList[index], + }) + ); + }, + // ������������ + onPreviewImage(item) { + if (!item.isImage || !this.previewFullImage) return + uni.previewImage({ + // ���filter������������������item������������filter������������������url + urls: this.lists.filter((item) => this.accept === 'image' || uni.$u.test.image(item.url || item.thumb)).map((item) => item.url || item.thumb), + current: item.url || item.thumb, + fail() { + uni.$u.toast('������������������') + }, + }); + }, + onPreviewVideo(event) { + if (!this.data.previewFullImage) return; + const { + index + } = event.currentTarget.dataset; + const { + lists + } = this.data; + wx.previewMedia({ + sources: lists + .filter((item) => isVideoFile(item)) + .map((item) => + Object.assign(Object.assign({}, item), { + type: 'video' + }) + ), + current: index, + fail() { + uni.$u.toast('������������������') + }, + }); + }, + onClickPreview(event) { + const { + index + } = event.currentTarget.dataset; + const item = this.data.lists[index]; + this.$emit( + 'clickPreview', + Object.assign(Object.assign({}, item), this.getDetail(index)) + ); + } + } + } +</script> + +<style lang="scss" scoped> + @import '../../libs/css/components.scss'; + $u-upload-preview-border-radius: 2px !default; + $u-upload-preview-margin: 0 8px 8px 0 !default; + $u-upload-image-width:80px !default; + $u-upload-image-height:$u-upload-image-width; + $u-upload-other-bgColor: rgb(242, 242, 242) !default; + $u-upload-other-flex:1 !default; + $u-upload-text-font-size:11px !default; + $u-upload-text-color:$u-tips-color !default; + $u-upload-text-margin-top:2px !default; + $u-upload-deletable-right:0 !default; + $u-upload-deletable-top:0 !default; + $u-upload-deletable-bgColor:rgb(55, 55, 55) !default; + $u-upload-deletable-height:14px !default; + $u-upload-deletable-width:$u-upload-deletable-height; + $u-upload-deletable-boder-bottom-left-radius:100px !default; + $u-upload-deletable-zIndex:3 !default; + $u-upload-success-bottom:0 !default; + $u-upload-success-right:0 !default; + $u-upload-success-border-style:solid !default; + $u-upload-success-border-top-color:transparent !default; + $u-upload-success-border-left-color:transparent !default; + $u-upload-success-border-bottom-color: $u-success !default; + $u-upload-success-border-right-color:$u-upload-success-border-bottom-color; + $u-upload-success-border-width:9px !default; + $u-upload-icon-top:0px !default; + $u-upload-icon-right:0px !default; + $u-upload-icon-h5-top:1px !default; + $u-upload-icon-h5-right:0 !default; + $u-upload-icon-width:16px !default; + $u-upload-icon-height:$u-upload-icon-width; + $u-upload-success-icon-bottom:-10px !default; + $u-upload-success-icon-right:-10px !default; + $u-upload-status-right:0 !default; + $u-upload-status-left:0 !default; + $u-upload-status-bottom:0 !default; + $u-upload-status-top:0 !default; + $u-upload-status-bgColor:rgba(0, 0, 0, 0.5) !default; + $u-upload-status-icon-Zindex:1 !default; + $u-upload-message-font-size:12px !default; + $u-upload-message-color:#FFFFFF !default; + $u-upload-message-margin-top:5px !default; + $u-upload-button-width:80px !default; + $u-upload-button-height:$u-upload-button-width; + $u-upload-button-bgColor:rgb(244, 245, 247) !default; + $u-upload-button-border-radius:2px !default; + $u-upload-botton-margin: 0 8px 8px 0 !default; + $u-upload-text-font-size:11px !default; + $u-upload-text-color:$u-tips-color !default; + $u-upload-text-margin-top: 2px !default; + $u-upload-hover-bgColor:rgb(230, 231, 233) !default; + $u-upload-disabled-opacity:.5 !default; + + .u-upload { + @include flex(column); + flex: 1; + + &__wrap { + @include flex; + flex-wrap: wrap; + flex: 1; + + &__preview { + border-radius: $u-upload-preview-border-radius; + margin: $u-upload-preview-margin; + position: relative; + overflow: hidden; + @include flex; + + &__image { + width: $u-upload-image-width; + height: $u-upload-image-height; + } + + &__other { + width: $u-upload-image-width; + height: $u-upload-image-height; + background-color: $u-upload-other-bgColor; + flex: $u-upload-other-flex; + @include flex(column); + justify-content: center; + align-items: center; + + &__text { + font-size: $u-upload-text-font-size; + color: $u-upload-text-color; + margin-top: $u-upload-text-margin-top; + } + } + } + } + + &__deletable { + position: absolute; + top: $u-upload-deletable-top; + right: $u-upload-deletable-right; + background-color: $u-upload-deletable-bgColor; + height: $u-upload-deletable-height; + width: $u-upload-deletable-width; + @include flex; + border-bottom-left-radius: $u-upload-deletable-boder-bottom-left-radius; + align-items: center; + justify-content: center; + z-index: $u-upload-deletable-zIndex; + + &__icon { + position: absolute; + transform: scale(0.7); + top: $u-upload-icon-top; + right: $u-upload-icon-right; + /* #ifdef H5 */ + top: $u-upload-icon-h5-top; + right: $u-upload-icon-h5-right; + /* #endif */ + } + } + + &__success { + position: absolute; + bottom: $u-upload-success-bottom; + right: $u-upload-success-right; + @include flex; + // ������weex(nvue)������������������KPI(������������������)���laji������������������css��������������� + // ���������nvue���������������������nvue���������css������ + /* #ifndef APP-NVUE */ + border-style: $u-upload-success-border-style; + border-top-color: $u-upload-success-border-top-color; + border-left-color: $u-upload-success-border-left-color; + border-bottom-color: $u-upload-success-border-bottom-color; + border-right-color: $u-upload-success-border-right-color; + border-width: $u-upload-success-border-width; + align-items: center; + justify-content: center; + /* #endif */ + + &__icon { + /* #ifndef APP-NVUE */ + position: absolute; + transform: scale(0.7); + bottom: $u-upload-success-icon-bottom; + right: $u-upload-success-icon-right; + /* #endif */ + /* #ifdef APP-NVUE */ + width: $u-upload-icon-width; + height: $u-upload-icon-height; + /* #endif */ + } + } + + &__status { + position: absolute; + top: $u-upload-status-top; + bottom: $u-upload-status-bottom; + left: $u-upload-status-left; + right: $u-upload-status-right; + background-color: $u-upload-status-bgColor; + @include flex(column); + align-items: center; + justify-content: center; + + &__icon { + position: relative; + z-index: $u-upload-status-icon-Zindex; + } + + &__message { + font-size: $u-upload-message-font-size; + color: $u-upload-message-color; + margin-top: $u-upload-message-margin-top; + } + } + + &__button { + @include flex(column); + align-items: center; + justify-content: center; + width: $u-upload-button-width; + height: $u-upload-button-height; + background-color: $u-upload-button-bgColor; + border-radius: $u-upload-button-border-radius; + margin: $u-upload-botton-margin; + /* #ifndef APP-NVUE */ + box-sizing: border-box; + /* #endif */ + + &__text { + font-size: $u-upload-text-font-size; + color: $u-upload-text-color; + margin-top: $u-upload-text-margin-top; + } + + &--hover { + background-color: $u-upload-hover-bgColor; + } + + &--disabled { + opacity: $u-upload-disabled-opacity; + } + } + } +</style> diff --git a/uni_modules/uview-ui/components/u-upload/utils.js b/uni_modules/uview-ui/components/u-upload/utils.js new file mode 100644 index 0000000..88cb602 --- /dev/null +++ b/uni_modules/uview-ui/components/u-upload/utils.js @@ -0,0 +1,151 @@ +function pickExclude(obj, keys) { + // ������������������type������������ + if (!['[object Object]', '[object File]'].includes(Object.prototype.toString.call(obj))) { + return {} + } + return Object.keys(obj).reduce((prev, key) => { + if (!keys.includes(key)) { + prev[key] = obj[key] + } + return prev + }, {}) +} + +function formatImage(res) { + return res.tempFiles.map((item) => ({ + ...pickExclude(item, ['path']), + type: 'image', + url: item.path, + thumb: item.path, + size: item.size, + // #ifdef H5 + name: item.name + // #endif + })) +} + +function formatVideo(res) { + return [ + { + ...pickExclude(res, ['tempFilePath', 'thumbTempFilePath', 'errMsg']), + type: 'video', + url: res.tempFilePath, + thumb: res.thumbTempFilePath, + size: res.size, + // #ifdef H5 + name: res.name + // #endif + } + ] +} + +function formatMedia(res) { + return res.tempFiles.map((item) => ({ + ...pickExclude(item, ['fileType', 'thumbTempFilePath', 'tempFilePath']), + type: res.type, + url: item.tempFilePath, + thumb: res.type === 'video' ? item.thumbTempFilePath : item.tempFilePath, + size: item.size + })) +} + +function formatFile(res) { + return res.tempFiles.map((item) => ({ + ...pickExclude(item, ['path']), + url: item.path, + size:item.size, + // #ifdef H5 + name: item.name, + type: item.type + // #endif + })) +} +export function chooseFile({ + accept, + multiple, + capture, + compressed, + maxDuration, + sizeType, + camera, + maxCount +}) { + return new Promise((resolve, reject) => { + switch (accept) { + case 'image': + uni.chooseImage({ + count: multiple ? Math.min(maxCount, 9) : 1, + sourceType: capture, + sizeType, + success: (res) => resolve(formatImage(res)), + fail: reject + }) + break + // #ifdef MP-WEIXIN + // ������������������������������chooseMedia������ + case 'media': + wx.chooseMedia({ + count: multiple ? Math.min(maxCount, 9) : 1, + sourceType: capture, + maxDuration, + sizeType, + camera, + success: (res) => resolve(formatMedia(res)), + fail: reject + }) + break + // #endif + case 'video': + uni.chooseVideo({ + sourceType: capture, + compressed, + maxDuration, + camera, + success: (res) => resolve(formatVideo(res)), + fail: reject + }) + break + // #ifdef MP-WEIXIN || H5 + // ������������������������������chooseMessageFile������ + case 'file': + // #ifdef MP-WEIXIN + wx.chooseMessageFile({ + count: multiple ? maxCount : 1, + type: accept, + success: (res) => resolve(formatFile(res)), + fail: reject + }) + // #endif + // #ifdef H5 + // ������hx2.9.9���������������uni.chooseFile + uni.chooseFile({ + count: multiple ? maxCount : 1, + type: accept, + success: (res) => resolve(formatFile(res)), + fail: reject + }) + // #endif + break + // #endif + default: + // ������������������������accept��������������������������������������������������� + // #ifdef MP-WEIXIN + wx.chooseMessageFile({ + count: multiple ? maxCount : 1, + type: 'all', + success: (res) => resolve(formatFile(res)), + fail: reject + }) + // #endif + // #ifdef H5 + // ������hx2.9.9���������������uni.chooseFile + uni.chooseFile({ + count: multiple ? maxCount : 1, + type: 'all', + success: (res) => resolve(formatFile(res)), + fail: reject + }) + // #endif + } + }) +} diff --git a/uni_modules/uview-ui/components/uview-ui/uview-ui.vue b/uni_modules/uview-ui/components/uview-ui/uview-ui.vue new file mode 100644 index 0000000..bcd3662 --- /dev/null +++ b/uni_modules/uview-ui/components/uview-ui/uview-ui.vue @@ -0,0 +1,15 @@ +<template> +</template> + +<template> + <view></view> +</template> + +<script> + export default { + + } +</script> + +<style> +</style> diff --git a/uni_modules/uview-ui/index.js b/uni_modules/uview-ui/index.js new file mode 100644 index 0000000..651c090 --- /dev/null +++ b/uni_modules/uview-ui/index.js @@ -0,0 +1,79 @@ +// ���������������������������������������vue.config.js������transpileDependencies���������������https://www.uviewui.com/components/npmSetting.html#_5-cli������������������ +const pleaseSetTranspileDependencies = {}, babelTest = pleaseSetTranspileDependencies?.test + + + +// ������������mixin +import mixin from './libs/mixin/mixin.js' +// ������������������mixin +import mpMixin from './libs/mixin/mpMixin.js' +// ������������������http������������������������ +import Request from './libs/luch-request' + +// ������������ +import route from './libs/util/route.js' +// ������������������,colorGradient-������������,hexToRgb-���������������������rgb������,rgbToHex-rgb��������������� +import colorGradient from './libs/function/colorGradient.js' + +// ������������ +import test from './libs/function/test.js' +// ������������ +import debounce from './libs/function/debounce.js' +// ������������ +import throttle from './libs/function/throttle.js' +// ��������������������������� +import index from './libs/function/index.js' + +// ������������ +import config from './libs/config/config.js' +// props������������ +import props from './libs/config/props.js' +// ������������fixed������������z-index������������ +import zIndex from './libs/config/zIndex.js' +// ������������������������������������������ +import color from './libs/config/color.js' +// ������ +import platform from './libs/function/platform' + +const $u = { + route, + date: index.timeFormat, // ������date + colorGradient: colorGradient.colorGradient, + hexToRgb: colorGradient.hexToRgb, + rgbToHex: colorGradient.rgbToHex, + colorToRgba: colorGradient.colorToRgba, + test, + type: ['primary', 'success', 'error', 'warning', 'info'], + http: new Request(), + config, // uView������������������������������������ + zIndex, + debounce, + throttle, + mixin, + mpMixin, + props, + ...index, + color, + platform +} + +// $u���������uni��������� +uni.$u = $u + +const install = (Vue) => { + // ���������������������������������������date���timeFormat + Vue.filter('timeFormat', (timestamp, format) => uni.$u.timeFormat(timestamp, format)) + Vue.filter('date', (timestamp, format) => uni.$u.timeFormat(timestamp, format)) + // ��������������������������������������������������� + Vue.filter('timeFrom', (timestamp, format) => uni.$u.timeFrom(timestamp, format)) + // ���������������uni���Vue.prototype��� + // #ifndef APP-NVUE + // ������vue������������Vue.prototype���������������������nvue���������Vue.prototype���Vue.mixin������������ + Vue.prototype.$u = $u + Vue.mixin(mixin) + // #endif +} + +export default { + install +} diff --git a/uni_modules/uview-ui/index.scss b/uni_modules/uview-ui/index.scss new file mode 100644 index 0000000..8fcfa83 --- /dev/null +++ b/uni_modules/uview-ui/index.scss @@ -0,0 +1,23 @@ +// ��������������������� +@import "./libs/css/common.scss"; +@import "./libs/css/color.scss"; + +// ���nvue��������� +/* #ifndef APP-NVUE */ +@import "./libs/css/vue.scss"; +/* #endif */ + +// nvue��������������� +/* #ifdef APP-NVUE */ +@import "./libs/css/nvue.scss"; +/* #endif */ + +// ������������������������ +/* #ifdef MP */ +@import "./libs/css/mp.scss"; +/* #endif */ + +// H5��������������� +/* #ifdef H5 */ +@import "./libs/css/h5.scss"; +/* #endif */ \ No newline at end of file diff --git a/uni_modules/uview-ui/libs/config/color.js b/uni_modules/uview-ui/libs/config/color.js new file mode 100644 index 0000000..56b4187 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/color.js @@ -0,0 +1,17 @@ +// ���������������������������������������������������������������������������������css������ +// ������������������������������������������������������������������������(2020-06-20) +const color = { + primary: '#3c9cff', + info: '#909399', + default: '#909399', + warning: '#f9ae3d', + error: '#f56c6c', + success: '#5ac725', + mainColor: '#303133', + contentColor: '#606266', + tipsColor: '#909399', + lightColor: '#c0c4cc', + borderColor: '#e4e7ed' +} + +export default color diff --git a/uni_modules/uview-ui/libs/config/config.js b/uni_modules/uview-ui/libs/config/config.js new file mode 100644 index 0000000..a3a784e --- /dev/null +++ b/uni_modules/uview-ui/libs/config/config.js @@ -0,0 +1,34 @@ +// ������������������2023-03-27 +const version = '2.0.36' + +// ������������������������������������������������ +if (process.env.NODE_ENV === 'development') { + console.log(`\n %c uView V${version} %c https://uviewui.com/ \n\n`, 'color: #ffffff; background: #3c9cff; padding:5px 0; border-radius: 5px;'); +} + +export default { + v: version, + version, + // ������������ + type: [ + 'primary', + 'success', + 'info', + 'error', + 'warning' + ], + // ���������������������������������scss���:export���������js���������������������nvue��������� + color: { + 'u-primary': '#2979ff', + 'u-warning': '#ff9900', + 'u-success': '#19be6b', + 'u-error': '#fa3534', + 'u-info': '#909399', + 'u-main-color': '#303133', + 'u-content-color': '#606266', + 'u-tips-color': '#909399', + 'u-light-color': '#c0c4cc' + }, + // ������������������������������������rpx���������������������������������������������������������������������rpx + unit: 'px' +} diff --git a/uni_modules/uview-ui/libs/config/props.js b/uni_modules/uview-ui/libs/config/props.js new file mode 100644 index 0000000..6930d48 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props.js @@ -0,0 +1,190 @@ +/** + * ������������������������������������������������props������ + * ���������������������������������������props��������� + * ������������������������������������������������������ + */ +import config from './config' + +import actionSheet from './props/actionSheet.js' +import album from './props/album.js' +import alert from './props/alert.js' +import avatar from './props/avatar' +import avatarGroup from './props/avatarGroup' +import backtop from './props/backtop' +import badge from './props/badge' +import button from './props/button' +import calendar from './props/calendar' +import carKeyboard from './props/carKeyboard' +import cell from './props/cell' +import cellGroup from './props/cellGroup' +import checkbox from './props/checkbox' +import checkboxGroup from './props/checkboxGroup' +import circleProgress from './props/circleProgress' +import code from './props/code' +import codeInput from './props/codeInput' +import col from './props/col' +import collapse from './props/collapse' +import collapseItem from './props/collapseItem' +import columnNotice from './props/columnNotice' +import countDown from './props/countDown' +import countTo from './props/countTo' +import datetimePicker from './props/datetimePicker' +import divider from './props/divider' +import empty from './props/empty' +import form from './props/form' +import formItem from './props/formItem' +import gap from './props/gap' +import grid from './props/grid' +import gridItem from './props/gridItem' +import icon from './props/icon' +import image from './props/image' +import indexAnchor from './props/indexAnchor' +import indexList from './props/indexList' +import input from './props/input' +import keyboard from './props/keyboard' +import line from './props/line' +import lineProgress from './props/lineProgress' +import link from './props/link' +import list from './props/list' +import listItem from './props/listItem' +import loadingIcon from './props/loadingIcon' +import loadingPage from './props/loadingPage' +import loadmore from './props/loadmore' +import modal from './props/modal' +import navbar from './props/navbar' +import noNetwork from './props/noNetwork' +import noticeBar from './props/noticeBar' +import notify from './props/notify' +import numberBox from './props/numberBox' +import numberKeyboard from './props/numberKeyboard' +import overlay from './props/overlay' +import parse from './props/parse' +import picker from './props/picker' +import popup from './props/popup' +import radio from './props/radio' +import radioGroup from './props/radioGroup' +import rate from './props/rate' +import readMore from './props/readMore' +import row from './props/row' +import rowNotice from './props/rowNotice' +import scrollList from './props/scrollList' +import search from './props/search' +import section from './props/section' +import skeleton from './props/skeleton' +import slider from './props/slider' +import statusBar from './props/statusBar' +import steps from './props/steps' +import stepsItem from './props/stepsItem' +import sticky from './props/sticky' +import subsection from './props/subsection' +import swipeAction from './props/swipeAction' +import swipeActionItem from './props/swipeActionItem' +import swiper from './props/swiper' +import swipterIndicator from './props/swipterIndicator' +import _switch from './props/switch' +import tabbar from './props/tabbar' +import tabbarItem from './props/tabbarItem' +import tabs from './props/tabs' +import tag from './props/tag' +import text from './props/text' +import textarea from './props/textarea' +import toast from './props/toast' +import toolbar from './props/toolbar' +import tooltip from './props/tooltip' +import transition from './props/transition' +import upload from './props/upload' + +const { + color +} = config + +export default { + ...actionSheet, + ...album, + ...alert, + ...avatar, + ...avatarGroup, + ...backtop, + ...badge, + ...button, + ...calendar, + ...carKeyboard, + ...cell, + ...cellGroup, + ...checkbox, + ...checkboxGroup, + ...circleProgress, + ...code, + ...codeInput, + ...col, + ...collapse, + ...collapseItem, + ...columnNotice, + ...countDown, + ...countTo, + ...datetimePicker, + ...divider, + ...empty, + ...form, + ...formItem, + ...gap, + ...grid, + ...gridItem, + ...icon, + ...image, + ...indexAnchor, + ...indexList, + ...input, + ...keyboard, + ...line, + ...lineProgress, + ...link, + ...list, + ...listItem, + ...loadingIcon, + ...loadingPage, + ...loadmore, + ...modal, + ...navbar, + ...noNetwork, + ...noticeBar, + ...notify, + ...numberBox, + ...numberKeyboard, + ...overlay, + ...parse, + ...picker, + ...popup, + ...radio, + ...radioGroup, + ...rate, + ...readMore, + ...row, + ...rowNotice, + ...scrollList, + ...search, + ...section, + ...skeleton, + ...slider, + ...statusBar, + ...steps, + ...stepsItem, + ...sticky, + ...subsection, + ...swipeAction, + ...swipeActionItem, + ...swiper, + ...swipterIndicator, + ..._switch, + ...tabbar, + ...tabbarItem, + ...tabs, + ...tag, + ...text, + ...textarea, + ...toast, + ...toolbar, + ...tooltip, + ...transition, + ...upload +} diff --git a/uni_modules/uview-ui/libs/config/props/actionSheet.js b/uni_modules/uview-ui/libs/config/props/actionSheet.js new file mode 100644 index 0000000..d8061a7 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/actionSheet.js @@ -0,0 +1,25 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:44:35 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/actionSheet.js + */ +export default { + // action-sheet������ + actionSheet: { + show: false, + title: '', + description: '', + actions: () => [], + index: '', + cancelText: '', + closeOnClickAction: true, + safeAreaInsetBottom: true, + openType: '', + closeOnClickOverlay: true, + round: 0 + } +} diff --git a/uni_modules/uview-ui/libs/config/props/album.js b/uni_modules/uview-ui/libs/config/props/album.js new file mode 100644 index 0000000..8877326 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/album.js @@ -0,0 +1,25 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:47:24 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/album.js + */ +export default { + // album ������ + album: { + urls: () => [], + keyName: '', + singleSize: 180, + multipleSize: 70, + space: 6, + singleMode: 'scaleToFill', + multipleMode: 'aspectFill', + maxCount: 9, + previewFullImage: true, + rowCount: 3, + showMore: true + } +} diff --git a/uni_modules/uview-ui/libs/config/props/alert.js b/uni_modules/uview-ui/libs/config/props/alert.js new file mode 100644 index 0000000..8f8182c --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/alert.js @@ -0,0 +1,22 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:48:53 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/alert.js + */ +export default { + // alert������������ + alert: { + title: '', + type: 'warning', + description: '', + closable: false, + showIcon: false, + effect: 'light', + center: false, + fontSize: 14 + } +} diff --git a/uni_modules/uview-ui/libs/config/props/avatar.js b/uni_modules/uview-ui/libs/config/props/avatar.js new file mode 100644 index 0000000..c097d4e --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/avatar.js @@ -0,0 +1,28 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:49:22 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/avatar.js + */ +export default { + // avatar ������ + avatar: { + src: '', + shape: 'circle', + size: 40, + mode: 'scaleToFill', + text: '', + bgColor: '#c0c4cc', + color: '#ffffff', + fontSize: 18, + icon: '', + mpAvatar: false, + randomBgColor: false, + defaultUrl: '', + colorIndex: '', + name: '' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/avatarGroup.js b/uni_modules/uview-ui/libs/config/props/avatarGroup.js new file mode 100644 index 0000000..f4a66c3 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/avatarGroup.js @@ -0,0 +1,23 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:49:55 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/avatarGroup.js + */ +export default { + // avatarGroup ������ + avatarGroup: { + urls: () => [], + maxCount: 5, + shape: 'circle', + mode: 'scaleToFill', + showMore: true, + size: 40, + keyName: '', + gap: 0.5, + extraValue: 0 + } +} diff --git a/uni_modules/uview-ui/libs/config/props/backtop.js b/uni_modules/uview-ui/libs/config/props/backtop.js new file mode 100644 index 0000000..80f17d0 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/backtop.js @@ -0,0 +1,27 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:50:18 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/backtop.js + */ +export default { + // backtop������ + backtop: { + mode: 'circle', + icon: 'arrow-upward', + text: '', + duration: 100, + scrollTop: 0, + top: 400, + bottom: 100, + right: 20, + zIndex: 9, + iconStyle: () => ({ + color: '#909399', + fontSize: '19px' + }) + } +} diff --git a/uni_modules/uview-ui/libs/config/props/badge.js b/uni_modules/uview-ui/libs/config/props/badge.js new file mode 100644 index 0000000..44ee7cc --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/badge.js @@ -0,0 +1,27 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-23 19:51:50 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/badge.js + */ +export default { + // ��������������� + badge: { + isDot: false, + value: '', + show: true, + max: 999, + type: 'error', + showZero: false, + bgColor: null, + color: null, + shape: 'circle', + numberType: 'overflow', + offset: () => [], + inverted: false, + absolute: false + } +} diff --git a/uni_modules/uview-ui/libs/config/props/button.js b/uni_modules/uview-ui/libs/config/props/button.js new file mode 100644 index 0000000..acd65fc --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/button.js @@ -0,0 +1,42 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:51:27 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/button.js + */ +export default { + // button������ + button: { + hairline: false, + type: 'info', + size: 'normal', + shape: 'square', + plain: false, + disabled: false, + loading: false, + loadingText: '', + loadingMode: 'spinner', + loadingSize: 15, + openType: '', + formType: '', + appParameter: '', + hoverStopPropagation: true, + lang: 'en', + sessionFrom: '', + sendMessageTitle: '', + sendMessagePath: '', + sendMessageImg: '', + showMessageCard: false, + dataName: '', + throttleTime: 0, + hoverStartTime: 0, + hoverStayTime: 200, + text: '', + icon: '', + iconColor: '', + color: '' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/calendar.js b/uni_modules/uview-ui/libs/config/props/calendar.js new file mode 100644 index 0000000..bfd2bd6 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/calendar.js @@ -0,0 +1,42 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:52:43 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/calendar.js + */ +export default { + // calendar ������ + calendar: { + title: '������������', + showTitle: true, + showSubtitle: true, + mode: 'single', + startText: '������', + endText: '������', + customList: () => [], + color: '#3c9cff', + minDate: 0, + maxDate: 0, + defaultDate: null, + maxCount: Number.MAX_SAFE_INTEGER, // Infinity + rowHeight: 56, + formatter: null, + showLunar: false, + showMark: true, + confirmText: '������', + confirmDisabledText: '������', + show: false, + closeOnClickOverlay: false, + readonly: false, + showConfirm: true, + maxRange: Number.MAX_SAFE_INTEGER, // Infinity + rangePrompt: '', + showRangePrompt: true, + allowSameDay: false, + round: 0, + monthNum: 3 + } +} diff --git a/uni_modules/uview-ui/libs/config/props/carKeyboard.js b/uni_modules/uview-ui/libs/config/props/carKeyboard.js new file mode 100644 index 0000000..af1baa0 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/carKeyboard.js @@ -0,0 +1,15 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:53:20 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/carKeyboard.js + */ +export default { + // ��������������� + carKeyboard: { + random: false + } +} diff --git a/uni_modules/uview-ui/libs/config/props/cell.js b/uni_modules/uview-ui/libs/config/props/cell.js new file mode 100644 index 0000000..425ea3f --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/cell.js @@ -0,0 +1,35 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-23 20:53:09 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/cell.js + */ +export default { + // cell���������props + cell: { + customClass: '', + title: '', + label: '', + value: '', + icon: '', + disabled: false, + border: true, + center: false, + url: '', + linkType: 'navigateTo', + clickable: false, + isLink: false, + required: false, + arrowDirection: '', + iconStyle: {}, + rightIconStyle: {}, + rightIcon: 'arrow-right', + titleStyle: {}, + size: '', + stop: true, + name: '' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/cellGroup.js b/uni_modules/uview-ui/libs/config/props/cellGroup.js new file mode 100644 index 0000000..d48a9cd --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/cellGroup.js @@ -0,0 +1,17 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:54:16 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/cellGroup.js + */ +export default { + // cell-group���������props + cellGroup: { + title: '', + border: true, + customStyle: {} + } +} diff --git a/uni_modules/uview-ui/libs/config/props/checkbox.js b/uni_modules/uview-ui/libs/config/props/checkbox.js new file mode 100644 index 0000000..2310901 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/checkbox.js @@ -0,0 +1,27 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-23 21:06:59 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/checkbox.js + */ +export default { + // checkbox������ + checkbox: { + name: '', + shape: '', + size: '', + checkbox: false, + disabled: '', + activeColor: '', + inactiveColor: '', + iconSize: '', + iconColor: '', + label: '', + labelSize: '', + labelColor: '', + labelDisabled: '' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/checkboxGroup.js b/uni_modules/uview-ui/libs/config/props/checkboxGroup.js new file mode 100644 index 0000000..8798fa4 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/checkboxGroup.js @@ -0,0 +1,29 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:54:47 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/checkboxGroup.js + */ +export default { + // checkbox-group������ + checkboxGroup: { + name: '', + value: () => [], + shape: 'square', + disabled: false, + activeColor: '#2979ff', + inactiveColor: '#c8c9cc', + size: 18, + placement: 'row', + labelSize: 14, + labelColor: '#303133', + labelDisabled: false, + iconColor: '#ffffff', + iconSize: 12, + iconPlacement: 'left', + borderBottom: false + } +} diff --git a/uni_modules/uview-ui/libs/config/props/circleProgress.js b/uni_modules/uview-ui/libs/config/props/circleProgress.js new file mode 100644 index 0000000..b3a9b43 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/circleProgress.js @@ -0,0 +1,15 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:55:02 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/circleProgress.js + */ +export default { + // circleProgress ������ + circleProgress: { + percentage: 30 + } +} diff --git a/uni_modules/uview-ui/libs/config/props/code.js b/uni_modules/uview-ui/libs/config/props/code.js new file mode 100644 index 0000000..693417a --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/code.js @@ -0,0 +1,21 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:55:27 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/code.js + */ + +export default { + // code ������ + code: { + seconds: 60, + startText: '���������������', + changeText: 'X���������������', + endText: '������������', + keepRunning: false, + uniqueKey: '' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/codeInput.js b/uni_modules/uview-ui/libs/config/props/codeInput.js new file mode 100644 index 0000000..cac9265 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/codeInput.js @@ -0,0 +1,29 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:55:58 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/codeInput.js + */ +export default { + // codeInput ������ + codeInput: { + adjustPosition: true, + maxlength: 6, + dot: false, + mode: 'box', + hairline: false, + space: 10, + value: '', + focus: false, + bold: false, + color: '#606266', + fontSize: 18, + size: 35, + disabledKeyboard: false, + borderColor: '#c9cacc', + disabledDot: true + } +} diff --git a/uni_modules/uview-ui/libs/config/props/col.js b/uni_modules/uview-ui/libs/config/props/col.js new file mode 100644 index 0000000..7621653 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/col.js @@ -0,0 +1,19 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:56:12 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/col.js + */ +export default { + // col ������ + col: { + span: 12, + offset: 0, + justify: 'start', + align: 'stretch', + textAlign: 'left' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/collapse.js b/uni_modules/uview-ui/libs/config/props/collapse.js new file mode 100644 index 0000000..c2b9fdd --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/collapse.js @@ -0,0 +1,17 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:56:30 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/collapse.js + */ +export default { + // collapse ������ + collapse: { + value: null, + accordion: false, + border: true + } +} diff --git a/uni_modules/uview-ui/libs/config/props/collapseItem.js b/uni_modules/uview-ui/libs/config/props/collapseItem.js new file mode 100644 index 0000000..74ce682 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/collapseItem.js @@ -0,0 +1,25 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:56:42 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/collapseItem.js + */ +export default { + // collapseItem ������ + collapseItem: { + title: '', + value: '', + label: '', + disabled: false, + isLink: true, + clickable: true, + border: true, + align: 'left', + name: '', + icon: '', + duration: 300 + } +} diff --git a/uni_modules/uview-ui/libs/config/props/columnNotice.js b/uni_modules/uview-ui/libs/config/props/columnNotice.js new file mode 100644 index 0000000..147c0aa --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/columnNotice.js @@ -0,0 +1,24 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:57:16 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/columnNotice.js + */ +export default { + // columnNotice ������ + columnNotice: { + text: '', + icon: 'volume', + mode: '', + color: '#f9ae3d', + bgColor: '#fdf6ec', + fontSize: 14, + speed: 80, + step: false, + duration: 1500, + disableTouch: true + } +} diff --git a/uni_modules/uview-ui/libs/config/props/countDown.js b/uni_modules/uview-ui/libs/config/props/countDown.js new file mode 100644 index 0000000..81e33b1 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/countDown.js @@ -0,0 +1,18 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:11:29 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/countDown.js + */ +export default { + // u-count-down ��������������� + countDown: { + time: 0, + format: 'HH:mm:ss', + autoStart: true, + millisecond: false + } +} diff --git a/uni_modules/uview-ui/libs/config/props/countTo.js b/uni_modules/uview-ui/libs/config/props/countTo.js new file mode 100644 index 0000000..a536cde --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/countTo.js @@ -0,0 +1,25 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:57:32 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/countTo.js + */ +export default { + // countTo ������ + countTo: { + startVal: 0, + endVal: 0, + duration: 2000, + autoplay: true, + decimals: 0, + useEasing: true, + decimal: '.', + color: '#606266', + fontSize: 22, + bold: false, + separator: '' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/datetimePicker.js b/uni_modules/uview-ui/libs/config/props/datetimePicker.js new file mode 100644 index 0000000..4f90966 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/datetimePicker.js @@ -0,0 +1,36 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:57:48 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/datetimePicker.js + */ +export default { + // datetimePicker ������ + datetimePicker: { + show: false, + showToolbar: true, + value: '', + title: '', + mode: 'datetime', + maxDate: new Date(new Date().getFullYear() + 10, 0, 1).getTime(), + minDate: new Date(new Date().getFullYear() - 10, 0, 1).getTime(), + minHour: 0, + maxHour: 23, + minMinute: 0, + maxMinute: 59, + filter: null, + formatter: null, + loading: false, + itemHeight: 44, + cancelText: '������', + confirmText: '������', + cancelColor: '#909193', + confirmColor: '#3c9cff', + visibleItemCount: 5, + closeOnClickOverlay: false, + defaultIndex: () => [] + } +} diff --git a/uni_modules/uview-ui/libs/config/props/divider.js b/uni_modules/uview-ui/libs/config/props/divider.js new file mode 100644 index 0000000..55a8ce4 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/divider.js @@ -0,0 +1,23 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:58:03 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/divider.js + */ +export default { + // divider������ + divider: { + dashed: false, + hairline: true, + dot: false, + textPosition: 'center', + text: '', + textSize: 14, + textColor: '#909399', + lineColor: '#dcdfe6' + } + +} diff --git a/uni_modules/uview-ui/libs/config/props/empty.js b/uni_modules/uview-ui/libs/config/props/empty.js new file mode 100644 index 0000000..fe20445 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/empty.js @@ -0,0 +1,26 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:03:27 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/empty.js + */ +export default { + // empty������ + empty: { + icon: '', + text: '', + textColor: '#c0c4cc', + textSize: 14, + iconColor: '#c0c4cc', + iconSize: 90, + mode: 'data', + width: 160, + height: 160, + show: true, + marginTop: 0 + } + +} diff --git a/uni_modules/uview-ui/libs/config/props/form.js b/uni_modules/uview-ui/libs/config/props/form.js new file mode 100644 index 0000000..41b122e --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/form.js @@ -0,0 +1,22 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:03:49 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/form.js + */ +export default { + // form ������ + form: { + model: () => ({}), + rules: () => ({}), + errorType: 'message', + borderBottom: true, + labelPosition: 'left', + labelWidth: 45, + labelAlign: 'left', + labelStyle: () => ({}) + } +} diff --git a/uni_modules/uview-ui/libs/config/props/formItem.js b/uni_modules/uview-ui/libs/config/props/formItem.js new file mode 100644 index 0000000..4b7c90a --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/formItem.js @@ -0,0 +1,23 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:04:32 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/formItem.js + */ +export default { + // formItem ������ + formItem: { + label: '', + prop: '', + borderBottom: '', + labelPosition: '', + labelWidth: '', + rightIcon: '', + leftIcon: '', + required: false, + leftIconStyle: '', + } +} diff --git a/uni_modules/uview-ui/libs/config/props/gap.js b/uni_modules/uview-ui/libs/config/props/gap.js new file mode 100644 index 0000000..60a21af --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/gap.js @@ -0,0 +1,19 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:05:25 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/gap.js + */ +export default { + // gap������ + gap: { + bgColor: 'transparent', + height: 20, + marginTop: 0, + marginBottom: 0, + customStyle: {} + } +} diff --git a/uni_modules/uview-ui/libs/config/props/grid.js b/uni_modules/uview-ui/libs/config/props/grid.js new file mode 100644 index 0000000..60abeb7 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/grid.js @@ -0,0 +1,17 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:05:57 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/grid.js + */ +export default { + // grid������ + grid: { + col: 3, + border: false, + align: 'left' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/gridItem.js b/uni_modules/uview-ui/libs/config/props/gridItem.js new file mode 100644 index 0000000..1b747f4 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/gridItem.js @@ -0,0 +1,16 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:06:13 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/gridItem.js + */ +export default { + // grid-item������ + gridItem: { + name: null, + bgColor: 'transparent' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/icon.js b/uni_modules/uview-ui/libs/config/props/icon.js new file mode 100644 index 0000000..1d81d2d --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/icon.js @@ -0,0 +1,36 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 18:00:14 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/icon.js + */ +import config from '../config' + +const { + color +} = config +export default { + // icon������ + icon: { + name: '', + color: color['u-content-color'], + size: '16px', + bold: false, + index: '', + hoverClass: '', + customPrefix: 'uicon', + label: '', + labelPos: 'right', + labelSize: '15px', + labelColor: color['u-content-color'], + space: '3px', + imgMode: '', + width: '', + height: '', + top: 0, + stop: false + } +} diff --git a/uni_modules/uview-ui/libs/config/props/image.js b/uni_modules/uview-ui/libs/config/props/image.js new file mode 100644 index 0000000..2552db6 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/image.js @@ -0,0 +1,30 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:01:51 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/image.js + */ +export default { + // image������ + image: { + src: '', + mode: 'aspectFill', + width: '300', + height: '225', + shape: 'square', + radius: 0, + lazyLoad: true, + showMenuByLongpress: true, + loadingIcon: 'photo', + errorIcon: 'error-circle', + showLoading: true, + showError: true, + fade: true, + webp: false, + duration: 500, + bgColor: '#f3f4f6' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/indexAnchor.js b/uni_modules/uview-ui/libs/config/props/indexAnchor.js new file mode 100644 index 0000000..bb20d46 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/indexAnchor.js @@ -0,0 +1,19 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:13:15 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/indexAnchor.js + */ +export default { + // indexAnchor ������ + indexAnchor: { + text: '', + color: '#606266', + size: 14, + bgColor: '#dedede', + height: 32 + } +} diff --git a/uni_modules/uview-ui/libs/config/props/indexList.js b/uni_modules/uview-ui/libs/config/props/indexList.js new file mode 100644 index 0000000..dc6ce94 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/indexList.js @@ -0,0 +1,19 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:13:35 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/indexList.js + */ +export default { + // indexList ������ + indexList: { + inactiveColor: '#606266', + activeColor: '#5677fc', + indexList: () => [], + sticky: true, + customNavHeight: 0 + } +} diff --git a/uni_modules/uview-ui/libs/config/props/input.js b/uni_modules/uview-ui/libs/config/props/input.js new file mode 100644 index 0000000..4f0edc6 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/input.js @@ -0,0 +1,48 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:13:55 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/input.js + */ +export default { + // index ������ + input: { + value: '', + type: 'text', + fixed: false, + disabled: false, + disabledColor: '#f5f7fa', + clearable: false, + password: false, + maxlength: -1, + placeholder: null, + placeholderClass: 'input-placeholder', + placeholderStyle: 'color: #c0c4cc', + showWordLimit: false, + confirmType: 'done', + confirmHold: false, + holdKeyboard: false, + focus: false, + autoBlur: false, + disableDefaultPadding: false, + cursor: -1, + cursorSpacing: 30, + selectionStart: -1, + selectionEnd: -1, + adjustPosition: true, + inputAlign: 'left', + fontSize: '15px', + color: '#303133', + prefixIcon: '', + prefixIconStyle: '', + suffixIcon: '', + suffixIconStyle: '', + border: 'surround', + readonly: false, + shape: 'square', + formatter: null + } +} diff --git a/uni_modules/uview-ui/libs/config/props/keyboard.js b/uni_modules/uview-ui/libs/config/props/keyboard.js new file mode 100644 index 0000000..57182bd --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/keyboard.js @@ -0,0 +1,30 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:07:49 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/keyboard.js + */ +export default { + // ������������ + keyboard: { + mode: 'number', + dotDisabled: false, + tooltip: true, + showTips: true, + tips: '', + showCancel: true, + showConfirm: true, + random: false, + safeAreaInsetBottom: true, + closeOnClickOverlay: true, + show: false, + overlay: true, + zIndex: 10075, + cancelText: '������', + confirmText: '������', + autoChange: false + } +} diff --git a/uni_modules/uview-ui/libs/config/props/line.js b/uni_modules/uview-ui/libs/config/props/line.js new file mode 100644 index 0000000..2c87af2 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/line.js @@ -0,0 +1,20 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:04:49 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/line.js + */ +export default { + // line������ + line: { + color: '#d6d7d9', + length: '100%', + direction: 'row', + hairline: true, + margin: 0, + dashed: false + } +} diff --git a/uni_modules/uview-ui/libs/config/props/lineProgress.js b/uni_modules/uview-ui/libs/config/props/lineProgress.js new file mode 100644 index 0000000..cdfcb0e --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/lineProgress.js @@ -0,0 +1,19 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:14:11 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/lineProgress.js + */ +export default { + // lineProgress ������ + lineProgress: { + activeColor: '#19be6b', + inactiveColor: '#ececec', + percentage: 0, + showText: true, + height: 12 + } +} diff --git a/uni_modules/uview-ui/libs/config/props/link.js b/uni_modules/uview-ui/libs/config/props/link.js new file mode 100644 index 0000000..6c4c883 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/link.js @@ -0,0 +1,26 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:45:36 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/link.js + */ +import config from '../config' + +const { + color +} = config +export default { + // link���������������props������ + link: { + color: color['u-primary'], + fontSize: 15, + underLine: false, + href: '', + mpTips: '���������������������������������������', + lineColor: '', + text: '' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/list.js b/uni_modules/uview-ui/libs/config/props/list.js new file mode 100644 index 0000000..a830c32 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/list.js @@ -0,0 +1,28 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:14:53 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/list.js + */ +export default { + // list ������ + list: { + showScrollbar: false, + lowerThreshold: 50, + upperThreshold: 0, + scrollTop: 0, + offsetAccuracy: 10, + enableFlex: false, + pagingEnabled: false, + scrollable: true, + scrollIntoView: '', + scrollWithAnimation: false, + enableBackToTop: false, + height: 0, + width: 0, + preLoadScreen: 1 + } +} diff --git a/uni_modules/uview-ui/libs/config/props/listItem.js b/uni_modules/uview-ui/libs/config/props/listItem.js new file mode 100644 index 0000000..7fe2166 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/listItem.js @@ -0,0 +1,15 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:15:40 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/listItem.js + */ +export default { + // listItem ������ + listItem: { + anchor: '' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/loadingIcon.js b/uni_modules/uview-ui/libs/config/props/loadingIcon.js new file mode 100644 index 0000000..f4739c4 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/loadingIcon.js @@ -0,0 +1,30 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:45:47 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/loadingIcon.js + */ +import config from '../config' + +const { + color +} = config +export default { + // loading-icon��������������������� + loadingIcon: { + show: true, + color: color['u-tips-color'], + textColor: color['u-tips-color'], + vertical: false, + mode: 'spinner', + size: 24, + textSize: 15, + text: '', + timingFunction: 'ease-in-out', + duration: 1200, + inactiveColor: '' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/loadingPage.js b/uni_modules/uview-ui/libs/config/props/loadingPage.js new file mode 100644 index 0000000..dc53109 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/loadingPage.js @@ -0,0 +1,23 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:00:23 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/loadingPage.js + */ +export default { + // loading-page������ + loadingPage: { + loadingText: '������������', + image: '', + loadingMode: 'circle', + loading: false, + bgColor: '#ffffff', + color: '#C8C8C8', + fontSize: 19, + iconSize: 28, + loadingColor: '#C8C8C8' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/loadmore.js b/uni_modules/uview-ui/libs/config/props/loadmore.js new file mode 100644 index 0000000..67c1160 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/loadmore.js @@ -0,0 +1,32 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:15:26 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/loadmore.js + */ +export default { + // loadmore ������ + loadmore: { + status: 'loadmore', + bgColor: 'transparent', + icon: true, + fontSize: 14, + iconSize: 17, + color: '#606266', + loadingIcon: 'spinner', + loadmoreText: '������������', + loadingText: '������������...', + nomoreText: '���������������', + isDot: false, + iconColor: '#b7b7b7', + marginTop: 10, + marginBottom: 10, + height: 'auto', + line: false, + lineColor: '#E6E8EB', + dashed: false, + } +} diff --git a/uni_modules/uview-ui/libs/config/props/modal.js b/uni_modules/uview-ui/libs/config/props/modal.js new file mode 100644 index 0000000..2ae3fff --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/modal.js @@ -0,0 +1,30 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:15:59 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/modal.js + */ +export default { + // modal ������ + modal: { + show: false, + title: '', + content: '', + confirmText: '������', + cancelText: '������', + showConfirmButton: true, + showCancelButton: false, + confirmColor: '#2979ff', + cancelColor: '#606266', + buttonReverse: false, + zoom: true, + asyncClose: false, + closeOnClickOverlay: false, + negativeTop: 0, + width: '650rpx', + confirmButtonShape: '' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/navbar.js b/uni_modules/uview-ui/libs/config/props/navbar.js new file mode 100644 index 0000000..614a99d --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/navbar.js @@ -0,0 +1,32 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:16:18 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/navbar.js + */ +import color from '../color' +export default { + // navbar ������ + navbar: { + safeAreaInsetTop: true, + placeholder: false, + fixed: true, + border: false, + leftIcon: 'arrow-left', + leftText: '', + rightText: '', + rightIcon: '', + title: '', + bgColor: '#ffffff', + titleWidth: '400rpx', + height: '44px', + leftIconSize: 20, + leftIconColor: color.mainColor, + autoBack: false, + titleStyle: '' + } + +} diff --git a/uni_modules/uview-ui/libs/config/props/noNetwork.js b/uni_modules/uview-ui/libs/config/props/noNetwork.js new file mode 100644 index 0000000..74dba1b --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/noNetwork.js @@ -0,0 +1,18 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:16:39 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/noNetwork.js + */ +export default { + // noNetwork + noNetwork: { + tips: '���������������������������', + zIndex: '', + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51AAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAABLKADAAQAAAABAAABLAAAAADYYILnAABAAElEQVR4Ae29CZhkV3kefNeq6m2W7tn3nl0aCbHIAgmQPGB+sLCNzSID9g9PYrAf57d/+4+DiW0cy8QBJ06c2In/PLFDHJ78+MGCGNsYgyxwIwktwEijAc1ohtmnZ+2Z7p5eq6vu9r/vuXWrq25VdVV1V3dXVX9Hmj73nv285963vvOd75yraeIEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQaD8E9PbrkvRopSMwMBBYRs+5O/yJS68cPnzYXel4tFP/jXbqjPRFEAiCQNe6Bw/6gdFn9Oy9Q90LLG2DgBBW2wyldIQIPPPCte2a5q3jtR+4ff/4wuBuXotrDwSEsNpjHKUXQODppy+udYJMEUEZgbd94DvnNwlA7YGAEFZ7jOOK78Xp06eTTkq7sxwQhmXuf/754VXl4iSstRAQwmqt8ZLWlkHg0UcD49qYfUjXfLtMtOZ7npExJu4iqZWLl7DWQUAIq3XGSlpaAYHD77q8xwuCOSUoXw8Sl0eMux977DGzQjES3AIICGG1wCBJEysj8PXnz230XXdr5RQFMYbRvWnv6w8UhMhliyGwYghr4Pjg3oEXL34ey9zyC9tiD2ml5h47dr1LN7S6CMjz/A3PvHh1Z6UyJby5EVgRhKUe7Kz/JU0LfvrJo5f+Y3MPibSuFgQGBgasYSd9l6GDsup0WS/T/9RTp9fXmU2SNwECdQ92E7S57iaMeJnPQLK6ixkDLfjlb7546RfrLkQyNBcC3dsP6oHWMd9G+V3JgwPHh7rnm1/yLQ8CbU9Y33zp0j+nZFUMb/DHmB7+SHGY3LUKAk8cObtD00xlHDrfNge+Z2ozU3c9dvx4Yr5lSL6lR6CtCWvg6OAPw9z538ZhhZRl6XrwhW8du1KX/iNejtwvPQIDR8+vSRqJ/obU7GupjdNdh2gW0ZDypJBFR6BtB2rg2OVtuub9JcmpHIpBoK1xfffLzx4f7C0XL2HNiYDp6bs9z23Ypn1fC1Y/9PCFDc3ZW2lVHIG2JKzTp4Ok7nv/G6Q054MIvda+bNb74pEgKGtwGAdL7pcfAa8vOKEZ2kyjWuLr7uDh+/qvN6o8KWdxEWhLwroyeek/g4zuqwU6kNrhyZcu/UktaSXN8iNwuL9/RuvVXtJ9PbPQ1vhmcP6t9+47u9ByJP/SIdB2hDVw9MJHQFYfrQdCph84evFX68kjaZcPAZJWwjMXRFpJ2zr91tfuvrh8vZCa54NA2xGWrunvmg8QWCJ/N4ir7fCYDxatkOeBB7an501agXbygVdvv9IK/ZQ2FiPQdi9osGbH+zRNf7y4m9Xu9Me7N9nv0HXdr5ZS4psHgXpJC9P/wDRTx0Vn1TxjWG9LGrbaUm/Fi5meSvcrkxf/Cg/ow9XqAUk91v3qHT97r6471dJKfHMi8Oyzgx1Z03t1YAQVT2MwgsC3u+yXHzi0faQ5eyGtqgWBtpOw2Ol9+/TM+sTOn8L08MtzgQCy+tOHXr3jA0JWc6HU/HF5Scssr4jXcYqfP6V/T8iq+ceyWgvbUsKKOn38eJAYyl56TAuCEr2WYei//9Crd/5GlFb81kdASVopSFrerKRlaoZj9HR+700H10+0fg+lB21NWBxe2lhNHsUpDZr27mi4dV379R9+za4/iO7Fbx8ECknLCPTsTDJ17O33bJpqnx6u7J60PWFxeAcCbMV56dJfQKf1bkMLfuGh1+76zMoe9vbuPUnLsb2DtmOe5HSxvXsrvWtLBEhaTx29+Ma27Jx0ShAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQaEsEVoQdVluO3BJ06ptHL34b1XRjp4Ch6Rq24+kmjG4Nwwg+9uA9u/73EjRBqhAEihAoe3xwUQq5WTYEzp0b3ZnV/Ncf6O/9AvY9wlh/6dy3X7ncN512Zw9BVLXjuAP4np44vnQtkZoEgVkEhLBmsWiKqwsXpjbPBOn3gRfenwnc+7GBe+zsjclvonFDS9nA9Iy/u3x9+vAP3735VPk4CRUEFhcBIazFxbfm0k9fHD7k+v4nQFaPQIrx8Gmyx/GJ0J/t7ez7mw0b9MmaC2pQQgh0/ZSm4g5TwueWWtqLt0HuVy4CQljLPPYnB0depTn+b3t+8B4t0AdBUv93h2H9xc6da0aXs2m+r1WQsLRnl7NdUvfKRkAIa5nG//r1oGtsZvjTgev/kqYHF/TA+AXoqv4npJemOEiQU1Eo2l+G0movBK1UBBPU7s9E1+ILAkuNgKwSLjXiqO/khVtvARH8dxDBRkMzPrF/V+9/BlG5y9CUqlXinHv9mRPXtvuus88L9H3JPv2zD2yXExCqAicJBIFWRwAvv3Xqwq0/Pnn+lv/K+ZvfPH3p9p5W75O0fxaBp793ce3AwIDMWmYhafiVgNtwSMsXeHp4eNXJC8Nf0PAdRCiuf/XgrnWUqsqotcvnl9DmRkCdweX4b9N7+m/ih+mbMraLM14yJVwcXItKpT1VRve+ArC3Qqn+3gM7132jKEGZm6tXg86J7OhDfuA/iHwPUpfUZSfu2L59tXxEoQxeyxkEgjKeOnLxHb4RqC+NY5H3+2953d4XlrNN7Vq3ENYij+yZwbG9jpt9GkBPQ5H9zgP9607OVeWp87cOQtn9zwJf+xDMNFfj+jryPqXpxj8c2Nn7P+SXey70lidu4IXzb0DNB4tr9751+HV7zxSHyd1CERDCWiiCc+QPjUCnsaqmZ62O5IN7N/VUNP48ee7mAZDTf4Tt049iUG4Guv4ZfNLos9UIbo7qJWoJEHjy+bP7fNsoOcnW0A0/aacef8PdG28sQTNWTBVCWIs01OfPj66BpfqTmq732UnjgT1bei+Vq4pTv7HM8Ceg2/o1qLQug7T+FaaM3IqTLZdewpoHgYEjV9fphvOj+OShWa5V+CxvZtpzv/LwG/aNl4uXsPoRwI+4uEYjAJ2GmdG8L0FK2mYa+tsrkdXZy+P7x2ZuHdW14P+BLdank9q6Qwd3rf+ckFWjR6Tx5Q2cP58K9Jm3VCIr1ogt48lO237r3//96YofeG18y9q7RFklXITxPXV+5DchKb3ZDMy37Nu5tuxG4R9cHH6b42QfAzlds+3EPXu2rfrBIjRFilwkBIIR7SHoJDurFU89ZOd680Gke6JaWomvjoBIWNUxqivFD87fej0e0n8Fwvr0/t1rnyqX+QfnRz7g+8FX8Rv8vL3auF/IqhxKzR2WCPxXqKeq3krDTdj2ierpJEUtCIgOqxaUakwzNBR0D09yiqePHOjveyOkpxLr9VMXb73V97S/h3nDXx7Y2fdPkAYbncW1IgIDxy5vM7LZt/hgrnLtxyaBrJNxv/72N+6tuNhSLp+EVUZACKsyNnXHvHL+1qcgNf2KbSXu2bt9dcmS9qlzo/fARgcmCtpzB3b1/Vg5QiuslLowENyDWDn8cSjl98PgdBviu03N+rl9/WufLEwr18uDwLdevLTF1YK3xnVZ2HI1bUxrT7z5zTuXdRP78qCyeLUKYTUI25OXbm4JPO00TBj+6I7+db8ZL3ZwMOiYdG4dA1lN9HWte2iuI2NAVPapC8O/CGPR34Ip/AZIbIMo7yX8G9QMbcS09P+2b1vf5XgdrXaPfiYns9oeLLEd8D1/B7Dp0E1jGP042pXQj7RKf546cmGzp+tv1TRf6YQD35/QO3seP3xow5IfC9QqmM23naJ0ny9ysXwgq98BWc0kVhv/Nhalbqe8kd/Fr8MOSEr3zEVWrwyO3I29hl+E9LUHGf+nAXI6sGPdd8uV2YphIKnE5IyL6bLxk7cn3bdkHHefrpvJAExMZ1uBZmqeNzXtfzUzk/m/ens7LjV7Px+8d9e1579/44l0duZtge+Np5zEEw8c2pBu9na3YvtEwmrAqNE8IZvNHsep5//yjl3r/0O8yFOXbv0QCO05gP0JGIL+fjw+uj91YeRh/Dp/PtCDM7Zpfmjvjt6Xo7hW9ycmJjaYduf7Hdf/8HTGfa3rG9rYxLSWnsloPg7fijZV8oFM2Ja2a9t6EJd7bCztvHP7us4rrdD/r3/7ct9I99jEI4cOiQ3dIg2YEFYDgOUJDFj1e8TqX7cT4kImXuQr5279A4DeBEX8ayvprU4N3rovcALot/TH13T0fXDTJn0qXk4r3k9OTm4y7a6PzjjORzOOvn1kbEqbnEprPhRzwAKzwFLHk05hv6Yd6N+o3R6beG50aPSdr3qV6IJKkVp5ITIlXOCYn4Yexr0w/DO6YXymHFlR0e5r7tsM3fxgJbI6fW1ivTeT+SsYmr54cFff+5Cu5X+hb94Merp6/J/PusGvTE6724eGJ7RpSFOkKPCUZvBPBccoHBet3Rwe13rX9tw/PjXzZ5hKvr8SfhWKkeA2REAIa4GD6p0feRdWBnvxjv2PckVhVfBf4A29uG/X2i+Ui2eYn8n8NryuDr3jPfWSFV5k44UT137eshIP2K7/64cObbheqZ6lCp+Ydt8TBO7vTM5od1+/NR4SFVhoLpKKt410lnE8LTMzo3V2dLznxLkhYgQ9obiVjEDln7mVjEodfYcpw+MAsftg/7qSDbAnb97sCSb0Yei2fqOcbovVqKNnNO8HmAE9Cv3Wp+uoWjt27HpXNqH9WTKR+kBHKqEFbvo5y3N/avfu4g23R45f3WGa1k9ZicTd0zPTf/f6O7f8dT311Jp2fHzmgJlI/N70jPPe4bEZ6Kg4qw0lqlrLiNKBiLWerpTW25PUbkPXZViW62ecHz+4d8PXojTirzwEyhq8rTwYFtRjvpX/rlwJ+iSXugPbMuyKBOHo3geRJtuT7PujcmVUCuPJlhnL/9NUqvMD2eyM5sxMaIlE4n7XML907tyNjcxHQjty4sZv66Z1xEok/xNW5n4uZSf+8sT5m++vVO58wkEu5sR09pd9w/rWyET2vReujiqygrSopn/zKZN5qMeirotKeTyolm7p/+X06Wvr51ue5Gt9BISwFjiGsLl6N6SrvylXDNTK70D4mX071pwtF88w6Jd/DG/1E1u26NOV0pQL71y3/8PJVOcHMzPTWkcCH2YGOaTTaS2RTN6f1fQvvvDK1bdnbO2JZCr1SeRfn05Pa1PTU0gXJBKW+ecnzlxvCGndhFQ1NRP8bcY1/vjS9bF1V26MwHwsVKiXa3etYVw1TNhYJ3TDjQCO42jJVMcez7J+t9YyJF37ISCEtahjGjxkGDr2DJZ31D8h5vUQJL5RPkXlUMM07u3qSGidICvkzzuSlmlZb0olrK9hD9v9JCrPC196JoPMAolFg6CV+PPj54YeyWecx8Vk2v1Q0rSfhFT18LnBmzBRyNalp5qrSuq7kiAsh4SFa7oZ9M0wzI+cPHOjZPo9V1kS1z4ICGEt4lhiCvZrSa2jol7qzPXJPk6nIGbVbWfUvcr7hO9MP97ZVXpggOu6ajplYStj7l1XvbRMXbPAbp6HzSSBlkraNknrvfVCcPt2sHYi7f3pTDb47KUbYxuvKqkKpYBXKBnV869c3WgbDEixAck0FGFFfEzJzbIsO9C1TyrcymWWsLZGIHoW2rqTzdo5dXyykz0NC8l779i5vu4zwM+eHVntGP5jqVTq/6AkVc5NZ3wNH2lVxNWZNIukMSjiNd9z0+CHp5DXAdX4SAg203w8GB5IATtODHzdK8C15kEjhXvNS9rWA11dnfcMDY9prscss48RySakrOLWqODCoIKAgkuVgsS0urtD60haeV1YYVbbtjUn6/74HXvW/11huFy3PwKzT1r797Upe3jq4sib9u9Y+wxe+vh7W1N7jx49v6ZzbffnQD4/Cj1Pfjx54XiBls6GVuTUc9mQsOIO9mPQFdkIRlz4fy5JLm2ZMOqTcJaXIqpcqnixVe+rdbZ3dbc2OT0D0wZIibHSksmklslknvx+//q3PiKnXcTQae/b+LPQ3r1t0969cOL6G7o6E09qgZegdMJBpVQ1DbKCpyUt6oPKz/4NEJalCAuZFIuEVBJd+jgLh4rvAiFqUVGkhJZMWFp3Z0obGSu/d5gSnWmavuO6h+/cvYHSobgVgoAYjrb4QPMUiGtj1/79jBMkLBwiTlMASlYzTkhWCJyTrGAyMOFkst/BoYMmuIIyGJYcMXMMdNwHPhYN1qWS1t6ZLGaKZL8yzFXTr15BooLLMugHMBRNKgW+It8y9TEcJGt4rvcRFCCEVQbFdg0Swmrxkb0+cf2XOzq73kgdFieEXF2jdEUJKQH6SVWQrNjtZDKlpTPp38U58iUbthk/Ph7sN6zg/xudSGvD4xkq6otcnnjyF0XRRTflkyC0IIJE1JG0QbqGNpMNp5xFhRTcZDNoj66988SFm5vv3LX+WkGUXLYxAuXnCW3c4XbqGs9hwjv+a9lsuN+ahOJSCoLjNDAFvVUll0p1aNPp6adTweSflEszPO48oFn+4yOTmR+6enOshKyYhzWpf/jDuuf6x2aV/qNRaPG/1d0gUXWCA0uu7GhMmkqmerEc8KOVU0lMuyFQ+Ylut562YX9Sncmf7Ojo3BDZWbGLtMkiUVXSWTFNuMqWuYG530f7+/tnGFboxsfdd9mm8XdDo9O7rg6NFq0CFqZr5DWlK9qV0fZqGvZchSuPlevB2VmG/hOV4yWm3RAQwmrhEcW64qu4ykfJho52Vp3J8quBYQooqWDKADftBd6HD+5efyoKj/zR8ew/hWXY56/cnFh7a3RCTTGjuMX0SVB9qzu1qfQM+jO3dBW1g6uVSHv/qVNX10Vh4rc3AkJYLTy+WA/8ou9kJjo7bOh+DLVFZ64TEbCyBktxI5PJZj56R//Gx+NdH5vM4vuI+p8NXh9LjU1iw3EZhXc8TyPuuV9wDaaCfBjTM06N0hVWQmHBDzvSDZ5tvqYR7ZAymh8BIazmH6OKLbzv0KZvJEz3ZzEFnEolaEtV2XEaCLKadrIz//TQnk1/EU85NuH8th8Yf4j9gMZUOrNkZEVZCnsbtTU9KW18GqcKFyjh420sd2+j33pg3F8uTsLaDwEhrBYf04O7N/2t7/o/C2FoGnsIy/YGlvAwSfCvZzLOe+8oR1ZT3u/5uvHJC9dGtJlMrfqjslXVHwjpat2aLi2rjFFLjUSrFUjlO0juddXSSXx7ICCE1QbjiHO0/hofbPgwpnDTOR2V6hWNQqGUx34890noet5yaO+Gko3Y45PO7/uB/lvnrwxrWdha1absbgxo1FWtwplXqYSJY5Nn5lU3bLHQmGA/yko0plVSSjMjIITVzKNTR9sO7dv8RSeb/T9BWmMkKv4D+YzBXuljV7yxd+zfte6VeHGKrHTz4+cv38JWmyUmKzSGG5z7VndoE7kz3uPtq+Welvhwm39weVjOyaoFsBZPI4TV4gNY2Pw79mz8KyebeRIH+VEZTaX0sf27+v794TKmCxNTzr/2NOPj5wZBVjjdYSklq6jN69dyKuhqmWztivYob+RTSkPbe/xMdlMUJn77IiCE1W5jq+s4dYEO6mzsYAmvi/+CrH7LDYxPcBq4HGTFVcG1ULLT5orS1ULIkoSFI2cMHKG8obiXcteOCAhhtdmo6gaOh4EWWlkyYU9gvHswXfgV19d/7+LVkSWfBrItJJhObL/p7elQR8fUZnEV70XxPc01sM+xrzhU7toRgZIHuh07uZL6xA3LBaYB+Ar8rBsfz34YX1j+D5eu317QNGy2xPquSE4mDuXb2IujY2AgytNE67RiKFshzuwCR5s9ZSMlsK0QEMJqq+GkBKOF5yFzRoidK5BoFCeMjM/8mG+a//Xy0Li55KYLBRiTrGjwOQ1br4VMBQuKVJeQKVPxMLlvPwSEsNpsTEECmBLSgbHUpwD1YGwse59l2p+9fmuig4fiNZIowrqq/6Xeqm9Vh9JbjcOKvqFtACX7gV8kTVZvkaRoRQSEsFpx1OZoM2iKxxuHLtDcsZlgLzYZfv7m7XSv+r7fIm234XSP/8o5ktWqzqSyZr89PoXPYDTYkZvziw0NLluKayoEyq4iNVULpTF1IaDjHHZmoAW4aep9geN8fiLt998cGYdtVp7K6iqzXGJFUCAi7jdkuapsBJKcPBwgyP8YRyV7B04Q3dDbpY3jg6gupoMNla5U41BbUN9n0sr1ScKaHwEhrOYfo7paCAW0WiWknihhW/0Tabf/6tDtxpIVSIhGnz1dSXUkDL8fSHKi4/lWPId9Kp3Vxqegp8J/m9f14D6DQ/nmb281FwgkZ1Dj7bnSSFx7ICCE1R7jmO8FJJr8jCvjeNrIxFjDJBpKVaSlXhwDw384MyucBoLAGEfHI5ptO6n1YAq4FjorH9IWjUOnFlF3pj62aui3whbI33ZGQAir/UY3XCVEvzgdw/8NcSyGUhSlpVWQrFg2p39xp0JYLyIohaXxdZ2FGofG6yi85/QS32F0Asu8URgu1+2JgCjd22xcsVElPC85169Gaa1YTkRWJKpSqooBiQQzONvq9sRULKKxtzzAEJw1api2EFZjoW3K0oSwmnJY5tcoSD09HanEDztubnfO/IopyUWC6sUmZUpW5aSqkgwgK04DxxaZrFivacCaIdAuH9zaM1rSDgloOwSEsNpoSMenvU93dXb+EE5taFivKElRqd67qrNmsqIF+yjMF/i56MV2JqadYKxXMDXM6+4Wu04pf/kQEMJaPuwbWvPticwj4Il/NnTrdl7JrqaDC5wTUle1GmdWWVCw1+JotjA6PgnThsIdQrXknF8arkJi/+R355dbcrUaArU9ha3WqxXW3tHR9C5dN//T9eEJ3aGdUwP7T0V7F86Mr0VW4mF6o2NTS/ilaB2HDmb8wA2+08AuS1FNjIAQVhMPTi1NgwRkGKbxRxMz3uaJSRzVUkumOtLwo6Zc7aOkVdEhynN9NQ1cyuNqeEqD67mX9TXGyxXbJhFthYAQVosP58S0909czfqJqzdGODVqaG/IUbCWr2p0yukfp4FUtDfeir1yl8IPUGjPHFy/fqJyKolpJwSEsFp4NEfT6Z3YBvOp8MvMc0hAi9hHNQ1cBrJil5TUZxhfXsTuSdFNhoAQVpMNSD3NMTzzU1PZYAM/ProYkg3UV5rHT8lXmA7SwnwEq4FLLVkRI04HM+n0LdvzvlEPZpK2tREQwmrR8ZucCd7hePr7rw2N5PfxLUZXON1zHKz4kb0KnIttP6Njk8tyaimbwXPrsW/yq3v3bhoqaJZctjkCQlgtOMCYCnU4GedTI+NpQ32XbxH7QOmKG5nzdIWZJz8HNkKygqI9TmSL2JSiovGVn0A39c8WBcpN2yMghNWCQ4zPc0HRbr6GEs6chJFnmfl3knZO4/hmII1B6fiFG9br0s6qAeXPp2WUrhzHeXH/jr6n5pNf8rQuAkJYLTZ2kK7Wul7w6zeGx9DyUsZovOodOizosTg1TM9k1Wogpa7lIisOF+w48E/7E5B1Y/cgtdizsBKbK6c1tNioT6X9n3MDcyePOo7OoJqrC6S0+ZIYV+GSOHxvc18PJCxXG4ed13I727axqTp9yk9rX1jutkj9S4+ASFhLj/m8axwdDdbgELxfGsLpoZyqVXPVU1QugVJUV0dC27p+FaaBWWxknq6ceAljTNMiAf/BoUMbJpewWqmqSRAQCatJBqKWZpgJ731Zx9pJM4aK0hXe5vlKVFEbKFlxs3PvqpSSqpbzKztRm+gnEkktnU6/2GFMfa4wXK5XDgJCWC0y1iAR6/Z49iOjY7C5qkG6mk+3SFQGlEP8FFdnygrNFqBsn1OxP5+K5pGHbcBhqhT8fqu/v39mHkVIljZAQAirRQYx7Wj3Zj3tddQjVVJ4l50CMjHe8mqOTJCCvmoTyIrENXx7Uinbm4Gs2PZUqkObnp76i0N7N36tWl8kvn0RaGnCGhgILKPn3B3+xKVXDh8+nPseX3sOlpt13+P4uonv71WeDqLr1ampFB8S1JrulNaHc9rTMxltcpofOeWns0rTLkeIZUHRnpm5YibMf7kc9UudzYNAyyrd8ZLpWvfgQT8w+oyevXeo++bBtaEtQd9s1/ffRsV3I6eDJCp+nourgH04UZQnhIYfWm1o8xdUGCU8/E/bil89sH3dlQUVJplbHoGWJaxnXri2HTvd1nEEcCBS3z++MLi75UejQgcmJjL92ax/gNJPo6QekhVXAbdvXI3D+XQ1Bcxiu02zTAEjKFIdHTQS/S8Hd2/4YhQm/spFoCUJ6+mnL651gkwRQRmBt33gO+c3teNQYin/oG6aKX5rcKEukqqoWN+Ij5vy81v8UATDG0WGC21jlJ96K6wKPpWd8H8jChN/ZSPQcoR1+vTppJPS7iw3bIZl7n/++eFV5eJaOczX9Z2YvM1LPxWpocBHKv8qHHdMqSphGUqqahaThfj40ITBcbLnsDj6oXvu2bS4n96JVy73TYtASxHWo48GxrUx+5Cu+XY5RH3PMzLGxF0ktXLxrRoGNVPPfNtOolIrgElLGYH2wbZqcipdIFVFlDbfGhqfj9bskCaHHS/7gTt3r73Y+BqkxFZFoKUI6/C7Lu/Bl1jmlKB8PUhcHjHufuyxx/g5lbZw+BL7bX4EoiZqyS0T0uM0j1+82QSl+ua+bhxj7GjD2LicwWkLzaarigbKsmDJ7gcTmezMBw/t3ixntUfAiK8QaBmzhq8/f26j77pbaxo3w+jetPf1B5D2RE3pmzyR4/nH+Mti4Wx1dUrCHO0lSVGqskFUnakkpn6mhu086jgYHkWTW3Wbo4Tli6L5gqYHE47vfeDufVv+YflaIjU3KwItIWEdO3a9Szc0ElDNDqcLbHjmxas7a87QxAnX9ljfxcr+Mzs29ykpi1O8iJjoR/cm5o7dnUl89LRLW93dyWmVIip+Kp7pmlWqIvQ8Mga9Gslm3Efu3LX+K008HNK0ZUSgplnGMrZPGxgYsIKeXa/TA61jPu0w0+7xBx/cd3M+eZspD0wbDgWm+RXP13cODY/jWGKuGAb48jG+agNpilbqlKZoWDqDY2AyjtNUlupzYZlKpXgaxIVMNv0zd+/d+uxcaSVuZSPQ/IT13TN34QRvZW81n6HSDdMLUqmjh9tgd//Fi8OHEl3JL3Z2dh3MzGA7XU664llVWRz/QhLjNYmsmaWp/DjCjqIDdlaZTOZZ1/A+fGj7hjP5OLkQBMog0NSE9cSRszuswNhdpt31BRnazM3U9IuPHDrUuG+419eChqU+cvzqjp7u5P9KJpMPpqc51Zv9QntLkFQBEqZluVCw/7nhaP9i376+8YIouRQEyiLQtIQ1cPT8GjOw7vE8tyFtxBrb2MBXdh579FF99g0vC0nzB548ebNHT2l/aFmJj1BPBYyav9EFLaQ+jdPAVNL8/pZ13a8qiJLLOhAAjvrTRy/d0enbF+69d0tzHFhWR/vnk7Rple6mp+9uFFkRGF8LVj/08IUN8wGp2fIcPLh+4sCu9R+F3ucj0MLf4vaVVnChqYWmdaQS2jpY2vd0djh86Vqh7c3Yxm8dudTPxaW0lrn7yJEjZW0Tm7HdC2lT0xKW1xecgHE3FDWNcb7uDh6+r/96Y0prjlIO7ur7TOD5b3ayzt9ylY0Gl83qKFXZsCXrXdOlrV3djf2LBr556JOshLDmMWhPPXV6vav5O5jVxYLUhNl3iIbV8yiqpbI0bQcP85C2Xu0l3dczC0XUN4Pzb71339mFltOM+Q/0rzu5f2fvu1zH+QDOt3uZ0pbVRMRFouJK5qqeTkhVqyBdtdUmhGV5JI4cudrpd5kHiyp3tTU/8s6r+4rC2vCmaQmLWJO0Ep65INJK2tbpt75298U2HLuiLh3oX/95L+0/kHUyvwTieiUJHVEimVzy1UKeWMqv2pCoKEVFRNXT1aHawnBx80eAZj7TwcxdAc5Gi5fiaNnNT37nCk4xaV/X1IRF2B94YHt63qQVaCcfePX2K+07fMU9U7qtHev+xE/7r3cc70O+6w1gxuV0dHZiusgvJS/O7IskRXLs6KCxqj+B26t9a3uUREWi4plbQlTFYzXvu+7tB3EIUGel/L6e3TNw5NS8zYAqldss4YvzBC9C7559drAja3qvDoyg6pwCP+KBZaVOPPjazS1vMLpQKE9fuPnawDB+EqehPwzWuAuSl8LPg90WVxhJJPWQCUmPBAWTBEz1TFUGpqO3wYYvIPgr2az35a2b1/50V6f1e1NTlVcvEzB0xRekj67usu5FmS2/crvQcaol/zeeObfTSOj91dIq28PxiaOHDx9quy8LtQxhcZBqIS0Dhkl2l/3yA4e2j1Qb2JUUD1Iyz1waOQib0vsxKXsAFvH3wMB0JySwtZC+DBPTN5BOCEnhrI1BuKe9l6tIzsVCiD6E0DOabrwI2elZ09aP7N3aNxjheXvK+a1OENa0EFYEyYL9rz072Ju03ZpNQKj7Xd899cKhNrA9LASvZTY/s9GcHoK0XsrakLS8UklLxyl+/rj+/Qfu2367sJNyTS7SuZfneO7ffweBGScu3NwAqWgrTvTc5jjBZmw87tMCfRXYKQWOgula4OiBOQUZ7DZuhrAGdQXxV0zPuCaGnkv3VPGHOpPw7+QPR62OM5HhdNddGOeX2kmCbSnC4mDlSStVTFr4eLljdHV+702vWz9R66Cu5HS5h5hmHvz3QiOxwJTRo2BGgY06dm7OVhewYGAY6s75oD+ZDs4JPY9JyqSCQ7ABqftd5VFM3/j2Ja4mtsWpJQSq6ZXu5UZTKeJnsHpohiYPRqBn04nkS2+CQWW59BK2dAjwS0Y4IHDz2ERWG8Gnwm7iK9W3sFmbvrqGPzw6gW8eTmvTM07XmTPX28KYd7EQ3rjnvv1QFHbPt3zT9DcMPHd+13zzN1s+/hC2rKOo7NjeQdsxT5LEWrYjbdLw05eHtwWe9jl0542u62HZHZIVpalY/yIlP5X3MHYddLLZfy4fmYiBhNuB509vw+rG3tKY+kOwGHLi7W/cS91jS7v4s9TSnZHGLx8CICH9lXNDX+zpWfXuycnaBV2e3e567nAm4973qv0bzy1fD5qr5oEB7KXt0u7B3Loh7yhWVfypbOalh9+wr6U3mbfklLC5Hi1pDRE4ef7Wj+EEiZ+amqpvJT2bzWjJRLIPR3n9riA5i4DZg720DSIrlsrvHXSZ9p7ZGlrzSgirNcetqVp9/vz5FJTqj6JRejTdq6eBMzNpHP9s//QrF4bvrydfO6f1JrCX1mvcXlo98Kembjotr3wXwmrnp36J+pYNeh5JdqRem83O77gxkpxtW3bgOZ/g1HKJmt3U1Rw+3D+zrc89aunagnWzpq6PdxujLz388L4F78tdbtCEsJZ7BFq8/sHBoMPX/I9hyrGgnuDUUZzrnnz7yQu3HlxQQW2Ued++fZmJ1e5LoPB5k5ZpWCPXz+08du+99zrtAI0QVjuM4jL2YcIZeh+2+9wF49MFtYJSlgmHE0g/JlLWLJQPg7RmhtyXsJ18eja0tivsXhj6xy9ve/mRR5TRcG2ZmjyViN9NPkDN3Dz1FW5z9XM4i+s1ME1YcFNpUIrVLHzJzHnwjl0bn1twgW1UwPHjxxPXpztejR0HFTc+F3YXRwxdfdM9W08D0zrs4wtLaM5rkbCac1xaolWOvurhZIPIih0OdVm2haNTfqUlAFjCRnJP4HBn+iUqz6tVa2nGpTe/etsP2o2s2G8hrGqjL/FlEQC5GHghfplSUSMdvwaEA/9+4vjpa3c2stx2KIsfUek2dr+EuXNF2xEjSJx98w/tbFt7NiGsdniSl6EPp84O3W/Z1oPzXRms1GRKWdCJdeCIlJ+vlGYlh997r+70+EPH8NHJEtLCauCph+7bmj81ox1xEsJqx1Fdij4Zxi9AT2KSYBrtslgxhOD2gWOyz7AstFzx6zFHj1mGobYUYAgC9cHge3ddK5uhjQKFsNpoMJeqK6+8cm0X6noXiWUxHA8WxAdWNyQM45HFKL8dyiRpueM7jllmMGpnjO+1w9fNaxmXxiogaqlR0jQdAkeOBPjczrnOiQ6jw88ESSOA6KT7iQzOHEvavu1pZsLQg4QPP/DdZG9Xx/vWrOr+mfR03SvtNffdxleAQIgvTzjBT0w409Mpu2faufZy+vDhw5WPMa25dEnYqggIYbXqyNXY7i/jCyvdfmaVb5hdVsLp9LJGp43j1/1A7/RdvdMwPRzEboRnLVHe9vEvL3eXBOB4ZMta22H+TiqV2LJQ26u5u6Bju44Z3J7O/Lvp6cwPmBanOwQ4uNHRTWMK21bSvh1Mm642nTWCtKkH07rnTE72aOO0XZq7bIltVQSEsFp15HLthg5J/+aJE12m3tVjOPYq1/dW4cTjHnwMYhXOce8xDd3y/PJW6OpMdsTRVy4iK/rKMR/jwvz825VIHFzT3fkx13UW/dnhRy3GJyeeHEs7n1XNibUPFvY6vtGDw5vV9w0Vofn81qGhZfDhi3HX8SfQ/3HPMse9CWcCX0gel2OIFJIt+2fRH7qWRaYJG85NxldGzV4tGayFSLQ24+q9ULyu9gJfMU5ELTn6wUISTl03NHz1KzyiJLqmX657OLLdSJgoXTO7cBxyN172blier4YCvBsFdSNXV2dC35tKJrbzfPfFdjwvC/qs9MSMxxNRsSqmT6LhUDQHE+jUBE7UnATXTuLsrRn01K2l/x6+qItiR3TNG8V59KNB0DGSfNXGUXwJY2Gm+osNhpSvEBDCasIHgVLTt75/aQ0MnXpBNb2QgNYEntfr4wu/nBYpKQLtxtdwAh0SBX3VDe7nM/Ha5vf1Fb/CURS2bCTAWWuxR229qRsbQQQbUed61LfW14JVKKsTJ5sk8WUcHbtlNANyTOhgcmAGKH7p3m1FWpqtuZCu+LByVdKHVMjpKEQrBwIW9tnpXOIH+QTDSH/D9f0bmCLewDn1I4HmwtAypPDZ/oe9oXKf/aMPsWxSs/RR13FHrURiZE1gDR86tKHEdCDMKX+XCwEhrOVCvqBeHNaW6ui11/mWDtLQ1kEiWodXE4rwYgepAPssTPCMOjIdAk94TZ8pMZjch8HjDorGFUTUAwlkh64be0A9/ZCatiDZWtOyE7ClQmIdJICJFYhA+TRV4Fo5/QIHiUvrTEbkVRCxiJfsSBbfYk87OTExXxdazY5yUgiRKfpHQ1YSkONmAZY+gV4NIeVFfCXoLNA5h/Plb5LzWAyzF+IVXdNnvO/6GcsyhjC1vmWZ7s2pO3fdOqzriy9asnJxZREoerDLppDAhiIAEtCfO3F5rW0a6z1PX4/nf53nG5RqqrpieSnULEVh8cx4E7ugH78H8tG9eP/24oVezY+pkpA8b/abhPF8le75BqdsXUtaFeaTlTI2IByEoU1l8oq1mkokcZHElIRoWmpejMMCMyCvQXyy7JjjuUcgOl4tLCzCMpTHgFpcgkViX/dH/ax2Szf8m2Yqc/MN+1r7BM/C/rfCtRDWEozSkbMjq7NTY5t13dqE6dhG3wsSqlp+C9DDi0ifLrqmT1f6BgUaPjiHN0lJAGAfvpWcI4XjiHIMF6ocO/EjmMa9HeelQ1LT1PRpoce/sJwOTCQtc+kfGQp6Uxl+9JWtmL+jNEaJ0gKBgbsygR58B4sHfwV5aliVWg3vCHv6ymHcdG868IzrVsK6pnd71+/dsmXxbD3m3/W2ybn0T1/bQFe5I8euX+9ybuqbXMPbDA7ZCKV4uMOecyz+9OfmWvj9x9zEw6JW+JuOX298WhE6qtwLEV3TL1tb/AWj7sqwfqaro/sdmcyM+vBp2XzzDEzaBiQsNH+e+eeTjQ+ohwqnG0BYhfVzNYKrkOmpyauYYH8KvD8G6RPBszrC6Jq+ystl0ghzXEZjR5+O4+iZwTh+eG7Yqa5rq/3hGzzTSkXKn4YgIITVABjBP+ZzP7i8ydasrZCetuCHvIvFRs92SEdlpnCYE2LOQi12OA7RNf1yjrphHIyE9yOXPnfNMDg70DpdTf8DWDKs5rRvMVwChAWrUgh21HzllD0NrigqlxKVC7bKQuOOWeGiuI7OTkhb6T8C/Xw3xkel9cXxj6eIxiY3Hhx3X9dHsWJwDaa3l1+zd9Mt/F4tUk/ijWnP+/DBb8++LWqvnh0c7NDGta0pO7kl6zpb8AJzEUr91kYEFdeBRCt69Nm4+AsSl6jwjVGckY6VwPwUpLhLURx9xliWvxFHi/w+zB0SWCnLsVpxnoXesSI2ngp4zmRJXPgf/0IleGH51R6uwjeX5MR76qtITh7+8N9Cp4GF7Sm8Zl1s35pVXVomm/5c1vG+Wm284njHJeJq44/FjixUAld8w7uijW6+xo3MhW2S6+oIVHumqpewglJ87+LFtcFUcqur+1vxwPcZJqYPMOyhXw6GKI4+4/GwQpjCBhe+6XDIpFb06PM+np5hhS5eXzw9bLJ2pBLGv4Fe36BU4kA6IQGw8MUY6MJywVeqDs54Z69zrWdY7jI3G1ZtUiSV6zzDI3IqLLew/wu9jspl+yywrA1pEed5QceXPT3jBb/DLrA5ua5UHZ/4eMTbFx+fwvE3DJO8fANrjlctL7giJhRx9MrfR89R+VgJ1Y6currONuwd0FNsxwtV02mPlWGLy1TxlPHf6Hh8PH9xesvw9yRM+5PIRT2ZIgVKKZxWUY/PT8aTFPji0i3m4Ed1hDWV/7uY9bNGtiGqAyorJRWSqCgdkrQiR5KddrwPlsq8xfhG6efvx8dvtiQczDdmmPaldDBxSVYeZ3GJXxUMWzxq5d4fPz7Ym7X1HTAL2A7NqtJHEQ3qtCPjw3LoxB/v+OMZ5VVzR5aHWRuErYA+y4uu6fM+Xl9J/lh7bFvbY+vmv0bWos9tsXAWSLIiaSnyApHxJz6SbFSFuXTw8i86r5vVRW1m+6IHmUREAuI0lcREP5q2ztWPrO9/YK54xsXHI56+cePvj3qBfimZNS+J5FWMcrjptThsRd4dPX9+DcwEd5iQphwozfkCwJKaLv9ewHYKeicfSudwShcnJDBBOD3MTwGRO0cqLIj73jQTaejDBYaPHTBgJ/i5+HyYijd95sFhRzkzB7yL2IrCtGwezj9nOQVTUlfPwiicifnu5J0qHHd8mXHIG6ZD7JQqIk9kJK6QwAokMWRUhMaSeJ0vcfaiXNhs7PyuwpYV51Vh+EM/Pu2M9GckpyiOuZm2Wvtom+Y4me8xPbvIIujzPu6Wbvyt1ejL3U7Sv/v754ZHsORwaX3KGdwiJhO5pzY+Mivk/urVq52jTnIXlEc78LKu8qAMx/G8kHhyOicosz0ovM3IrIDKb15HSvDoOoqv+hMLYCOWI8ash0vmufryZVcqLz4u8fym3ov1xT/EVp4UDUTn4/iS0xW+sZTMojASmLqGp64iH4FRXJQ2TKj+lv7JVRTVxwQkm9APyaboGnGMzSVR6VR87ipsVT645ovOzi5tamb6zzB1/nqzjz+s9YetwLioZW5C8jq08K9+1IxS8yQsfF6ap1WL2BK8VOaJc6NbPcPrx7wJ++hmHQUPvOaQgMJ3ETtVlERDP0wVsQ19uPgcLQyt/Dc+p4jlL6k/1xa2qVyh5ApEzEoErm/DsPOTXV3de6anq36roFyRdYWVbVSshHJEMt98saIXfIu9koplYZL6m/hUz7kS/Jt0/PE8+Jj6X/Y6k+fv2tA1BKIvB/OC8WnGAmp5dpqx3XW36fjgYK/upXbhFd+BrRlqn16MfkrspkoC4hnirYjbUVWzs4rHx8uL3cerjwt0TA4RcBcsuX8Rn97q54okVsCKJJ9YkSvy1gJR4aOtnAr6OJP+L13d+BKBKMEzHhAfgDh6yzD+vqHjTDDvYpAxLqwEfVdbE9bpIEi6V27tdLP+LnzPrWS/XrRTnz5d4e79+LNY7r4kP+Z7Jv7z1LyPL0B4Tb+ci9cXLy+eJ54e8Rw//rqqcUR+HOrgYVprJbBl5E2w63oI64J7k8mUDZLGhmAXs19ucVkxP8gKQu4ptCxbMy2TW3KAGI4u1P207ztH3CDx/7bL+Cdse8h1Zy5ev7Dp8uHD7blJuy0J69TV8XW6l92Dl3cbLG6g98idbhDgdANcY1ZY9o2N4mpNr96GRf1Da3Wui0RW69F1bWslvp81LD2xDTOGu9DhQzBc7AcYfYlkAqo6A6ozqHNBYJTESGitTGShsp0qQSxT4AcoPJQw0LBlEPhBFakHDjoLvY+XgVIyg7WK77tG8n9pvpHXBbXL+OMBd7FN6KLu+uf27esbX9RHdIkLbxvCGhgYsDb3v2a7obt7YHakpKmYiqgE2ioqJbzIOszXcSov/DAzRRNehyJKvPx4+igv/ZLKEaCkoZxUFMYXE1I8f7Xyq/UHp9CkAlfbCF3NdlhS7IQguA0N2wiJYy1ktC5IISb1Okr5jSYruy2SGlYkIkKLSC3yy/WrUWGzSnjaTUX/QEhYQuNewLCdwBFKRkpOuAfr4sBnwwfDg6B0MHagORhBHNqHw5WxTwYav6lAt/42MBLfrYZXHO9w3Ftr/B0Hp0pY+tkD29ddAz5ln8NGjddSlNPyhHV8aKjbzAS7Dd3egRcvgRHJWyrHASw9Pyp+vlSxEluH0jWAGQF9VVZMpxHVRZ/xSKQU4PR5Xy0+/sLQZCFS9DN/XKtSeh5WrL2x+sMyZv+W67+vwz5eC7oDx12rm9pakNg639B68XL3Qh+2Bm94DySxHhg0daBHSQhiCbyyyMS9SDi8RhEHyYP1qD9qak0S4VGn5VYrSTRKEkKHWYYiHuQmCYb/YKYLqS+3H5LYckxJmz6qhSYJ5yNgzgtuclESpncBfN8Fj3lgJdCSGpHcGECoxrouMoHjzO+4evLLMB1VKxJV8Wyj8Q80Ix043jnTu32hlTdkh08Yn7UWcnio9Qs3pzZm0lN7LCOxIdIZxbuQ1+lAVFFxJB7aMeUIiPkiPRPjo2v6dPF4FVjHnxi/oQK0Az/bymf5uI7ayGLj6eM63nrbF5VNXzV7nv3HViQL3JAEaSV1z0iBNJIgJBCYkSKJYbdjEiSHw7a0BI5s6QBBbINUswMUsQ6E11UojZGccA9dcZDBdQY+TgyFTgkiEKYyIBvstAQzIRk8cBJ+A2j4gZFDFWAqjAp3V5IhQYYwwUJ57ByS0QINzMYK8FyrRxt3KNbXb2qG/UVNT5wDyCt6/A0boGbdqzPA4tD21SPquWihPy1FWHjQzYs3xnZkM95ePIZd8RccBx1xez/UPowp46I4+uVcLD9/8Plq0Gfy6Jp+uez5uqPyY+UtNN5DuVQc06drpv4bIDXsjtsMpdkOSC79QK4Xog3PzwF4IBNCBiIhpBSpoE8jioqWaM2KCRuOqwLXgIQItKIe0lCYD/lZjoqgGIo0+J++SsmMKA8eqQ21qHuUh2PfzQHN6vgG6vVK8GfmQhcbr3Yff+AEi3rtdCtNF8u/eIWD2ATXx4Mg0XH1Vr/hm7sDQw8PvyvTrriKWocEE0C6oM/kJRJHrAykgj6WGlq+JUifu6YfS6pu4/UVa6AgQcXKi78ApekhcWFBwMstEkTX9MvVHw+Lt2ex+4+Pg62CxgsHEwZbAdgWIJfA+ICkfDRYtyAwWWB7Ay8F8VT/KB0bOJ4Gx/CQfUKSwZGrJJs8iZHYgB0zMB+zk8hopQ8hEcEog2ERASIBAOL5fIrVIKLxXKtzKPZLgZUckvGf+/nH5HsK0+Uz3316zeAjj3D23Lwu90w0ZwNpiZ72UnvwfO/AXIFnXfLBxLOsHn6yiLqmr3oQ04LHX9hq6TFHI6txrlYWkHj98UT1lh8vryR/rIKq6aO204drdP8hRWF3itmLUw42QnW1CSTSA2IAIXkWOBYKLWw8wjVqNkEaFqjFwLQNJhWI4ZiFoiq6QX0SbsEo6HMoWVFCYprwjw6FP65BXCSoXJwiOwpnFK9A6yiWkQhRDwA9XAfpwLS/AqnqSKP7jwapquiznXFXMn6x8Yg/X/HySvLHKqiaPlZfvf0H6BloAM/v3tpzHkJwUx59Uxb4GE5Lfnt2ZGS16SX3+F5mq4llfegtwnaSR6J5EC8hPUV6IDaS6aDnoZ5DpYe6AtdgOr4pyhXLNPH0KKCo/DDP7N+S+mI6qHzbQr7AbdgW+iylWn0l5cf6E29ftfSN6L9lGl04x30tOtMHklmLhxpClW9BL4S1T+i2uNPRp+0FflD0AN9A9LHnmHGBBfJCE3QL9ALiguoJqiu+64gDzWGIIAlhzhaSDsMV/yjJi3BxyY9khP9BXBSzEMY/AFORGMmM1yyKZfmm+ZKuJf4uMHV1THEj+o+S864E7zYd/8Dliqp2MamvPbt9uw4dY/M4DnXTuMuXx/scK9iHLcbryzfKwvOJBSGNPl10Tb8WV0xYyMFymDdXXv46Kq+ueChJQI4WlSUqf8StOf5CNdXqr9afxe8/Gm6AoLAqGKyCGLSG350ACFzKM2FvaeOseEhFOsjItdQ2S6wYYmkOdl2+CfLBvmpIV55vYY2Qn6uAxAWC40zbhxSmWArcQj0TSIiSU37mx0kgVesgLereOSz8E5EWJa6Qzyh1hZEcO7xY4Ct9WLfNvwa+5xA2h6uGP6vMPxMsZ8WNf0Gf+cOCw9usq51a5+kNG9Sn1IjJsjoO0LI7EpVra/vxhPdFs7JyjYriohlbTAKGxO1C6oJEljseOLqmTxfPX66OucJK66OUNzuDjK7p05UIbGwX25I/vrj4BYrnD0uZ/Rtvfzz9fPsPIkgkbL0DZNMFRVEHFEY2ZCBTcwMLdfCsCCVN4SwpE9YG+ARNgD24IDHYSYB1yNCYDkLRFoC8oOUG40AKQx5IYyAmlQ6SF7dDoSof0hbJiApzqLs43aPc5UG+AvVQ/4T7nGQFQiJ5kdbAkmgH2Sz0FaWB4gLrad22v4nmuvPt/yzCc1+V4t0e4z93r8PYwDCvNANxLSthkai0jmCf5+jq6y6Y4SkjTfoKprgWufj9Dg3AozBmiK7pl3H8WDH3u0YfLY6u6c/HVS2vSvsxoygyTF2q/qNenEyjJ5NJPYGPRidME1M1/JYqwyoNq32Ihu4J0z5M+WA2DoqwEI9wfmEaEhQJzPNsKNOh0jJwrfRVJqbnNOrC6IGwQFzgHiKrpCuq2kE+FizrMXWE7IWCEKemg7hSiimOQchNIC3EchqpHlBO95TshQThkwF5TL9k+Mm/MZLGzVo3AlQdLzagDle1vCYd/wU9/5Z5ZcyZPnNow/J8ZHZZCGtsbKw3rdn7nIzTx42o0WfP1cPKuYJ6XPFs5q7p8zmKx5v8cdcxDeMPOR1fj+gh4X10TV/dukiC+nJPeLy8eH1hrtm/UVvpKxcrP2oL/dlcs1eQ9PCeo73wGcp+R2Xyvlp74vH19B9EkoA2CYKUlcQqJCQj6vkoyBjh/IurcJiy4Zxy2FMptRBO7sK3kClR0UYUZAX+wMqfC1ICiYHMYBsKSQsSFKaAUEqZLoiK00ASFsgpN0UEUWE6yOkiiArE6NmUb91OWwAAEuNJREFUszCNxA0c/uBoF04W86YOarWQAYjGmHBBEIkUiXEqib025hNmInWknv6zKo77Sh3/RvcfSx5Xl4O4yr5Y7NxiuEEQFT4uvs8yrF5VvosX28LLS185vsiRHkc9YPiJtrCbJIzHyx3gJdfpl80flZWPR6qIxJghus7xjSqj4E9UNn2VvN76Csqq6XIR+48OYEeGlcAaXhLfQwxNQcgQEI9IErOOxBUuCuDLz9Arm5iyOTaYy7Jty8hAb2VCm43ZmwnwQTbgFpAWyA4SGEKhaMdgYNpngKAcpeMCAfFjYGE4yAqco3RZ0LorUqOkxVkf6AgzvFBPFbISSsOUD+WRrWijpcwbmI4Gomj4yxAIv4bPVU+q9sfxk/EP36UlfP49N3vNWr/m9CZdX/zzjDDofAoW3XHVr9NPHdB8p2+uORl/mjFLUktMbBTtkSJbpLCRxYyD5OpJps/4+DJuvq5IIgoLqfi3pLzcRuloM7QSzKImsBSWG80LVKkxkSvOkFHaCjL5QvrPN9rwvaSVtEg2ICmQCNRQkGjwnlOpNktMxdds+GxcRFrIyCmhTQMEUJjl4qwtzPbAOVC8o0DUZroGiMmBpEUfRBZ4DvRUJC4/1GOpij1ML9XU0PJdFxIZGsOpJkkOQ0YdFh5CPodKl0WfRqQkVUhTIEf1iN4GkdJU4Rx/xsJfHkpfMv4cd+IAUJb1+YdkfSU7NXp6+/bti7qquKiEdfVq0Gl2TO2DonYzAcUTCv0slCB8FuGia/q8j7iAPl30aNIPHVKq55w+00MvjFLo05WmV8H5P9XLzydVF/H0xbGl9UGfjm226B98po2u6fO+0f3H9M7SbT1h+FoS00ybSmm+5/RZHxzbwWvVHtSvNuLRR4BKl0vPtHRhWh1SESUsNBkH0qjvNiAx4MA1JDBc4yBmTPmwJArJCFM+dA1SE5XsmFIqRTzKUrZYkMio78IUkauFoW6Mcbin1GWrOR8nqOEUEUQFmuK3ZdEw6NFg92s9j3XLp0CIsAuS8VdPkcKhCZ9/KAc81x/c3NdzFjy6KHZc0YPNh7VhDg9jYnh4co9n2dvx1nLalys7Rimx2xLGigfEJBQ0Xr149FkBVb04BQiTlPAFbTiDxRGKM1pJf5AgarPKG0sQu413N07hkCANO5m0fSebtCwziW5DqMISHTRMJCDF23inYbmsauNCHq+Vn1ta5dErzKN8psP/RiIXVpAegKJQ30Y06AQSEXdAIpdL0wbTNsLpoSIeCwRJHZYBpTusIFAIlPC0iqL5AxoCcmLPQkkLdITRCc0dSFqQD1A51g4pLOXmhZCwDMO2BpH9q6ZtDoU4oKQIy5yEynFnv+mzw+0+/q3Sf5yT4aYs89zq1alLIK7wYeQANcCpgW5AOaqIARzxcudrXrMTz+cuFAxBI1Rw06eLKz3xsnDikt+Mmr9mWBlXrbySeJAlTt8MXJImXHRNv0zx2GpWZ3r0KKqzXHlRHH26+fQf+mkbg56ADjppUuihMJl7BEhGtmnj+4Phj1lEUAzjaQcgJkzcqPPmlI/yjdJV8Trf/+hbeYyP0uMS0zSVF8SEaSELxkhR6a7IC1IVHkNMBWEkCljxYQ7YXgWKrDCHw2ohJDDKSkr5Tst3TANBp7DdgkTFKSOpxYMtV2i3hXQoJjwbBo3L4oibAajdXmSbCl01PEvi6x3PetMvwfi3cv+xHpPRk8GZvo6Oq5y5FvZlvtfqQZ5v5igfH7iRdHqrn/H24McyEb6ejCUxkCwqEATi8JDNKtWRIxI6wrLj+aOyQgIqLT/KTZ+OLYnCFGHE60PdSgzIgVmcfrbt5evjYkB97VeNyv8plx/UYoChElhYgB7KtD3PAUWRpejIVNzNAjNzyDuYRqnrMF5dIx4CkTrlAJQRps2FhZIX5lqYwfFLOygTBeSmkUhDEgNvIC7MR5ML6JhozoCpn+858G1utbH4j7BRT0Z9VlZzbTyOKJCKeCjkqYbkFBJh+DXCPVcKuXKIFURlm8WBoZSFOBCYmk6i33ioT+Kw1CegEMspcFfe+M8+rRySNum/YUwm9I7TPT04NWOBDg/nwtz16xMbEp3mPswIOuI6G7wBSlynz1pQWZEIP0smIcEEWN3QsfJDn+nj9FFSPh73wilgdE2f+eOumo4pPqWI2kI/LKu4RVXLq7H/kJopRUFhnkj4joNT9KC/BlZgAIVD1I+cwASVUBgCIsF1KEQxJLpGPKHGP5LYrAs5ikREnmJ61KF4K5cG1+REVS6HC1JauGroYYcOrLWUEp6MSF0UpoZgK5hV2dgEzeNLYbMBnRQZEUPnOwGMT6GOp57Kg/0WTCMYjnsQHpDmlJFTR5IcNt/alvV1PdF5NsKcLSpGG03L6QcjnWDpeIXqgFYb//A9wGi1+fMPDeqY7nae6uvT530KKp+JebkhHJyX6Fqz33X83tCgRr1d6gXBH+XnFtEwDmEVMBfAtbK7UvHxVTb1gGLQokbFVBZMDtUJHmT+dsPxmqSRU2nkrxkWxhfbOfEVwLov4sIaonSRr1qZy6vy8xliPbn+qPjYHxSm6mJwdB357DfaVtJ/BMLeW0/ayVQSR6TA5AB7h8kwmFeRrFBUSFYkJk7GsM+F5SuiCQmFBEriCskHYcxfEM9ozBjBS/yaKD//rBzndjD3BHswAcmqwFdhOWGugCw5owwpEt9sxMlVGWQEK4GlcAOi1XAcL6eLICfdcMFmNDnH7xdO/YTCHTkxM2B6EiSPbuXmHrZO5eJy4Iu6lfo2Gu8orFfA+PM9UMjnHpBIx9v+/Q9Wm8nMfcMTE1d7u7vP4Ec6fzy1wqOGP3xI63JHjgT2/rsy/boTbMP0pe78dVUWS5wjK0VUjIqNN3kA62ZYeIcfxofXDFNFUZBTT4W6m71mWBlXrb4yWSoEYWh0jVIUdJEmzA6o18mRDN7dCplCEkK8IiP4WRAU9OO8j5wimZB3SAhKYlJEphLkJCaSEP7PEdxsfVG5UWFxP6qPPngTlvBED6IWLN8dTPmg8ocFPPRXWBdlFWqqCEmLlhAgLRtKdLaAkpQNfRUM6DUQGOUiTimNEaT7FvRVw/F6K91XG4/mHf9KPaovvJ36jzfSS1mpc6mUdhnvhZL4a0GjZsKBKK+n0+kt0AHvztCAsIzjeeAeUKVPF1l101cBWCICxcGmcPalUeHRnyguIsJYej79fFnpKxdjrKhu+spVK69Ke+OW6SXlh7Xk/8b7D5umJKY6nUiQAEmp5ZKoD5Ay8kTFzcAsJIrL+ZREYCWAaU4ubXRNP8wfpuSuGubHMwCJhSuGPCiYJIMw5GV6xkfY0Wd+WoPiBAlEhvnzNluw3SKZYTkQHIQ5J1RQDg7Lw/QQGUIdFp4wcC9KgQ/7KkxjucEHROVmc3ZaCFfEjMxUvlPvBZ0WhT1Q1zG06hQKyGPA9qEh4bPRJuO/0p//WvoPyXpa77BPr9L1mn64QiJRT0vlP3jg1oyn0/th1dnN6VOkQyh8wVRuPpLUH9GHi+sckD4vLaj43NSHLwfv8cKjbGxdgc97JUpFpIRbpovKYHTUltkpHYkyEqNYf1gWfZU+Vn+JiMZERS4qKyTAMv1hmwoItLT/aL6OL9cn8A4mknhDkR5CUuh43ExhAXjnIQVxRQ9UwnU1JM73meHISINzlY/1Ir3jwNQBtui5IpU3K2mFZbEUEhgJiHlZhkqI8rws7hPFxBHlZ5romu1CGRSv2HyQEQiLPkwefJcSk2o0mU+F8Z46KswbKd8qvRUWiq7BsuoYlF/q+Jd839p4/KNnFHhw+Fbc819r/y3dHO7qsk9D2lLPBvEq59SLXC6CYSCq1OTk5F48g+FxLyQSvvyzhFK8taaYL1ACiYdkkSOg/HVO4irmAySLlR8+yHy5wnaWysTF7YmnRxdyecMXFDcxx3KjNCUEGUtb2r4Iixwh5qebxEG58v2Hkh0ERqlLp5kClNLkngLSyF8XExrZi089SYbFm9DRg1FCbEKyoxQE8sqFkTOgTwrDVIPCP/k8qpRcGrxMEXmxnpwjUeXbhjpgA2bBNsp0HPQWOiwNOnddw5YcNIdSFyzTlUKehEbrLDxDNn7osjCXPw5FO22qgPfKHn/pf8XxxxetvSvYlX8BxBVKCdGDmPPDhz0W+Oijjxof//jHt+Hh2oko/qKqFx4l0BJQmQIwS3RNn/fxZXqGFbq4nQzimI9tKFs+S1S1KJ9XoQkEfUQwtKg98fSzefMMwmx5F28/IqK2RLjM2b54/gX0H0v6+IiDZSVgHJogfYWNzDMUpCtsUkKg4pKIUJAsnNTlkjNWzfBCPMOhi8JAiCSqPBmyMFVQ1OdctQwLywNZ5cPCpDl80D6IhjzBASQF0sUeREpSJCyE4ceSpJXbEO2612AHepaTSRn/YrtEAD3n8xV/ntv4+S96nyGRO9gccQZmEPiBK3bRi5kPHcG+v2T32n2+53bxNY8oQyWIB0SR9OmqxMeTh5lm/8azx8srEbCQNSqTpUTX+eagwCiPqiWeQAXO/olHV2tPaYUFjWCxsQJjt7MV564K6iOB2Xj1adNGa3PqDMFl4XwSSnAQCUIibqFPlwtTwbiOkoSR+JvLx3KYv9BXaSrlLyifSegQBNMFTAWhiIeFArRZnoX+8Y2EzKhbnuNlYO9wFpZXkwoH5Kmj/6qOFTz+0n8+Y4Y/2pVIcJqY35+YJ6wjEN33ZzL9kPY3hWjx6Sv+RcByLIQAZZYQJSn2C944FRF/QkvjQ31XZDcV04GVPOGl+WdJEhVGbaNPV3d7Va7ZP83U/1ACgzTjkg4gjUFvHhGWkrPAPnnBLNeFSEKKfAbzOu9yBAUdVj6cZURpZuU3XOUILioD93x2IEnxxFGc9c6M+M93cHSNZVzHquBQDeMn4x898wQ2us7pgGvAbyU8/z5e5EupVEqtJirCgp4KHxVI7sbrQIYKHyKF3+yvIvEEX8FsQNk9qXwgBpgQwNo7p9OKrukzfdzF08+WTmYrV35YF+tU8bEpYImInGtLVH+8PkzZ8iQcVpjrawXCLOHH5uo/9JmWjbXHJMQcNhVW8bOklbsumnJw7Q+cgtVK2mJxAUNNKKncp54KHuzAwnjCE01B1UIHA1A80ik/IkdIfTj6mE8MXh2sSKZhdHUd+IcDykwFLj4eMv7Fv+il75c8/xEmeHaojD+jZ4LgbsPVVvO5iutg4oSAFCCiAqVp/jrUKRU8mzVexsube05ff3tiD0Q1wkP/ojrYgeiaftiheHsjLKL4GrudTxYvb0H9h94bpzeAwCD4cAqJf5SmlBjFH5D8ChVC1Q8KyIkrjtgbE64y4lqtINJHel5Hq4q4ZdsYzsWBWaU+rkFWtFzQbiNNnWciNbT/qD4+Hitq/FdE/3mWzmvQU+W4hZZPenQuRHRNfylcvfVjpUqz0Tj6dNE1/fm4euufTx1z5am3/hr6z6lj9A9ElneKwPJ3IYEVEpqKys0YFeUhoDBP4TV/+bjVIkfqKuu8/ixC/+tqR73111V4DYnrrb+G8a+h1tkk9dY/m7MxV7XUzwdP3ApBgCYG6Co+L6/+kcB4X0g0ERFFzwXjojBc5q8ZhqOKtWEoROmLEwSWBIHowVySyqSS5kIABEYhisRFEov8SgRWGD6K9OMgq8IwBIkTBBYXASGsxcW3pUoHgfF5iIiLPv9x+03kuLxMqaqsUj1KJL4gsFgICGEtFrJtUG6OwDhtJHHhqLOl+dBAG0AnXRAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBAFBQBAQBAQBQUAQEAQEAUFAEBAEBIGVhMD/D0fV/fpMMM+gAAAAAElFTkSuQmCC' + } + +} diff --git a/uni_modules/uview-ui/libs/config/props/noticeBar.js b/uni_modules/uview-ui/libs/config/props/noticeBar.js new file mode 100644 index 0000000..02c660a --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/noticeBar.js @@ -0,0 +1,27 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:17:13 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/noticeBar.js + */ +export default { + // noticeBar + noticeBar: { + text: () => [], + direction: 'row', + step: false, + icon: 'volume', + mode: '', + color: '#f9ae3d', + bgColor: '#fdf6ec', + speed: 80, + fontSize: 14, + duration: 2000, + disableTouch: true, + url: '', + linkType: 'navigateTo' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/notify.js b/uni_modules/uview-ui/libs/config/props/notify.js new file mode 100644 index 0000000..1042d2a --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/notify.js @@ -0,0 +1,22 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:10:21 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/notify.js + */ +export default { + // notify������ + notify: { + top: 0, + type: 'primary', + color: '#ffffff', + bgColor: '', + message: '', + duration: 3000, + fontSize: 15, + safeAreaInsetTop: false + } +} diff --git a/uni_modules/uview-ui/libs/config/props/numberBox.js b/uni_modules/uview-ui/libs/config/props/numberBox.js new file mode 100644 index 0000000..424f0ca --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/numberBox.js @@ -0,0 +1,35 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:11:46 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/numberBox.js + */ +export default { + // ��������������� + numberBox: { + name: '', + value: 0, + min: 1, + max: Number.MAX_SAFE_INTEGER, + step: 1, + integer: false, + disabled: false, + disabledInput: false, + asyncChange: false, + inputWidth: 35, + showMinus: true, + showPlus: true, + decimalLength: null, + longPress: true, + color: '#323233', + buttonSize: 30, + bgColor: '#EBECEE', + cursorSpacing: 100, + disableMinus: false, + disablePlus: false, + iconStyle: '' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/numberKeyboard.js b/uni_modules/uview-ui/libs/config/props/numberKeyboard.js new file mode 100644 index 0000000..7b45065 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/numberKeyboard.js @@ -0,0 +1,17 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:08:05 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/numberKeyboard.js + */ +export default { + // ������������ + numberKeyboard: { + mode: 'number', + dotDisabled: false, + random: false + } +} diff --git a/uni_modules/uview-ui/libs/config/props/overlay.js b/uni_modules/uview-ui/libs/config/props/overlay.js new file mode 100644 index 0000000..c26d068 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/overlay.js @@ -0,0 +1,18 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:06:50 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/overlay.js + */ +export default { + // overlay������ + overlay: { + show: false, + zIndex: 10070, + duration: 300, + opacity: 0.5 + } +} diff --git a/uni_modules/uview-ui/libs/config/props/parse.js b/uni_modules/uview-ui/libs/config/props/parse.js new file mode 100644 index 0000000..feb22b9 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/parse.js @@ -0,0 +1,22 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:17:33 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/parse.js + */ +export default { + // parse + parse: { + copyLink: true, + errorImg: '', + lazyLoad: false, + loadingImg: '', + pauseVideo: true, + previewImg: true, + setTitle: true, + showImgMenu: true + } +} diff --git a/uni_modules/uview-ui/libs/config/props/picker.js b/uni_modules/uview-ui/libs/config/props/picker.js new file mode 100644 index 0000000..f06b321 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/picker.js @@ -0,0 +1,29 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:18:20 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/picker.js + */ +export default { + // picker + picker: { + show: false, + showToolbar: true, + title: '', + columns: () => [], + loading: false, + itemHeight: 44, + cancelText: '������', + confirmText: '������', + cancelColor: '#909193', + confirmColor: '#3c9cff', + visibleItemCount: 5, + keyName: 'text', + closeOnClickOverlay: false, + defaultIndex: () => [], + immediateChange: false + } +} diff --git a/uni_modules/uview-ui/libs/config/props/popup.js b/uni_modules/uview-ui/libs/config/props/popup.js new file mode 100644 index 0000000..0cc1bc0 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/popup.js @@ -0,0 +1,29 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:06:33 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/popup.js + */ +export default { + // popup������ + popup: { + show: false, + overlay: true, + mode: 'bottom', + duration: 300, + closeable: false, + overlayStyle: () => {}, + closeOnClickOverlay: true, + zIndex: 10075, + safeAreaInsetBottom: true, + safeAreaInsetTop: false, + closeIconPos: 'top-right', + round: 0, + zoom: true, + bgColor: '', + overlayOpacity: 0.5 + } +} diff --git a/uni_modules/uview-ui/libs/config/props/radio.js b/uni_modules/uview-ui/libs/config/props/radio.js new file mode 100644 index 0000000..4df200f --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/radio.js @@ -0,0 +1,27 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:02:34 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/radio.js + */ +export default { + // radio������ + radio: { + name: '', + shape: '', + disabled: '', + labelDisabled: '', + activeColor: '', + inactiveColor: '', + iconSize: '', + labelSize: '', + label: '', + labelColor: '', + size: '', + iconColor: '', + placement: '' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/radioGroup.js b/uni_modules/uview-ui/libs/config/props/radioGroup.js new file mode 100644 index 0000000..728e9db --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/radioGroup.js @@ -0,0 +1,30 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:03:12 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/radioGroup.js + */ +export default { + // radio-group������ + radioGroup: { + value: '', + disabled: false, + shape: 'circle', + activeColor: '#2979ff', + inactiveColor: '#c8c9cc', + name: '', + size: 18, + placement: 'row', + label: '', + labelColor: '#303133', + labelSize: 14, + labelDisabled: false, + iconColor: '#ffffff', + iconSize: 12, + borderBottom: false, + iconPlacement: 'left' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/rate.js b/uni_modules/uview-ui/libs/config/props/rate.js new file mode 100644 index 0000000..d31c61a --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/rate.js @@ -0,0 +1,26 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:05:09 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/rate.js + */ +export default { + // rate������ + rate: { + value: 1, + count: 5, + disabled: false, + size: 18, + inactiveColor: '#b2b2b2', + activeColor: '#FA3534', + gutter: 4, + minCount: 1, + allowHalf: false, + activeIcon: 'star-fill', + inactiveIcon: 'star', + touchable: true + } +} diff --git a/uni_modules/uview-ui/libs/config/props/readMore.js b/uni_modules/uview-ui/libs/config/props/readMore.js new file mode 100644 index 0000000..09b11cc --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/readMore.js @@ -0,0 +1,22 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:18:41 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/readMore.js + */ +export default { + // readMore + readMore: { + showHeight: 400, + toggle: false, + closeText: '������������������', + openText: '������', + color: '#2979ff', + fontSize: 14, + textIndent: '2em', + name: '' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/row.js b/uni_modules/uview-ui/libs/config/props/row.js new file mode 100644 index 0000000..573a431 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/row.js @@ -0,0 +1,17 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:18:58 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/row.js + */ +export default { + // row + row: { + gutter: 0, + justify: 'start', + align: 'center' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/rowNotice.js b/uni_modules/uview-ui/libs/config/props/rowNotice.js new file mode 100644 index 0000000..cd9d0a0 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/rowNotice.js @@ -0,0 +1,21 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:19:13 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/rowNotice.js + */ +export default { + // rowNotice + rowNotice: { + text: '', + icon: 'volume', + mode: '', + color: '#f9ae3d', + bgColor: '#fdf6ec', + fontSize: 14, + speed: 80 + } +} diff --git a/uni_modules/uview-ui/libs/config/props/scrollList.js b/uni_modules/uview-ui/libs/config/props/scrollList.js new file mode 100644 index 0000000..441e63a --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/scrollList.js @@ -0,0 +1,20 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:19:28 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/scrollList.js + */ +export default { + // scrollList + scrollList: { + indicatorWidth: 50, + indicatorBarWidth: 20, + indicator: true, + indicatorColor: '#f2f2f2', + indicatorActiveColor: '#3c9cff', + indicatorStyle: '' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/search.js b/uni_modules/uview-ui/libs/config/props/search.js new file mode 100644 index 0000000..2699954 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/search.js @@ -0,0 +1,37 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:19:45 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/search.js + */ +export default { + // search + search: { + shape: 'round', + bgColor: '#f2f2f2', + placeholder: '������������������', + clearabled: true, + focus: false, + showAction: true, + actionStyle: () => ({}), + actionText: '������', + inputAlign: 'left', + inputStyle: () => ({}), + disabled: false, + borderColor: 'transparent', + searchIconColor: '#909399', + searchIconSize: 22, + color: '#606266', + placeholderColor: '#909399', + searchIcon: 'search', + margin: '0', + animation: false, + value: '', + maxlength: '-1', + height: 32, + label: null + } +} diff --git a/uni_modules/uview-ui/libs/config/props/section.js b/uni_modules/uview-ui/libs/config/props/section.js new file mode 100644 index 0000000..f432648 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/section.js @@ -0,0 +1,24 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:07:33 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/section.js + */ +export default { + // u-section������ + section: { + title: '', + subTitle: '������', + right: true, + fontSize: 15, + bold: true, + color: '#303133', + subColor: '#909399', + showLine: true, + lineColor: '', + arrow: true + } +} diff --git a/uni_modules/uview-ui/libs/config/props/skeleton.js b/uni_modules/uview-ui/libs/config/props/skeleton.js new file mode 100644 index 0000000..83b777d --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/skeleton.js @@ -0,0 +1,25 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:20:14 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/skeleton.js + */ +export default { + // skeleton + skeleton: { + loading: true, + animate: true, + rows: 0, + rowsWidth: '100%', + rowsHeight: 18, + title: true, + titleWidth: '50%', + titleHeight: 18, + avatar: false, + avatarSize: 32, + avatarShape: 'circle' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/slider.js b/uni_modules/uview-ui/libs/config/props/slider.js new file mode 100644 index 0000000..50cc37f --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/slider.js @@ -0,0 +1,25 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:08:25 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/slider.js + */ +export default { + // slider������ + slider: { + value: 0, + blockSize: 18, + min: 0, + max: 100, + step: 1, + activeColor: '#2979ff', + inactiveColor: '#c0c4cc', + blockColor: '#ffffff', + showValue: false, + disabled:false, + blockStyle: () => {} + } +} diff --git a/uni_modules/uview-ui/libs/config/props/statusBar.js b/uni_modules/uview-ui/libs/config/props/statusBar.js new file mode 100644 index 0000000..d237a83 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/statusBar.js @@ -0,0 +1,15 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:20:39 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/statusBar.js + */ +export default { + // statusBar + statusBar: { + bgColor: 'transparent' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/steps.js b/uni_modules/uview-ui/libs/config/props/steps.js new file mode 100644 index 0000000..881c39e --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/steps.js @@ -0,0 +1,21 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:12:37 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/steps.js + */ +export default { + // steps������ + steps: { + direction: 'row', + current: 0, + activeColor: '#3c9cff', + inactiveColor: '#969799', + activeIcon: '', + inactiveIcon: '', + dot: false + } +} diff --git a/uni_modules/uview-ui/libs/config/props/stepsItem.js b/uni_modules/uview-ui/libs/config/props/stepsItem.js new file mode 100644 index 0000000..5dba8f4 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/stepsItem.js @@ -0,0 +1,18 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:12:55 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/stepsItem.js + */ +export default { + // steps-item������ + stepsItem: { + title: '', + desc: '', + iconSize: 17, + error: false + } +} diff --git a/uni_modules/uview-ui/libs/config/props/sticky.js b/uni_modules/uview-ui/libs/config/props/sticky.js new file mode 100644 index 0000000..b034604 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/sticky.js @@ -0,0 +1,20 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:01:30 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/sticky.js + */ +export default { + // sticky������ + sticky: { + offsetTop: 0, + customNavHeight: 0, + disabled: false, + bgColor: 'transparent', + zIndex: '', + index: '' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/subsection.js b/uni_modules/uview-ui/libs/config/props/subsection.js new file mode 100644 index 0000000..9a165ff --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/subsection.js @@ -0,0 +1,23 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:12:20 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/subsection.js + */ +export default { + // subsection������ + subsection: { + list: [], + current: 0, + activeColor: '#3c9cff', + inactiveColor: '#303133', + mode: 'button', + fontSize: 12, + bold: true, + bgColor: '#eeeeef', + keyName: 'name' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/swipeAction.js b/uni_modules/uview-ui/libs/config/props/swipeAction.js new file mode 100644 index 0000000..25051b8 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/swipeAction.js @@ -0,0 +1,15 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:00:42 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/swipeAction.js + */ +export default { + // swipe-action������ + swipeAction: { + autoClose: true + } +} diff --git a/uni_modules/uview-ui/libs/config/props/swipeActionItem.js b/uni_modules/uview-ui/libs/config/props/swipeActionItem.js new file mode 100644 index 0000000..40ef27c --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/swipeActionItem.js @@ -0,0 +1,21 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:01:13 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/swipeActionItem.js + */ +export default { + // swipeActionItem ������ + swipeActionItem: { + show: false, + name: '', + disabled: false, + threshold: 20, + autoClose: true, + options: [], + duration: 300 + } +} diff --git a/uni_modules/uview-ui/libs/config/props/swiper.js b/uni_modules/uview-ui/libs/config/props/swiper.js new file mode 100644 index 0000000..0e6a3b7 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/swiper.js @@ -0,0 +1,39 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:21:38 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/swiper.js + */ +export default { + // swiper ������ + swiper: { + list: () => [], + indicator: false, + indicatorActiveColor: '#FFFFFF', + indicatorInactiveColor: 'rgba(255, 255, 255, 0.35)', + indicatorStyle: '', + indicatorMode: 'line', + autoplay: true, + current: 0, + currentItemId: '', + interval: 3000, + duration: 300, + circular: false, + previousMargin: 0, + nextMargin: 0, + acceleration: false, + displayMultipleItems: 1, + easingFunction: 'default', + keyName: 'url', + imgMode: 'aspectFill', + height: 130, + bgColor: '#f3f4f6', + radius: 4, + loading: false, + showTitle: false + } + +} diff --git a/uni_modules/uview-ui/libs/config/props/swipterIndicator.js b/uni_modules/uview-ui/libs/config/props/swipterIndicator.js new file mode 100644 index 0000000..4b59e6e --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/swipterIndicator.js @@ -0,0 +1,19 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:22:07 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/swiperIndicator.js + */ +export default { + // swiperIndicator ������ + swiperIndicator: { + length: 0, + current: 0, + indicatorActiveColor: '', + indicatorInactiveColor: '', + indicatorMode: 'line' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/switch.js b/uni_modules/uview-ui/libs/config/props/switch.js new file mode 100644 index 0000000..e6400b4 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/switch.js @@ -0,0 +1,24 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:22:24 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/switch.js + */ +export default { + // switch + switch: { + loading: false, + disabled: false, + size: 25, + activeColor: '#2979ff', + inactiveColor: '#ffffff', + value: false, + activeValue: true, + inactiveValue: false, + asyncChange: false, + space: 0 + } +} diff --git a/uni_modules/uview-ui/libs/config/props/tabbar.js b/uni_modules/uview-ui/libs/config/props/tabbar.js new file mode 100644 index 0000000..187112d --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/tabbar.js @@ -0,0 +1,22 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:22:40 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/tabbar.js + */ +export default { + // tabbar + tabbar: { + value: null, + safeAreaInsetBottom: true, + border: true, + zIndex: 1, + activeColor: '#1989fa', + inactiveColor: '#7d7e80', + fixed: true, + placeholder: true + } +} diff --git a/uni_modules/uview-ui/libs/config/props/tabbarItem.js b/uni_modules/uview-ui/libs/config/props/tabbarItem.js new file mode 100644 index 0000000..d036ce5 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/tabbarItem.js @@ -0,0 +1,20 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:22:55 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/tabbarItem.js + */ +export default { + // + tabbarItem: { + name: null, + icon: '', + badge: null, + dot: false, + text: '', + badgeStyle: 'top: 6px;right:2px;' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/tabs.js b/uni_modules/uview-ui/libs/config/props/tabs.js new file mode 100644 index 0000000..81c794a --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/tabs.js @@ -0,0 +1,32 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:23:14 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/tabs.js + */ +export default { + // + tabs: { + duration: 300, + list: () => [], + lineColor: '#3c9cff', + activeStyle: () => ({ + color: '#303133' + }), + inactiveStyle: () => ({ + color: '#606266' + }), + lineWidth: 20, + lineHeight: 3, + lineBgSize: 'cover', + itemStyle: () => ({ + height: '44px' + }), + scrollable: true, + current: 0, + keyName: 'name' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/tag.js b/uni_modules/uview-ui/libs/config/props/tag.js new file mode 100644 index 0000000..125ce94 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/tag.js @@ -0,0 +1,29 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:23:37 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/tag.js + */ +export default { + // tag ������ + tag: { + type: 'primary', + disabled: false, + size: 'medium', + shape: 'square', + text: '', + bgColor: '', + color: '', + borderColor: '', + closeColor: '#C6C7CB', + name: '', + plainFill: false, + plain: false, + closable: false, + show: true, + icon: '' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/text.js b/uni_modules/uview-ui/libs/config/props/text.js new file mode 100644 index 0000000..7e73606 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/text.js @@ -0,0 +1,38 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:23:58 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/text.js + */ +export default { + // text ������ + text: { + type: '', + show: true, + text: '', + prefixIcon: '', + suffixIcon: '', + mode: '', + href: '', + format: '', + call: false, + openType: '', + bold: false, + block: false, + lines: '', + color: '#303133', + size: 15, + iconStyle: () => ({ + fontSize: '15px' + }), + decoration: 'none', + margin: 0, + lineHeight: '', + align: 'left', + wordWrap: 'normal' + } + +} diff --git a/uni_modules/uview-ui/libs/config/props/textarea.js b/uni_modules/uview-ui/libs/config/props/textarea.js new file mode 100644 index 0000000..44519f9 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/textarea.js @@ -0,0 +1,36 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:24:32 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/textarea.js + */ +export default { + // textarea ������ + textarea: { + value: '', + placeholder: '', + placeholderClass: 'textarea-placeholder', + placeholderStyle: 'color: #c0c4cc', + height: 70, + confirmType: 'done', + disabled: false, + count: false, + focus: false, + autoHeight: false, + fixed: false, + cursorSpacing: 0, + cursor: '', + showConfirmBar: true, + selectionStart: -1, + selectionEnd: -1, + adjustPosition: true, + disableDefaultPadding: false, + holdKeyboard: false, + maxlength: 140, + border: 'surround', + formatter: null + } +} diff --git a/uni_modules/uview-ui/libs/config/props/toast.js b/uni_modules/uview-ui/libs/config/props/toast.js new file mode 100644 index 0000000..a50134b --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/toast.js @@ -0,0 +1,30 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:07:07 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/toast.js + */ +export default { + // toast������ + toast: { + zIndex: 10090, + loading: false, + text: '', + icon: '', + type: '', + loadingMode: '', + show: '', + overlay: false, + position: 'center', + params: () => {}, + duration: 2000, + isTab: false, + url: '', + callback: null, + back: false + } + +} diff --git a/uni_modules/uview-ui/libs/config/props/toolbar.js b/uni_modules/uview-ui/libs/config/props/toolbar.js new file mode 100644 index 0000000..3289967 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/toolbar.js @@ -0,0 +1,21 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:24:55 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/toolbar.js + */ +export default { + // toolbar ������ + toolbar: { + show: true, + cancelText: '������', + confirmText: '������', + cancelColor: '#909193', + confirmColor: '#3c9cff', + title: '' + } + +} diff --git a/uni_modules/uview-ui/libs/config/props/tooltip.js b/uni_modules/uview-ui/libs/config/props/tooltip.js new file mode 100644 index 0000000..115e030 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/tooltip.js @@ -0,0 +1,25 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:25:14 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/tooltip.js + */ +export default { + // tooltip ������ + tooltip: { + text: '', + copyText: '', + size: 14, + color: '#606266', + bgColor: 'transparent', + direction: 'top', + zIndex: 10071, + showCopy: true, + buttons: () => [], + overlay: true, + showToast: true + } +} diff --git a/uni_modules/uview-ui/libs/config/props/transition.js b/uni_modules/uview-ui/libs/config/props/transition.js new file mode 100644 index 0000000..0fad118 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/transition.js @@ -0,0 +1,18 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 16:59:00 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/transition.js + */ +export default { + // transition���������������props + transition: { + show: false, + mode: 'fade', + duration: '300', + timingFunction: 'ease-out' + } +} diff --git a/uni_modules/uview-ui/libs/config/props/upload.js b/uni_modules/uview-ui/libs/config/props/upload.js new file mode 100644 index 0000000..fc7ca92 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/props/upload.js @@ -0,0 +1,36 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-20 16:44:21 + * @LastAuthor : LQ + * @lastTime : 2021-08-20 17:09:50 + * @FilePath : /u-view2.0/uview-ui/libs/config/props/upload.js + */ +export default { + // upload������ + upload: { + accept: 'image', + capture: () => ['album', 'camera'], + compressed: true, + camera: 'back', + maxDuration: 60, + uploadIcon: 'camera-fill', + uploadIconColor: '#D3D4D6', + useBeforeRead: false, + previewFullImage: true, + maxCount: 52, + disabled: false, + imageMode: 'aspectFill', + name: '', + sizeType: () => ['original', 'compressed'], + multiple: false, + deletable: true, + maxSize: Number.MAX_VALUE, + fileList: () => [], + uploadText: '', + width: 80, + height: 80, + previewImage: true + } +} diff --git a/uni_modules/uview-ui/libs/config/zIndex.js b/uni_modules/uview-ui/libs/config/zIndex.js new file mode 100644 index 0000000..5fc3682 --- /dev/null +++ b/uni_modules/uview-ui/libs/config/zIndex.js @@ -0,0 +1,20 @@ +// uniapp���H5������API���z-index������������ +/** + * actionsheet: 999 + * modal: 999 + * navigate: 998 + * tabbar: 998 + * toast: 999 + */ + +export default { + toast: 10090, + noNetwork: 10080, + // popup������popup���actionsheet���keyboard���picker������ + popup: 10075, + mask: 10070, + navbar: 980, + topTips: 975, + sticky: 970, + indexListSticky: 965 +} diff --git a/uni_modules/uview-ui/libs/css/color.scss b/uni_modules/uview-ui/libs/css/color.scss new file mode 100644 index 0000000..3237ba4 --- /dev/null +++ b/uni_modules/uview-ui/libs/css/color.scss @@ -0,0 +1,155 @@ +.u-primary-light { + color: $u-primary-light; +} + +.u-warning-light { + color: $u-warning-light; +} + +.u-success-light { + color: $u-success-light; +} + +.u-error-light { + color: $u-error-light; +} + +.u-info-light { + color: $u-info-light; +} + +.u-primary-light-bg { + background-color: $u-primary-light; +} + +.u-warning-light-bg { + background-color: $u-warning-light; +} + +.u-success-light-bg { + background-color: $u-success-light; +} + +.u-error-light-bg { + background-color: $u-error-light; +} + +.u-info-light-bg { + background-color: $u-info-light; +} + +.u-primary-dark { + color: $u-primary-dark; +} + +.u-warning-dark { + color: $u-warning-dark; +} + +.u-success-dark { + color: $u-success-dark; +} + +.u-error-dark { + color: $u-error-dark; +} + +.u-info-dark { + color: $u-info-dark; +} + +.u-primary-dark-bg { + background-color: $u-primary-dark; +} + +.u-warning-dark-bg { + background-color: $u-warning-dark; +} + +.u-success-dark-bg { + background-color: $u-success-dark; +} + +.u-error-dark-bg { + background-color: $u-error-dark; +} + +.u-info-dark-bg { + background-color: $u-info-dark; +} + +.u-primary-disabled { + color: $u-primary-disabled; +} + +.u-warning-disabled { + color: $u-warning-disabled; +} + +.u-success-disabled { + color: $u-success-disabled; +} + +.u-error-disabled { + color: $u-error-disabled; +} + +.u-info-disabled { + color: $u-info-disabled; +} + +.u-primary { + color: $u-primary; +} + +.u-warning { + color: $u-warning; +} + +.u-success { + color: $u-success; +} + +.u-error { + color: $u-error; +} + +.u-info { + color: $u-info; +} + +.u-primary-bg { + background-color: $u-primary; +} + +.u-warning-bg { + background-color: $u-warning; +} + +.u-success-bg { + background-color: $u-success; +} + +.u-error-bg { + background-color: $u-error; +} + +.u-info-bg { + background-color: $u-info; +} + +.u-main-color { + color: $u-main-color; +} + +.u-content-color { + color: $u-content-color; +} + +.u-tips-color { + color: $u-tips-color; +} + +.u-light-color { + color: $u-light-color; +} diff --git a/uni_modules/uview-ui/libs/css/common.scss b/uni_modules/uview-ui/libs/css/common.scss new file mode 100644 index 0000000..11f1e53 --- /dev/null +++ b/uni_modules/uview-ui/libs/css/common.scss @@ -0,0 +1,97 @@ +// ���������������������������������������������������5��� +// ������uView���������������������������������������������������������������������App.vue���style���������������lang="scss"��� +@for $i from 1 through 5 { + .u-line-#{$i} { + /* #ifdef APP-NVUE */ + // nvue������������������������lines���������������weex������������ + lines: $i; + text-overflow: ellipsis; + overflow: hidden; + flex: 1; + /* #endif */ + + /* #ifndef APP-NVUE */ + // vue������������������������������������������������������ + @if $i == '1' { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } @else { + display: -webkit-box!important; + overflow: hidden; + text-overflow: ellipsis; + word-break: break-all; + -webkit-line-clamp: $i; + -webkit-box-orient: vertical!important; + } + /* #endif */ + } +} + + +// ������������!important���������������������������������������*.nvue���������������H5������ +// App.vue���������������uni-app���view���������������border��������������������������� +// ���������������uni-app������������������������������������������������������������!important +// ���������������������������������������0.5px��������������������������������������������������� +.u-border { + border-width: 0.5px!important; + border-color: $u-border-color!important; + border-style: solid; +} + +.u-border-top { + border-top-width: 0.5px!important; + border-color: $u-border-color!important; + border-top-style: solid; +} + +.u-border-left { + border-left-width: 0.5px!important; + border-color: $u-border-color!important; + border-left-style: solid; +} + +.u-border-right { + border-right-width: 0.5px!important; + border-color: $u-border-color!important; + border-right-style: solid; +} + +.u-border-bottom { + border-bottom-width: 0.5px!important; + border-color: $u-border-color!important; + border-bottom-style: solid; +} + +.u-border-top-bottom { + border-top-width: 0.5px!important; + border-bottom-width: 0.5px!important; + border-color: $u-border-color!important; + border-top-style: solid; + border-bottom-style: solid; +} + +// ������button������������������������������������������������view���text������������ +.u-reset-button { + padding: 0; + background-color: transparent; + /* #ifndef APP-PLUS */ + font-size: inherit; + line-height: inherit; + color: inherit; + /* #endif */ + /* #ifdef APP-NVUE */ + border-width: 0; + /* #endif */ +} + +/* #ifndef APP-NVUE */ +.u-reset-button::after { + border: none; +} +/* #endif */ + +.u-hover-class { + opacity: 0.7; +} + diff --git a/uni_modules/uview-ui/libs/css/components.scss b/uni_modules/uview-ui/libs/css/components.scss new file mode 100644 index 0000000..766679e --- /dev/null +++ b/uni_modules/uview-ui/libs/css/components.scss @@ -0,0 +1,15 @@ +@import "./mixin.scss"; + +/* #ifndef APP-NVUE */ +// ������uView���������nvue���������������������������������������������������������flex-direction: column; +// ������������nvue������������������������������������flex-direction: column; ��������������������������� +view, scroll-view, swiper-item { + display: flex; + flex-direction: column; + flex-shrink: 0; + flex-grow: 0; + flex-basis: auto; + align-items: stretch; + align-content: flex-start; +} +/* #endif */ diff --git a/uni_modules/uview-ui/libs/css/flex.scss b/uni_modules/uview-ui/libs/css/flex.scss new file mode 100644 index 0000000..6d61be9 --- /dev/null +++ b/uni_modules/uview-ui/libs/css/flex.scss @@ -0,0 +1,257 @@ +// .u-flex { +// @include vue-flex(row); +// } + +// .u-flex-x { +// @include vue-flex(row); +// } + +// .u-flex-y { +// @include vue-flex(column); +// } + +// .u-flex-xy-center { +// @include vue-flex(row); +// justify-content: center; +// align-items: center; +// } + +// .u-flex-x-center { +// @include vue-flex(row); +// justify-content: center; +// } + +// .u-flex-y-center { +// @include vue-flex(column); +// justify-content: center; +// } + + +// flex������ +.u-flex, +.u-flex-row, +.u-flex-x { + @include flex; +} + +.u-flex-y, +.u-flex-column { + @include flex(column); +} + +.u-flex-x-center { + @include flex; + justify-content: center; +} + +.u-flex-xy-center { + @include flex; + justify-content: center; + align-items: center; +} + +.u-flex-y-center { + @include flex; + align-items: center; +} + +.u-flex-x-left { + @include flex; +} + +.u-flex-x-reverse, +.u-flex-row-reverse { + flex-direction: row-reverse; +} + +.u-flex-y-reverse, +.u-flex-column-reverse { + flex-direction: column-reverse; +} + +/* #ifndef APP-NVUE */ +// ���������vue������������������������nvue��������������������������������������������������� +// nvue���������������class="u-flex-x u-flex-x-reverse���������" +.u-flex.u-flex-reverse, +.u-flex-row.u-flex-reverse, +.u-flex-x.u-flex-reverse { + flex-direction: row-reverse; +} + +.u-flex-column.u-flex-reverse, +.u-flex-y.u-flex-reverse { + flex-direction: column-reverse; +} + +// ������������ +.u-flex-fill { + flex: 1 1 auto +} + +// ������������������ +.u-margin-top-auto, +.u-m-t-auto { + margin-top: auto !important +} + +.u-margin-right-auto, +.u-m-r-auto { + margin-right: auto !important +} + +.u-margin-bottom-auto, +.u-m-b-auto { + margin-bottom: auto !important +} + +.u-margin-left-auto, +.u-m-l-auto { + margin-left: auto !important +} + +.u-margin-center-auto, +.u-m-c-auto { + margin-left: auto !important; + margin-right: auto !important +} + +.u-margin-middle-auto, +.u-m-m-auto { + margin-top: auto !important; + margin-bottom: auto !important +} +/* #endif */ + +// ������ +.u-flex-wrap { + flex-wrap: wrap; +} + +// ������������ +.u-flex-wrap-reverse { + flex-wrap: wrap-reverse; +} + +// ������������������ +.u-flex-start { + justify-content: flex-start +} + +// ������������������ +.u-flex-center { + justify-content: center +} + +// ������������������ +.u-flex-end { + justify-content: flex-end +} + +// ������������������ +.u-flex-between { + justify-content: space-between +} + +// ������������������ +.u-flex-around { + justify-content: space-around +} + +// ��������������������� +.u-flex-items-start { + align-items: flex-start +} + +// ��������������������� +.u-flex-items-center { + align-items: center +} + +// ��������������������� +.u-flex-items-end { + align-items: flex-end +} + +// ������������������������������������ +.u-flex-items-baseline { + align-items: baseline +} + +// ��������������������������� +.u-flex-items-stretch { + align-items: stretch +} + + +// ������������������(���������)������ + +// ������������������������������ +.u-flex-self-start { + align-self: flex-start +} + +// ������������������������������ +.u-flex-self-center { + align-self: center +} + +// ������������������������������ +.u-flex-self-end { + align-self: flex-end +} + +// ��������������������������������������������� +.u-flex-self-baseline { + align-self: baseline +} + +// ������������������������������������ +.u-flex-self-stretch { + align-self: stretch +} + +// ������������������������������ + +// ������������ +.u-flex-content-start { + align-content: flex-start +} + +// ������������ +.u-flex-content-center { + align-content: center +} + +// ������������ +.u-flex-content-end { + align-content: flex-end +} + +// ������������ +.u-flex-content-between { + align-content: space-between +} + +// ������������ +.u-flex-content-around { + align-content: space-around +} + +// ������������������ +.u-flex-middle { + justify-content: center; + align-items: center; + align-self: center; + align-content: center +} + +// ������������������ +.u-flex-grow { + flex-grow: 1 +} + +// ������������������ +.u-flex-shrink { + flex-shrink: 1 +} + diff --git a/uni_modules/uview-ui/libs/css/h5.scss b/uni_modules/uview-ui/libs/css/h5.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/uni_modules/uview-ui/libs/css/h5.scss diff --git a/uni_modules/uview-ui/libs/css/mixin.scss b/uni_modules/uview-ui/libs/css/mixin.scss new file mode 100644 index 0000000..7e35b3b --- /dev/null +++ b/uni_modules/uview-ui/libs/css/mixin.scss @@ -0,0 +1,8 @@ +// ������scss���mixin���������������������������4������css��������������� +// ������������������������������������������������nvue���������������������display:flex��������������� +@mixin flex($direction: row) { + /* #ifndef APP-NVUE */ + display: flex; + /* #endif */ + flex-direction: $direction; +} diff --git a/uni_modules/uview-ui/libs/css/mp.scss b/uni_modules/uview-ui/libs/css/mp.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/uni_modules/uview-ui/libs/css/mp.scss diff --git a/uni_modules/uview-ui/libs/css/nvue.scss b/uni_modules/uview-ui/libs/css/nvue.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/uni_modules/uview-ui/libs/css/nvue.scss diff --git a/uni_modules/uview-ui/libs/css/vue.scss b/uni_modules/uview-ui/libs/css/vue.scss new file mode 100644 index 0000000..3ae4d29 --- /dev/null +++ b/uni_modules/uview-ui/libs/css/vue.scss @@ -0,0 +1,27 @@ +// ������������4��������������������������� +@each $d in top, right, bottom, left { + .u-safe-area-inset-#{$d} { + padding-#{$d}: 0; + padding-#{$d}: constant(safe-area-inset-#{$d}); + padding-#{$d}: env(safe-area-inset-#{$d}); + } +} + +//������H5���uni.toast()���������������������uView���modal��������� +/* #ifdef H5 */ +uni-toast { + z-index: 10090; +} +uni-toast .uni-toast { + z-index: 10090; +} +/* #endif */ + +// ������scroll-view������������ +::-webkit-scrollbar { + display: none; + width: 0 !important; + height: 0 !important; + -webkit-appearance: none; + background: transparent; +} \ No newline at end of file diff --git a/uni_modules/uview-ui/libs/function/colorGradient.js b/uni_modules/uview-ui/libs/function/colorGradient.js new file mode 100644 index 0000000..9727732 --- /dev/null +++ b/uni_modules/uview-ui/libs/function/colorGradient.js @@ -0,0 +1,134 @@ +/** + * ��������������������������������� + * @param {string} startColor ��������������� + * @param {string} endColor ��������������� + * @param {number} step ��������������������� + * */ +function colorGradient(startColor = 'rgb(0, 0, 0)', endColor = 'rgb(255, 255, 255)', step = 10) { + const startRGB = hexToRgb(startColor, false) // ���������rgb������������ + const startR = startRGB[0] + const startG = startRGB[1] + const startB = startRGB[2] + + const endRGB = hexToRgb(endColor, false) + const endR = endRGB[0] + const endG = endRGB[1] + const endB = endRGB[2] + + const sR = (endR - startR) / step // ��������� + const sG = (endG - startG) / step + const sB = (endB - startB) / step + const colorArr = [] + for (let i = 0; i < step; i++) { + // ������������������hex��� + let hex = rgbToHex(`rgb(${Math.round((sR * i + startR))},${Math.round((sG * i + startG))},${Math.round((sB + * i + startB))})`) + // ���������������������������startColor������ + if (i === 0) hex = rgbToHex(startColor) + // ������������������������������endColor������ + if (i === step - 1) hex = rgbToHex(endColor) + colorArr.push(hex) + } + return colorArr +} + +// ���hex���������������������rgb������������(������������rgb������������) +function hexToRgb(sColor, str = true) { + const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/ + sColor = String(sColor).toLowerCase() + if (sColor && reg.test(sColor)) { + if (sColor.length === 4) { + let sColorNew = '#' + for (let i = 1; i < 4; i += 1) { + sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1)) + } + sColor = sColorNew + } + // ������������������������ + const sColorChange = [] + for (let i = 1; i < 7; i += 2) { + sColorChange.push(parseInt(`0x${sColor.slice(i, i + 2)}`)) + } + if (!str) { + return sColorChange + } + return `rgb(${sColorChange[0]},${sColorChange[1]},${sColorChange[2]})` + } if (/^(rgb|RGB)/.test(sColor)) { + const arr = sColor.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',') + return arr.map((val) => Number(val)) + } + return sColor +} + +// ���rgb���������������������hex������������ +function rgbToHex(rgb) { + const _this = rgb + const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/ + if (/^(rgb|RGB)/.test(_this)) { + const aColor = _this.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',') + let strHex = '#' + for (let i = 0; i < aColor.length; i++) { + let hex = Number(aColor[i]).toString(16) + hex = String(hex).length == 1 ? `${0}${hex}` : hex // ������������rgb���������2��� + if (hex === '0') { + hex += hex + } + strHex += hex + } + if (strHex.length !== 7) { + strHex = _this + } + return strHex + } if (reg.test(_this)) { + const aNum = _this.replace(/#/, '').split('') + if (aNum.length === 6) { + return _this + } if (aNum.length === 3) { + let numHex = '#' + for (let i = 0; i < aNum.length; i += 1) { + numHex += (aNum[i] + aNum[i]) + } + return numHex + } + } else { + return _this + } +} + +/** +* JS���������������������������rgb���rgba,������������������ rgba���255���255���255���0.5������������ +* sHex��������������������������������� +* alpha���rgba������������ +*/ +function colorToRgba(color, alpha) { + color = rgbToHex(color) + // ��������������������������������������� + const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/ + /* 16������������������RGB������ */ + let sColor = String(color).toLowerCase() + if (sColor && reg.test(sColor)) { + if (sColor.length === 4) { + let sColorNew = '#' + for (let i = 1; i < 4; i += 1) { + sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1)) + } + sColor = sColorNew + } + // ������������������������ + const sColorChange = [] + for (let i = 1; i < 7; i += 2) { + sColorChange.push(parseInt(`0x${sColor.slice(i, i + 2)}`)) + } + // return sColorChange.join(',') + return `rgba(${sColorChange.join(',')},${alpha})` + } + + return sColor +} + +export default { + colorGradient, + hexToRgb, + rgbToHex, + colorToRgba +} diff --git a/uni_modules/uview-ui/libs/function/debounce.js b/uni_modules/uview-ui/libs/function/debounce.js new file mode 100644 index 0000000..ad3996b --- /dev/null +++ b/uni_modules/uview-ui/libs/function/debounce.js @@ -0,0 +1,29 @@ +let timeout = null + +/** + * ������������������������������������������������������������������wait������������������������ + * + * @param {Function} func ������������������������ + * @param {Number} wait ��������������� + * @param {Boolean} immediate ������������������ + * @return null + */ +function debounce(func, wait = 500, immediate = false) { + // ��������������� + if (timeout !== null) clearTimeout(timeout) + // ������������������������������������������ + if (immediate) { + const callNow = !timeout + timeout = setTimeout(() => { + timeout = null + }, wait) + if (callNow) typeof func === 'function' && func() + } else { + // ���������������������������������������������timeout������������������������������������wait���������������func������������ + timeout = setTimeout(() => { + typeof func === 'function' && func() + }, wait) + } +} + +export default debounce diff --git a/uni_modules/uview-ui/libs/function/digit.js b/uni_modules/uview-ui/libs/function/digit.js new file mode 100644 index 0000000..c8260a0 --- /dev/null +++ b/uni_modules/uview-ui/libs/function/digit.js @@ -0,0 +1,167 @@ +let _boundaryCheckingState = true; // ��������������������������������������� + +/** + * ������������������������ + * @private + * @example strip(0.09999999999999998)=0.1 + */ +function strip(num, precision = 15) { + return +parseFloat(Number(num).toPrecision(precision)); +} + +/** + * Return digits length of a number + * @private + * @param {*number} num Input number + */ +function digitLength(num) { + // Get digit length of e + const eSplit = num.toString().split(/[eE]/); + const len = (eSplit[0].split('.')[1] || '').length - +(eSplit[1] || 0); + return len > 0 ? len : 0; +} + +/** + * ���������������������,��������������������������������� + * @private + * @param {*number} num ��������� + */ +function float2Fixed(num) { + if (num.toString().indexOf('e') === -1) { + return Number(num.toString().replace('.', '')); + } + const dLen = digitLength(num); + return dLen > 0 ? strip(Number(num) * Math.pow(10, dLen)) : Number(num); +} + +/** + * ��������������������������������������������������� + * @private + * @param {*number} num ��������� + */ +function checkBoundary(num) { + if (_boundaryCheckingState) { + if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) { + console.warn(`${num} ���������������������������������������������`); + } + } +} + +/** + * ������������������������������ + * @param {number[]} arr ������������������������ + * @param {function} operation ������������ + * @private + */ +function iteratorOperation(arr, operation) { + const [num1, num2, ...others] = arr; + let res = operation(num1, num2); + + others.forEach((num) => { + res = operation(res, num); + }); + + return res; +} + +/** + * ��������������� + * @export + */ +export function times(...nums) { + if (nums.length > 2) { + return iteratorOperation(nums, times); + } + + const [num1, num2] = nums; + const num1Changed = float2Fixed(num1); + const num2Changed = float2Fixed(num2); + const baseNum = digitLength(num1) + digitLength(num2); + const leftValue = num1Changed * num2Changed; + + checkBoundary(leftValue); + + return leftValue / Math.pow(10, baseNum); +} + +/** + * ��������������� + * @export + */ +export function plus(...nums) { + if (nums.length > 2) { + return iteratorOperation(nums, plus); + } + + const [num1, num2] = nums; + // ��������������������� + const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2))); + // ��������������������������������������� + return (times(num1, baseNum) + times(num2, baseNum)) / baseNum; +} + +/** + * ��������������� + * @export + */ +export function minus(...nums) { + if (nums.length > 2) { + return iteratorOperation(nums, minus); + } + + const [num1, num2] = nums; + const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2))); + return (times(num1, baseNum) - times(num2, baseNum)) / baseNum; +} + +/** + * ��������������� + * @export + */ +export function divide(...nums) { + if (nums.length > 2) { + return iteratorOperation(nums, divide); + } + + const [num1, num2] = nums; + const num1Changed = float2Fixed(num1); + const num2Changed = float2Fixed(num2); + checkBoundary(num1Changed); + checkBoundary(num2Changed); + // ������������������������strip������������ + return times(num1Changed / num2Changed, strip(Math.pow(10, digitLength(num2) - digitLength(num1)))); +} + +/** + * ������������ + * @export + */ +export function round(num, ratio) { + const base = Math.pow(10, ratio); + let result = divide(Math.round(Math.abs(times(num, base))), base); + if (num < 0 && result !== 0) { + result = times(result, -1); + } + // ������������������0 + return result; +} + +/** + * ��������������������������������������� + * @param flag ���������������true ������������false ��������������������� true + * @export + */ +export function enableBoundaryChecking(flag = true) { + _boundaryCheckingState = flag; +} + + +export default { + times, + plus, + minus, + divide, + round, + enableBoundaryChecking, +}; + diff --git a/uni_modules/uview-ui/libs/function/index.js b/uni_modules/uview-ui/libs/function/index.js new file mode 100644 index 0000000..bd80ee7 --- /dev/null +++ b/uni_modules/uview-ui/libs/function/index.js @@ -0,0 +1,731 @@ +import test from './test.js' +import { round } from './digit.js' +/** + * @description ������value������min������min���������value������max������max + * @param {number} min + * @param {number} max + * @param {number} value + */ +function range(min = 0, max = 0, value = 0) { + return Math.max(min, Math.min(max, Number(value))) +} + +/** + * @description ������������������������������px��� ���������������������"xxpx"������"xxrpx"������������������������������������"xxxrpx"���������������uni.upx2px������������ + * @param {number|string} value ������������������px��� + * @param {boolean} unit + * @returns {number|string} + */ +function getPx(value, unit = false) { + if (test.number(value)) { + return unit ? `${value}px` : Number(value) + } + // ������������rpx���������������������������������������px��� + if (/(rpx|upx)$/.test(value)) { + return unit ? `${uni.upx2px(parseInt(value))}px` : Number(uni.upx2px(parseInt(value))) + } + return unit ? `${parseInt(value)}px` : parseInt(value) +} + +/** + * @description ��������������������������������������������������� ������: await uni.$u.sleep(20)������������20ms + * @param {number} value ������������ ������ms ������ + * @returns {Promise} ������promise + */ +function sleep(value = 30) { + return new Promise((resolve) => { + setTimeout(() => { + resolve() + }, value) + }) +} +/** + * @description ��������������������� + * @returns {string} ������������������(������) + * @link ��������������������� https://uniapp.dcloud.io/frame?id=������������ + */ +function os() { + return uni.getSystemInfoSync().platform.toLowerCase() +} +/** + * @description ������������������������������ + * @link ������������������������������ https://uniapp.dcloud.io/api/system/info?id=getsysteminfosync + */ +function sys() { + return uni.getSystemInfoSync() +} + +/** + * @description ������������������ + * @param {Number} min ��������� + * @param {Number} max ��������� + */ +function random(min, max) { + if (min >= 0 && max > 0 && max >= min) { + const gab = max - min + 1 + return Math.floor(Math.random() * gab + min) + } + return 0 +} + +/** + * @param {Number} len uuid��������� + * @param {Boolean} firstU ���������������������������"u" + * @param {Nubmer} radix ������uuid���������(���������������������������������������������),2-���������,8-���������,10-���������,16-������������ + */ +function guid(len = 32, firstU = true, radix = null) { + const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('') + const uuid = [] + radix = radix || chars.length + + if (len) { + // ������������uuid������,������������������������,0|x������������,���������x������������,��������������� + for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix] + } else { + let r + // rfc4122���������������������uuid���,��������������������������� + uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-' + uuid[14] = '4' + + for (let i = 0; i < 36; i++) { + if (!uuid[i]) { + r = 0 | Math.random() * 16 + uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r] + } + } + } + // ���������������������,������u������,���������������������������������,���guuid������������id������class + if (firstU) { + uuid.shift() + return `u${uuid.join('')}` + } + return uuid.join('') +} + +/** +* @description ������������������������������������������������������������provide/inject��������� + this.$parent������H5������������������������������������������������H5������������������this.$parent.$parent.xxx + ���������������������undefined���������������������������������������(������)���$parent������undefined������������������name + ���(���������undefined)���������������������������$parent +* @param {string|undefined} name ��������������������� +*/ +function $parent(name = undefined) { + let parent = this.$parent + // ������while������������������������������H5��������������������������� + while (parent) { + // ��������� + if (parent.$options && parent.$options.name !== name) { + // ���������������name��������������������������������� + parent = parent.$parent + } else { + return parent + } + } + return false +} + +/** + * @description ������������ + * ��������������������������������������������� + * @param {object | string} customStyle ��������������������� + * @param {String} target ������������������object-���������������string-��������������� + * @returns {object|string} + */ +function addStyle(customStyle, target = 'object') { + // ������������������������������������������������������������ + if (test.empty(customStyle) || typeof(customStyle) === 'object' && target === 'object' || target === 'string' && + typeof(customStyle) === 'string') { + return customStyle + } + // ������������������ + if (target === 'object') { + // ���������������������������������������(������������������������������������padding: 20px 0������������������������)��������������������� + customStyle = trim(customStyle) + // ������";"������������������������������ + const styleArray = customStyle.split(';') + const style = {} + // ������������������������������ + for (let i = 0; i < styleArray.length; i++) { + // 'font-size:20px;color:red;'���������������������������";"������������������styleArray������������������������������������������������������ + if (styleArray[i]) { + const item = styleArray[i].split(':') + style[trim(item[0])] = trim(item[1]) + } + } + return style + } + // ��������������������������������� + let string = '' + for (const i in customStyle) { + // ���������������������������������������css������������������������������������������������ + const key = i.replace(/([A-Z])/g, '-$1').toLowerCase() + string += `${key}:${customStyle[i]};` + } + // ������������������ + return trim(string) +} + +/** + * @description ������������������������rpx���upx���%���px���������������������������auto������������������������������px������������ + * @param {string|number} value ������������������������ + * @param {string} unit ������������������ ������px + */ +function addUnit(value = 'auto', unit = uni?.$u?.config?.unit ?? 'px') { + value = String(value) + // ���uView������������������������number��������������������� + return test.number(value) ? `${value}${unit}` : value +} + +/** + * @description ������������ + * @param {object} obj ��������������������������� + * @param cache ������ + * @returns {*} ������������������������������������������������ + */ +function deepClone(obj, cache = new WeakMap()) { + if (obj === null || typeof obj !== 'object') return obj; + if (cache.has(obj)) return cache.get(obj); + let clone; + if (obj instanceof Date) { + clone = new Date(obj.getTime()); + } else if (obj instanceof RegExp) { + clone = new RegExp(obj); + } else if (obj instanceof Map) { + clone = new Map(Array.from(obj, ([key, value]) => [key, deepClone(value, cache)])); + } else if (obj instanceof Set) { + clone = new Set(Array.from(obj, value => deepClone(value, cache))); + } else if (Array.isArray(obj)) { + clone = obj.map(value => deepClone(value, cache)); + } else if (Object.prototype.toString.call(obj) === '[object Object]') { + clone = Object.create(Object.getPrototypeOf(obj)); + cache.set(obj, clone); + for (const [key, value] of Object.entries(obj)) { + clone[key] = deepClone(value, cache); + } + } else { + clone = Object.assign({}, obj); + } + cache.set(obj, clone); + return clone; +} + +/** + * @description JS������������������ + * @param {object} target ��������������������� + * @param {object} source ��������������������� + * @returns {object|boolean} ������������������������������false��������������������������� + */ +function deepMerge(target = {}, source = {}) { + target = deepClone(target) + if (typeof target !== 'object' || target === null || typeof source !== 'object' || source === null) return target; + const merged = Array.isArray(target) ? target.slice() : Object.assign({}, target); + for (const prop in source) { + if (!source.hasOwnProperty(prop)) continue; + const sourceValue = source[prop]; + const targetValue = merged[prop]; + if (sourceValue instanceof Date) { + merged[prop] = new Date(sourceValue); + } else if (sourceValue instanceof RegExp) { + merged[prop] = new RegExp(sourceValue); + } else if (sourceValue instanceof Map) { + merged[prop] = new Map(sourceValue); + } else if (sourceValue instanceof Set) { + merged[prop] = new Set(sourceValue); + } else if (typeof sourceValue === 'object' && sourceValue !== null) { + merged[prop] = deepMerge(targetValue, sourceValue); + } else { + merged[prop] = sourceValue; + } + } + return merged; +} + +/** + * @description error������ + * @param {*} err ������������ + */ +function error(err) { + // ������������������������������������������������ + if (process.env.NODE_ENV === 'development') { + console.error(`uView���������${err}`) + } +} + +/** + * @description ������������ + * @param {array} array ��������������������� + * @returns {array} ������������������ + */ +function randomArray(array = []) { + // ���������sort������,Math.random()������0<= x < 1������������,���������x-0.05������������������0 + return array.sort(() => Math.random() - 0.5) +} + +// padStart ��� polyfill������������������������������������������������es7���padStart������������������������������������ +// ���������������������������polyfill��������������� +if (!String.prototype.padStart) { + // ������������������������ fillString ������ES6 ��������������������������������� + String.prototype.padStart = function(maxLength, fillString = ' ') { + if (Object.prototype.toString.call(fillString) !== '[object String]') { + throw new TypeError( + 'fillString must be String' + ) + } + const str = this + // ������ String(str) ������������������������������������������������������������������������������������ + if (str.length >= maxLength) return String(str) + + const fillLength = maxLength - str.length + let times = Math.ceil(fillLength / fillString.length) + while (times >>= 1) { + fillString += fillString + if (times === 1) { + fillString += fillString + } + } + return fillString.slice(0, fillLength) + str + } +} + +/** + * @description ��������������� + * @param {String|Number} dateTime ��������������������������� + * @param {String} fmt ��������������� yyyy:mm:dd|yyyy:mm|yyyy���mm���dd���|yyyy���mm���dd��� hh���MM������,������������������ ������yyyy-mm-dd + * @returns {string} ������������������������������ + */ + function timeFormat(dateTime = null, formatStr = 'yyyy-mm-dd') { + let date + // ��������������������������������������������� + if (!dateTime) { + date = new Date() + } + // ������unix������������������������������������������������������������������������������������������������������ + else if (/^\d{10}$/.test(dateTime?.toString().trim())) { + date = new Date(dateTime * 1000) + } + // ������������������������������������������new Date��������������������������� + else if (typeof dateTime === 'string' && /^\d+$/.test(dateTime.trim())) { + date = new Date(Number(dateTime)) + } + // ���������������������������Safari/Webkit������new Date���������/��������������������������������� + // ������ '2022-07-10 01:02:03'��������� '2022-07-10T01:02:03' + else if (typeof dateTime === 'string' && dateTime.includes('-') && !dateTime.includes('T')) { + date = new Date(dateTime.replace(/-/g, '/')) + } + // ��������������������� RFC 2822 ������ + else { + date = new Date(dateTime) + } + + const timeSource = { + 'y': date.getFullYear().toString(), // ��� + 'm': (date.getMonth() + 1).toString().padStart(2, '0'), // ��� + 'd': date.getDate().toString().padStart(2, '0'), // ��� + 'h': date.getHours().toString().padStart(2, '0'), // ��� + 'M': date.getMinutes().toString().padStart(2, '0'), // ��� + 's': date.getSeconds().toString().padStart(2, '0') // ��� + // ��������������������������������������������������������������������������� + } + + for (const key in timeSource) { + const [ret] = new RegExp(`${key}+`).exec(formatStr) || [] + if (ret) { + // ��������������������������� + const beginIndex = key === 'y' && ret.length === 2 ? 2 : 0 + formatStr = formatStr.replace(ret, timeSource[key].slice(beginIndex)) + } + } + + return formatStr +} + +/** + * @description ��������������������������� + * @param {String|Number} timestamp ��������� + * @param {String|Boolean} format + * ��������������������������������������������������������������������������������������������������������� + * ������������������false������������������������������������������������������ + * @returns {string} ������������������ + */ +function timeFrom(timestamp = null, format = 'yyyy-mm-dd') { + if (timestamp == null) timestamp = Number(new Date()) + timestamp = parseInt(timestamp) + // ������������������������������������������������,������������js���������������������������(13���),������������������������(10���) + if (timestamp.toString().length == 10) timestamp *= 1000 + let timer = (new Date()).getTime() - timestamp + timer = parseInt(timer / 1000) + // ������������5������,���������"������",������������������ + let tips = '' + switch (true) { + case timer < 300: + tips = '������' + break + case timer >= 300 && timer < 3600: + tips = `${parseInt(timer / 60)}���������` + break + case timer >= 3600 && timer < 86400: + tips = `${parseInt(timer / 3600)}���������` + break + case timer >= 86400 && timer < 2592000: + tips = `${parseInt(timer / 86400)}������` + break + default: + // ������format���false���������������������������������������xx������ + if (format === false) { + if (timer >= 2592000 && timer < 365 * 86400) { + tips = `${parseInt(timer / (86400 * 30))}���������` + } else { + tips = `${parseInt(timer / (86400 * 365))}������` + } + } else { + tips = timeFormat(timestamp, format) + } + } + return tips +} + +/** + * @description ������������ + * @param String str ������������������������������ + * @param String pos both(������)|left|right|all ������both + */ +function trim(str, pos = 'both') { + str = String(str) + if (pos == 'both') { + return str.replace(/^\s+|\s+$/g, '') + } + if (pos == 'left') { + return str.replace(/^\s*/, '') + } + if (pos == 'right') { + return str.replace(/(\s*$)/g, '') + } + if (pos == 'all') { + return str.replace(/\s+/g, '') + } + return str +} + +/** + * @description ���������url������ + * @param {object} data,������ + * @param {Boolean} isPrefix,������������������"?" + * @param {string} arrayFormat ������ indices|brackets|repeat|comma + */ +function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') { + const prefix = isPrefix ? '?' : '' + const _result = [] + if (['indices', 'brackets', 'repeat', 'comma'].indexOf(arrayFormat) == -1) arrayFormat = 'brackets' + for (const key in data) { + const value = data[key] + // ��������������������� + if (['', undefined, null].indexOf(value) >= 0) { + continue + } + // ��������������������������������� + if (value.constructor === Array) { + // e.g. {ids: [1, 2, 3]} + switch (arrayFormat) { + case 'indices': + // ������: ids[0]=1&ids[1]=2&ids[2]=3 + for (let i = 0; i < value.length; i++) { + _result.push(`${key}[${i}]=${value[i]}`) + } + break + case 'brackets': + // ������: ids[]=1&ids[]=2&ids[]=3 + value.forEach((_value) => { + _result.push(`${key}[]=${_value}`) + }) + break + case 'repeat': + // ������: ids=1&ids=2&ids=3 + value.forEach((_value) => { + _result.push(`${key}=${_value}`) + }) + break + case 'comma': + // ������: ids=1,2,3 + let commaStr = '' + value.forEach((_value) => { + commaStr += (commaStr ? ',' : '') + _value + }) + _result.push(`${key}=${commaStr}`) + break + default: + value.forEach((_value) => { + _result.push(`${key}[]=${_value}`) + }) + } + } else { + _result.push(`${key}=${value}`) + } + } + return _result.length ? prefix + _result.join('&') : '' +} + +/** + * ��������������������� + * @param {String} title ��������������������������� icon ��������������� + * @param {Number} duration ������������������������������������������������2000 + */ +function toast(title, duration = 2000) { + uni.showToast({ + title: String(title), + icon: 'none', + duration + }) +} + +/** + * @description ������������type���,��������������������� + * @param {String} type ������������,primary|info|error|warning|success + * @param {boolean} fill ������������fill��������������������� + */ +function type2icon(type = 'success', fill = false) { + // ������������������,���������success + if (['primary', 'info', 'error', 'warning', 'success'].indexOf(type) == -1) type = 'success' + let iconName = '' + // ������(2019-12-12),info���primary��������������������� + switch (type) { + case 'primary': + iconName = 'info-circle' + break + case 'info': + iconName = 'info-circle' + break + case 'error': + iconName = 'close-circle' + break + case 'warning': + iconName = 'error-circle' + break + case 'success': + iconName = 'checkmark-circle' + break + default: + iconName = 'checkmark-circle' + } + // ���������������������,������-fill,���icon������������,���������������������������-fill��� + if (fill) iconName += '-fill' + return iconName +} + +/** + * @description ��������������� + * @param {number|string} number ��������������������� + * @param {number} decimals ������������������ + * @param {string} decimalPoint ��������������� + * @param {string} thousandsSeparator ��������������� + * @returns {string} ��������������������� + */ +function priceFormat(number, decimals = 0, decimalPoint = '.', thousandsSeparator = ',') { + number = (`${number}`).replace(/[^0-9+-Ee.]/g, '') + const n = !isFinite(+number) ? 0 : +number + const prec = !isFinite(+decimals) ? 0 : Math.abs(decimals) + const sep = (typeof thousandsSeparator === 'undefined') ? ',' : thousandsSeparator + const dec = (typeof decimalPoint === 'undefined') ? '.' : decimalPoint + let s = '' + + s = (prec ? round(n, prec) + '' : `${Math.round(n)}`).split('.') + const re = /(-?\d+)(\d{3})/ + while (re.test(s[0])) { + s[0] = s[0].replace(re, `$1${sep}$2`) + } + + if ((s[1] || '').length < prec) { + s[1] = s[1] || '' + s[1] += new Array(prec - s[1].length + 1).join('0') + } + return s.join(dec) +} + +/** + * @description ������duration��� + * ������������ms������s������������������������������������������������ms������������������������������������s������ + * ���������30������������������300������30������������������������������������300ms������������������300s��������������������� + * @param {String|number} value ������: "1s"|"100ms"|1|100 + * @param {boolean} unit ������: ���������false ������������number + * @return {string|number} + */ +function getDuration(value, unit = true) { + const valueNum = parseInt(value) + if (unit) { + if (/s$/.test(value)) return value + return value > 30 ? `${value}ms` : `${value}s` + } + if (/ms$/.test(value)) return valueNum + if (/s$/.test(value)) return valueNum > 30 ? valueNum : valueNum * 1000 + return valueNum +} + +/** + * @description ������������������������������ + * @param {String} value ������������������ + */ +function padZero(value) { + return `00${value}`.slice(-2) +} + +/** + * @description ���u-form���������������������������������������������������������������������u-form������������������ + * @param {*} instance + * @param {*} event + */ +function formValidate(instance, event) { + const formItem = uni.$u.$parent.call(instance, 'u-form-item') + const form = uni.$u.$parent.call(instance, 'u-form') + // ���������������������input������textarea������������������������u-form-item������u-form���������������form���validate������ + // ���������form-item���pros���������form��������������������������������� + if (formItem && form) { + form.validateField(formItem.prop, () => {}, event) + } +} + +/** + * @description ���������������������������������������������������'a.b.c'��������������������������������������������������� + * @param {object} obj ������ + * @param {string} key ��������������������������� + * @returns {*} + */ +function getProperty(obj, key) { + if (!obj) { + return + } + if (typeof key !== 'string' || key === '') { + return '' + } + if (key.indexOf('.') !== -1) { + const keys = key.split('.') + let firstObj = obj[keys[0]] || {} + + for (let i = 1; i < keys.length; i++) { + if (firstObj) { + firstObj = firstObj[keys[i]] + } + } + return firstObj + } + return obj[key] +} + +/** + * @description ���������������������������������'a.b.c'��������������������� + * @param {object} obj ������ + * @param {string} key ��������������������� + * @param {string} value ������������ + */ +function setProperty(obj, key, value) { + if (!obj) { + return + } + // ������������ + const inFn = function(_obj, keys, v) { + // ������������������key + if (keys.length === 1) { + _obj[keys[0]] = v + return + } + // 0~length-1���key + while (keys.length > 1) { + const k = keys[0] + if (!_obj[k] || (typeof _obj[k] !== 'object')) { + _obj[k] = {} + } + const key = keys.shift() + // ������������������������������������������������������������������ + inFn(_obj[k], keys, v) + } + } + + if (typeof key !== 'string' || key === '') { + + } else if (key.indexOf('.') !== -1) { // ��������������������������� + const keys = key.split('.') + inFn(obj, keys, value) + } else { + obj[key] = value + } +} + +/** + * @description ������������������������ + */ +function page() { + const pages = getCurrentPages() + // ���������������������(������������������redirectTo������������������)���pages������������������ + return `/${pages[pages.length - 1]?.route ?? ''}` +} + +/** + * @description ��������������������������������� + */ +function pages() { + const pages = getCurrentPages() + return pages +} + +/** + * ������������������������������������ + * @param back {number} [0] - 0���������������������������������������������������0���������������������������������-1 ������������������������������������������0��� + */ +function getHistoryPage(back = 0) { + const pages = getCurrentPages() + const len = pages.length + return pages[len - 1 + back] +} + +/** + * @description ������uView��������������� + * @param {object} props ������������props������ + * @param {object} config ������������config������ + * @param {object} color ������������color������ + * @param {object} zIndex ������������zIndex������ + */ +function setConfig({ + props = {}, + config = {}, + color = {}, + zIndex = {} +}) { + const { + deepMerge, + } = uni.$u + uni.$u.config = deepMerge(uni.$u.config, config) + uni.$u.props = deepMerge(uni.$u.props, props) + uni.$u.color = deepMerge(uni.$u.color, color) + uni.$u.zIndex = deepMerge(uni.$u.zIndex, zIndex) +} + +export default { + range, + getPx, + sleep, + os, + sys, + random, + guid, + $parent, + addStyle, + addUnit, + deepClone, + deepMerge, + error, + randomArray, + timeFormat, + timeFrom, + trim, + queryParams, + toast, + type2icon, + priceFormat, + getDuration, + padZero, + formValidate, + getProperty, + setProperty, + page, + pages, + getHistoryPage, + setConfig +} diff --git a/uni_modules/uview-ui/libs/function/platform.js b/uni_modules/uview-ui/libs/function/platform.js new file mode 100644 index 0000000..d6b926e --- /dev/null +++ b/uni_modules/uview-ui/libs/function/platform.js @@ -0,0 +1,75 @@ +/** + * ��������� + * ���������������������vue-cli���������������������vue.config.js������������������������������ + * module.exports = { + * transpileDependencies: ['uview-v2'] + * } + */ + +let platform = 'none' + +// #ifdef VUE3 +platform = 'vue3' +// #endif + +// #ifdef VUE2 +platform = 'vue2' +// #endif + +// #ifdef APP-PLUS +platform = 'plus' +// #endif + +// #ifdef APP-NVUE +platform = 'nvue' +// #endif + +// #ifdef H5 +platform = 'h5' +// #endif + +// #ifdef MP-WEIXIN +platform = 'weixin' +// #endif + +// #ifdef MP-ALIPAY +platform = 'alipay' +// #endif + +// #ifdef MP-BAIDU +platform = 'baidu' +// #endif + +// #ifdef MP-TOUTIAO +platform = 'toutiao' +// #endif + +// #ifdef MP-QQ +platform = 'qq' +// #endif + +// #ifdef MP-KUAISHOU +platform = 'kuaishou' +// #endif + +// #ifdef MP-360 +platform = '360' +// #endif + +// #ifdef MP +platform = 'mp' +// #endif + +// #ifdef QUICKAPP-WEBVIEW +platform = 'quickapp-webview' +// #endif + +// #ifdef QUICKAPP-WEBVIEW-HUAWEI +platform = 'quickapp-webview-huawei' +// #endif + +// #ifdef QUICKAPP-WEBVIEW-UNION +platform = 'quckapp-webview-union' +// #endif + +export default platform diff --git a/uni_modules/uview-ui/libs/function/test.js b/uni_modules/uview-ui/libs/function/test.js new file mode 100644 index 0000000..c776437 --- /dev/null +++ b/uni_modules/uview-ui/libs/function/test.js @@ -0,0 +1,288 @@ +/** + * ������������������������ + */ +function email(value) { + return /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(value) +} + +/** + * ������������������ + */ +function mobile(value) { + return /^1([3589]\d|4[5-9]|6[1-2,4-7]|7[0-8])\d{8}$/.test(value) +} + +/** + * ������URL������ + */ +function url(value) { + return /^((https|http|ftp|rtsp|mms):\/\/)(([0-9a-zA-Z_!~*'().&=+$%-]+: )?[0-9a-zA-Z_!~*'().&=+$%-]+@)?(([0-9]{1,3}.){3}[0-9]{1,3}|([0-9a-zA-Z_!~*'()-]+.)*([0-9a-zA-Z][0-9a-zA-Z-]{0,61})?[0-9a-zA-Z].[a-zA-Z]{2,6})(:[0-9]{1,4})?((\/?)|(\/[0-9a-zA-Z_!~*'().;?:@&=+$,%#-]+)+\/?)$/ + .test(value) +} + +/** + * ������������������ + */ +function date(value) { + if (!value) return false + // ���������������������������������������(���������������������)������������������������new Date������������������������������ + if (number(value)) value = +value + return !/Invalid|NaN/.test(new Date(value).toString()) +} + +/** + * ������ISO��������������������� + */ +function dateISO(value) { + return /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value) +} + +/** + * ��������������������� + */ +function number(value) { + return /^[\+-]?(\d+\.?\d*|\.\d+|\d\.\d+e\+\d+)$/.test(value) +} + +/** + * ��������������� + */ +function string(value) { + return typeof value === 'string' +} + +/** + * ������������ + */ +function digits(value) { + return /^\d+$/.test(value) +} + +/** + * ��������������������� + */ +function idCard(value) { + return /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test( + value + ) +} + +/** + * ��������������� + */ +function carNo(value) { + // ��������������� + const xreg = /^[���������������������������������������������������������������������������������������������������A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/ + // ��������� + const creg = /^[���������������������������������������������������������������������������������������������������A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9���������������]{1}$/ + if (value.length === 7) { + return creg.test(value) + } if (value.length === 8) { + return xreg.test(value) + } + return false +} + +/** + * ������,���������2��������� + */ +function amount(value) { + // ������������������������������������ + return /^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0\.\d{1,2}$/.test(value) +} + +/** + * ������ + */ +function chinese(value) { + const reg = /^[\u4e00-\u9fa5]+$/gi + return reg.test(value) +} + +/** + * ������������������ + */ +function letter(value) { + return /^[a-zA-Z]*$/.test(value) +} + +/** + * ��������������������������� + */ +function enOrNum(value) { + // ������������������ + const reg = /^[0-9a-zA-Z]*$/g + return reg.test(value) +} + +/** + * ��������������������������� + */ +function contains(value, param) { + return value.indexOf(param) >= 0 +} + +/** + * ���������������������[min, max] + */ +function range(value, param) { + return value >= param[0] && value <= param[1] +} + +/** + * ������������������������[min, max] + */ +function rangeLength(value, param) { + return value.length >= param[0] && value.length <= param[1] +} + +/** + * ������������������ + */ +function landline(value) { + const reg = /^\d{3,4}-\d{7,8}(-\d{3,4})?$/ + return reg.test(value) +} + +/** + * ������������������ + */ +function empty(value) { + switch (typeof value) { + case 'undefined': + return true + case 'string': + if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true + break + case 'boolean': + if (!value) return true + break + case 'number': + if (value === 0 || isNaN(value)) return true + break + case 'object': + if (value === null || value.length === 0) return true + for (const i in value) { + return false + } + return true + } + return false +} + +/** + * ������json��������� + */ +function jsonString(value) { + if (typeof value === 'string') { + try { + const obj = JSON.parse(value) + if (typeof obj === 'object' && obj) { + return true + } + return false + } catch (e) { + return false + } + } + return false +} + +/** + * ������������ + */ +function array(value) { + if (typeof Array.isArray === 'function') { + return Array.isArray(value) + } + return Object.prototype.toString.call(value) === '[object Array]' +} + +/** + * ������������ + */ +function object(value) { + return Object.prototype.toString.call(value) === '[object Object]' +} + +/** + * ��������������������� + */ +function code(value, len = 6) { + return new RegExp(`^\\d{${len}}$`).test(value) +} + +/** + * ������������������ + * @param {Object} value + */ +function func(value) { + return typeof value === 'function' +} + +/** + * ������promise������ + * @param {Object} value + */ +function promise(value) { + return object(value) && func(value.then) && func(value.catch) +} + +/** ������������������ + * @param {Object} value + */ +function image(value) { + const newValue = value.split('?')[0] + const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i + return IMAGE_REGEXP.test(newValue) +} + +/** + * ������������������ + * @param {Object} value + */ +function video(value) { + const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv|m3u8)/i + return VIDEO_REGEXP.test(value) +} + +/** + * ��������������������� + * @param {Object} + * @return {Boolean} + */ +function regExp(o) { + return o && Object.prototype.toString.call(o) === '[object RegExp]' +} + +export default { + email, + mobile, + url, + date, + dateISO, + number, + digits, + idCard, + carNo, + amount, + chinese, + letter, + enOrNum, + contains, + range, + rangeLength, + empty, + isEmpty: empty, + jsonString, + landline, + object, + array, + code, + func, + promise, + video, + image, + regExp, + string +} diff --git a/uni_modules/uview-ui/libs/function/throttle.js b/uni_modules/uview-ui/libs/function/throttle.js new file mode 100644 index 0000000..2f33611 --- /dev/null +++ b/uni_modules/uview-ui/libs/function/throttle.js @@ -0,0 +1,30 @@ +let timer; let + flag +/** + * ������������������������������������������������������ + * + * @param {Function} func ������������������������ + * @param {Number} wait ��������������� + * @param {Boolean} immediate ������������������ + * @return null + */ +function throttle(func, wait = 500, immediate = true) { + if (immediate) { + if (!flag) { + flag = true + // ������������������������������wait������������������������ + typeof func === 'function' && func() + timer = setTimeout(() => { + flag = false + }, wait) + } + } else if (!flag) { + flag = true + // ���������������������������������wait��������������������������� + timer = setTimeout(() => { + flag = false + typeof func === 'function' && func() + }, wait) + } +} +export default throttle diff --git a/uni_modules/uview-ui/libs/luch-request/adapters/index.js b/uni_modules/uview-ui/libs/luch-request/adapters/index.js new file mode 100644 index 0000000..e03cf5f --- /dev/null +++ b/uni_modules/uview-ui/libs/luch-request/adapters/index.js @@ -0,0 +1,97 @@ +import buildURL from '../helpers/buildURL' +import buildFullPath from '../core/buildFullPath' +import settle from '../core/settle' +import { isUndefined } from '../utils' + +/** + * ������������������������������ + * @param {Array} keys - ��������������� + * @param {Object} config2 - ������ + * @return {{}} - ������������������ + */ +const mergeKeys = (keys, config2) => { + const config = {} + keys.forEach((prop) => { + if (!isUndefined(config2[prop])) { + config[prop] = config2[prop] + } + }) + return config +} +export default (config) => new Promise((resolve, reject) => { + const fullPath = buildURL(buildFullPath(config.baseURL, config.url), config.params) + const _config = { + url: fullPath, + header: config.header, + complete: (response) => { + config.fullPath = fullPath + response.config = config + try { + // ������������������������json ��������������� + if (typeof response.data === 'string') { + response.data = JSON.parse(response.data) + } + // eslint-disable-next-line no-empty + } catch (e) { + } + settle(resolve, reject, response) + } + } + let requestTask + if (config.method === 'UPLOAD') { + delete _config.header['content-type'] + delete _config.header['Content-Type'] + const otherConfig = { + // #ifdef MP-ALIPAY + fileType: config.fileType, + // #endif + filePath: config.filePath, + name: config.name + } + const optionalKeys = [ + // #ifdef APP-PLUS || H5 + 'files', + // #endif + // #ifdef H5 + 'file', + // #endif + // #ifdef H5 || APP-PLUS + 'timeout', + // #endif + 'formData' + ] + requestTask = uni.uploadFile({ ..._config, ...otherConfig, ...mergeKeys(optionalKeys, config) }) + } else if (config.method === 'DOWNLOAD') { + // #ifdef H5 || APP-PLUS + if (!isUndefined(config.timeout)) { + _config.timeout = config.timeout + } + // #endif + requestTask = uni.downloadFile(_config) + } else { + const optionalKeys = [ + 'data', + 'method', + // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN + 'timeout', + // #endif + 'dataType', + // #ifndef MP-ALIPAY + 'responseType', + // #endif + // #ifdef APP-PLUS + 'sslVerify', + // #endif + // #ifdef H5 + 'withCredentials', + // #endif + // #ifdef APP-PLUS + 'firstIpv4' + // #endif + ] + requestTask = uni.request({ ..._config, ...mergeKeys(optionalKeys, config) }) + } + if (config.getTask) { + config.getTask(requestTask, config) + } +}) diff --git a/uni_modules/uview-ui/libs/luch-request/core/InterceptorManager.js b/uni_modules/uview-ui/libs/luch-request/core/InterceptorManager.js new file mode 100644 index 0000000..3e8728d --- /dev/null +++ b/uni_modules/uview-ui/libs/luch-request/core/InterceptorManager.js @@ -0,0 +1,50 @@ +'use strict' + +function InterceptorManager() { + this.handlers = [] +} + +/** + * Add a new interceptor to the stack + * + * @param {Function} fulfilled The function to handle `then` for a `Promise` + * @param {Function} rejected The function to handle `reject` for a `Promise` + * + * @return {Number} An ID used to remove interceptor later + */ +InterceptorManager.prototype.use = function use(fulfilled, rejected) { + this.handlers.push({ + fulfilled, + rejected + }) + return this.handlers.length - 1 +} + +/** + * Remove an interceptor from the stack + * + * @param {Number} id The ID that was returned by `use` + */ +InterceptorManager.prototype.eject = function eject(id) { + if (this.handlers[id]) { + this.handlers[id] = null + } +} + +/** + * Iterate over all the registered interceptors + * + * This method is particularly useful for skipping over any + * interceptors that may have become `null` calling `eject`. + * + * @param {Function} fn The function to call for each interceptor + */ +InterceptorManager.prototype.forEach = function forEach(fn) { + this.handlers.forEach((h) => { + if (h !== null) { + fn(h) + } + }) +} + +export default InterceptorManager diff --git a/uni_modules/uview-ui/libs/luch-request/core/Request.js b/uni_modules/uview-ui/libs/luch-request/core/Request.js new file mode 100644 index 0000000..cc48566 --- /dev/null +++ b/uni_modules/uview-ui/libs/luch-request/core/Request.js @@ -0,0 +1,198 @@ +/** + * @Class Request + * @description luch-request http������������ + * @version 3.0.7 + * @Author lu-ch + * @Date 2021-09-04 + * @Email webwork.s@qq.com + * ������: https://www.quanzhan.co/luch-request/ + * github: https://github.com/lei-mu/luch-request + * DCloud: http://ext.dcloud.net.cn/plugin?id=392 + * HBuilderX: beat-3.0.4 alpha-3.0.4 + */ + +import dispatchRequest from './dispatchRequest' +import InterceptorManager from './InterceptorManager' +import mergeConfig from './mergeConfig' +import defaults from './defaults' +import { isPlainObject } from '../utils' +import clone from '../utils/clone' + +export default class Request { + /** + * @param {Object} arg - ������������ + * @param {String} arg.baseURL - ��������������� + * @param {Object} arg.header - ������header + * @param {String} arg.method = [GET|POST|PUT|DELETE|CONNECT|HEAD|OPTIONS|TRACE] - ������������������������ + * @param {String} arg.dataType = [json] - ���������������dataType + * @param {String} arg.responseType = [text|arraybuffer] - ���������������responseType������������������������������ + * @param {Object} arg.custom - ������������������������������ + * @param {Number} arg.timeout - ������������������������������������ ms���������60000���H5(HBuilderX 2.9.9+)���APP(HBuilderX 2.9.9+)���������������������2.10.0������������������������ + * @param {Boolean} arg.sslVerify - ��������������������������� ssl ���������������true.���App������������������HBuilderX 2.3.3+��� + * @param {Boolean} arg.withCredentials - ���������������������������������������������������cookies������������false������H5���������HBuilderX 2.6.15+��� + * @param {Boolean} arg.firstIpv4 - ���DNS���������������������ipv4���������false������ App-Android ������ (HBuilderX 2.8.0+) + * @param {Function(statusCode):Boolean} arg.validateStatus - ������������������������������������������statusCode >= 200 && statusCode < 300 + */ + constructor(arg = {}) { + if (!isPlainObject(arg)) { + arg = {} + console.warn('������������������������������������Object') + } + this.config = clone({ ...defaults, ...arg }) + this.interceptors = { + request: new InterceptorManager(), + response: new InterceptorManager() + } + } + + /** + * @Function + * @param {Request~setConfigCallback} f - ������������������������ + */ + setConfig(f) { + this.config = f(this.config) + } + + middleware(config) { + config = mergeConfig(this.config, config) + const chain = [dispatchRequest, undefined] + let promise = Promise.resolve(config) + + this.interceptors.request.forEach((interceptor) => { + chain.unshift(interceptor.fulfilled, interceptor.rejected) + }) + + this.interceptors.response.forEach((interceptor) => { + chain.push(interceptor.fulfilled, interceptor.rejected) + }) + + while (chain.length) { + promise = promise.then(chain.shift(), chain.shift()) + } + + return promise + } + + /** + * @Function + * @param {Object} config - ��������������� + * @prop {String} options.url - ������������ + * @prop {Object} options.data - ������������ + * @prop {Object} [options.responseType = config.responseType] [text|arraybuffer] - ��������������������� + * @prop {Object} [options.dataType = config.dataType] - ������������ json��������������������������������������� JSON.parse + * @prop {Object} [options.header = config.header] - ������header + * @prop {Object} [options.method = config.method] - ������������ + * @returns {Promise<unknown>} + */ + request(config = {}) { + return this.middleware(config) + } + + get(url, options = {}) { + return this.middleware({ + url, + method: 'GET', + ...options + }) + } + + post(url, data, options = {}) { + return this.middleware({ + url, + data, + method: 'POST', + ...options + }) + } + + // #ifndef MP-ALIPAY + put(url, data, options = {}) { + return this.middleware({ + url, + data, + method: 'PUT', + ...options + }) + } + + // #endif + + // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU + delete(url, data, options = {}) { + return this.middleware({ + url, + data, + method: 'DELETE', + ...options + }) + } + + // #endif + + // #ifdef H5 || MP-WEIXIN + connect(url, data, options = {}) { + return this.middleware({ + url, + data, + method: 'CONNECT', + ...options + }) + } + + // #endif + + // #ifdef H5 || MP-WEIXIN || MP-BAIDU + head(url, data, options = {}) { + return this.middleware({ + url, + data, + method: 'HEAD', + ...options + }) + } + + // #endif + + // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU + options(url, data, options = {}) { + return this.middleware({ + url, + data, + method: 'OPTIONS', + ...options + }) + } + + // #endif + + // #ifdef H5 || MP-WEIXIN + trace(url, data, options = {}) { + return this.middleware({ + url, + data, + method: 'TRACE', + ...options + }) + } + + // #endif + + upload(url, config = {}) { + config.url = url + config.method = 'UPLOAD' + return this.middleware(config) + } + + download(url, config = {}) { + config.url = url + config.method = 'DOWNLOAD' + return this.middleware(config) + } +} + +/** + * setConfig������ + * @return {Object} - ������������������config + * @callback Request~setConfigCallback + * @param {Object} config - ������������config + */ diff --git a/uni_modules/uview-ui/libs/luch-request/core/buildFullPath.js b/uni_modules/uview-ui/libs/luch-request/core/buildFullPath.js new file mode 100644 index 0000000..5eb8a17 --- /dev/null +++ b/uni_modules/uview-ui/libs/luch-request/core/buildFullPath.js @@ -0,0 +1,20 @@ +'use strict' + +import isAbsoluteURL from '../helpers/isAbsoluteURL' +import combineURLs from '../helpers/combineURLs' + +/** + * Creates a new URL by combining the baseURL with the requestedURL, + * only when the requestedURL is not already an absolute URL. + * If the requestURL is absolute, this function returns the requestedURL untouched. + * + * @param {string} baseURL The base URL + * @param {string} requestedURL Absolute or relative URL to combine + * @returns {string} The combined full path + */ +export default function buildFullPath(baseURL, requestedURL) { + if (baseURL && !isAbsoluteURL(requestedURL)) { + return combineURLs(baseURL, requestedURL) + } + return requestedURL +} diff --git a/uni_modules/uview-ui/libs/luch-request/core/defaults.js b/uni_modules/uview-ui/libs/luch-request/core/defaults.js new file mode 100644 index 0000000..be375a9 --- /dev/null +++ b/uni_modules/uview-ui/libs/luch-request/core/defaults.js @@ -0,0 +1,29 @@ +/** + * ��������������������� + */ + +export default { + baseURL: '', + header: {}, + method: 'GET', + dataType: 'json', + // #ifndef MP-ALIPAY + responseType: 'text', + // #endif + custom: {}, + // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN + timeout: 60000, + // #endif + // #ifdef APP-PLUS + sslVerify: true, + // #endif + // #ifdef H5 + withCredentials: false, + // #endif + // #ifdef APP-PLUS + firstIpv4: false, + // #endif + validateStatus: function validateStatus(status) { + return status >= 200 && status < 300 + } +} diff --git a/uni_modules/uview-ui/libs/luch-request/core/dispatchRequest.js b/uni_modules/uview-ui/libs/luch-request/core/dispatchRequest.js new file mode 100644 index 0000000..724545c --- /dev/null +++ b/uni_modules/uview-ui/libs/luch-request/core/dispatchRequest.js @@ -0,0 +1,3 @@ +import adapter from '../adapters/index' + +export default (config) => adapter(config) diff --git a/uni_modules/uview-ui/libs/luch-request/core/mergeConfig.js b/uni_modules/uview-ui/libs/luch-request/core/mergeConfig.js new file mode 100644 index 0000000..08f8b9b --- /dev/null +++ b/uni_modules/uview-ui/libs/luch-request/core/mergeConfig.js @@ -0,0 +1,103 @@ +import { deepMerge, isUndefined } from '../utils' + +/** + * ��������������������������������������������������������������������������������������������������������������������� + * @param {Array} keys - ��������� + * @param {Object} globalsConfig - ��������������������� + * @param {Object} config2 - ������������ + * @return {{}} + */ +const mergeKeys = (keys, globalsConfig, config2) => { + const config = {} + keys.forEach((prop) => { + if (!isUndefined(config2[prop])) { + config[prop] = config2[prop] + } else if (!isUndefined(globalsConfig[prop])) { + config[prop] = globalsConfig[prop] + } + }) + return config +} +/** + * + * @param globalsConfig - ��������������������������� + * @param config2 - ��������������������� + * @return - ������������������ + */ +export default (globalsConfig, config2 = {}) => { + const method = config2.method || globalsConfig.method || 'GET' + let config = { + baseURL: globalsConfig.baseURL || '', + method, + url: config2.url || '', + params: config2.params || {}, + custom: { ...(globalsConfig.custom || {}), ...(config2.custom || {}) }, + header: deepMerge(globalsConfig.header || {}, config2.header || {}) + } + const defaultToConfig2Keys = ['getTask', 'validateStatus'] + config = { ...config, ...mergeKeys(defaultToConfig2Keys, globalsConfig, config2) } + + // eslint-disable-next-line no-empty + if (method === 'DOWNLOAD') { + // #ifdef H5 || APP-PLUS + if (!isUndefined(config2.timeout)) { + config.timeout = config2.timeout + } else if (!isUndefined(globalsConfig.timeout)) { + config.timeout = globalsConfig.timeout + } + // #endif + } else if (method === 'UPLOAD') { + delete config.header['content-type'] + delete config.header['Content-Type'] + const uploadKeys = [ + // #ifdef APP-PLUS || H5 + 'files', + // #endif + // #ifdef MP-ALIPAY + 'fileType', + // #endif + // #ifdef H5 + 'file', + // #endif + 'filePath', + 'name', + // #ifdef H5 || APP-PLUS + 'timeout', + // #endif + 'formData' + ] + uploadKeys.forEach((prop) => { + if (!isUndefined(config2[prop])) { + config[prop] = config2[prop] + } + }) + // #ifdef H5 || APP-PLUS + if (isUndefined(config.timeout) && !isUndefined(globalsConfig.timeout)) { + config.timeout = globalsConfig.timeout + } + // #endif + } else { + const defaultsKeys = [ + 'data', + // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN + 'timeout', + // #endif + 'dataType', + // #ifndef MP-ALIPAY + 'responseType', + // #endif + // #ifdef APP-PLUS + 'sslVerify', + // #endif + // #ifdef H5 + 'withCredentials', + // #endif + // #ifdef APP-PLUS + 'firstIpv4' + // #endif + ] + config = { ...config, ...mergeKeys(defaultsKeys, globalsConfig, config2) } + } + + return config +} diff --git a/uni_modules/uview-ui/libs/luch-request/core/settle.js b/uni_modules/uview-ui/libs/luch-request/core/settle.js new file mode 100644 index 0000000..8d3638f --- /dev/null +++ b/uni_modules/uview-ui/libs/luch-request/core/settle.js @@ -0,0 +1,16 @@ +/** + * Resolve or reject a Promise based on response status. + * + * @param {Function} resolve A function that resolves the promise. + * @param {Function} reject A function that rejects the promise. + * @param {object} response The response. + */ +export default function settle(resolve, reject, response) { + const { validateStatus } = response.config + const status = response.statusCode + if (status && (!validateStatus || validateStatus(status))) { + resolve(response) + } else { + reject(response) + } +} diff --git a/uni_modules/uview-ui/libs/luch-request/helpers/buildURL.js b/uni_modules/uview-ui/libs/luch-request/helpers/buildURL.js new file mode 100644 index 0000000..472ad6a --- /dev/null +++ b/uni_modules/uview-ui/libs/luch-request/helpers/buildURL.js @@ -0,0 +1,69 @@ +'use strict' + +import * as utils from '../utils' + +function encode(val) { + return encodeURIComponent(val) + .replace(/%40/gi, '@') + .replace(/%3A/gi, ':') + .replace(/%24/g, '$') + .replace(/%2C/gi, ',') + .replace(/%20/g, '+') + .replace(/%5B/gi, '[') + .replace(/%5D/gi, ']') +} + +/** + * Build a URL by appending params to the end + * + * @param {string} url The base of the url (e.g., http://www.google.com) + * @param {object} [params] The params to be appended + * @returns {string} The formatted url + */ +export default function buildURL(url, params) { + /* eslint no-param-reassign:0 */ + if (!params) { + return url + } + + let serializedParams + if (utils.isURLSearchParams(params)) { + serializedParams = params.toString() + } else { + const parts = [] + + utils.forEach(params, (val, key) => { + if (val === null || typeof val === 'undefined') { + return + } + + if (utils.isArray(val)) { + key = `${key}[]` + } else { + val = [val] + } + + utils.forEach(val, (v) => { + if (utils.isDate(v)) { + v = v.toISOString() + } else if (utils.isObject(v)) { + v = JSON.stringify(v) + } + parts.push(`${encode(key)}=${encode(v)}`) + }) + }) + + serializedParams = parts.join('&') + } + + if (serializedParams) { + const hashmarkIndex = url.indexOf('#') + if (hashmarkIndex !== -1) { + url = url.slice(0, hashmarkIndex) + } + + url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams + } + + return url +} diff --git a/uni_modules/uview-ui/libs/luch-request/helpers/combineURLs.js b/uni_modules/uview-ui/libs/luch-request/helpers/combineURLs.js new file mode 100644 index 0000000..ac7c124 --- /dev/null +++ b/uni_modules/uview-ui/libs/luch-request/helpers/combineURLs.js @@ -0,0 +1,14 @@ +'use strict' + +/** + * Creates a new URL by combining the specified URLs + * + * @param {string} baseURL The base URL + * @param {string} relativeURL The relative URL + * @returns {string} The combined URL + */ +export default function combineURLs(baseURL, relativeURL) { + return relativeURL + ? `${baseURL.replace(/\/+$/, '')}/${relativeURL.replace(/^\/+/, '')}` + : baseURL +} diff --git a/uni_modules/uview-ui/libs/luch-request/helpers/isAbsoluteURL.js b/uni_modules/uview-ui/libs/luch-request/helpers/isAbsoluteURL.js new file mode 100644 index 0000000..63c6647 --- /dev/null +++ b/uni_modules/uview-ui/libs/luch-request/helpers/isAbsoluteURL.js @@ -0,0 +1,14 @@ +'use strict' + +/** + * Determines whether the specified URL is absolute + * + * @param {string} url The URL to test + * @returns {boolean} True if the specified URL is absolute, otherwise false + */ +export default function isAbsoluteURL(url) { + // A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL). + // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed + // by any combination of letters, digits, plus, period, or hyphen. + return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url) +} diff --git a/uni_modules/uview-ui/libs/luch-request/index.d.ts b/uni_modules/uview-ui/libs/luch-request/index.d.ts new file mode 100644 index 0000000..e939ce1 --- /dev/null +++ b/uni_modules/uview-ui/libs/luch-request/index.d.ts @@ -0,0 +1,116 @@ +type AnyObject = Record<string | number | symbol, any> +type HttpPromise<T> = Promise<HttpResponse<T>>; +type Tasks = UniApp.RequestTask | UniApp.UploadTask | UniApp.DownloadTask +export interface RequestTask { + abort: () => void; + offHeadersReceived: () => void; + onHeadersReceived: () => void; +} +export interface HttpRequestConfig<T = Tasks> { + /** ��������������� */ + baseURL?: string; + /** ��������������������������� */ + url?: string; + + /** ��������������������������������������������������� */ + params?: AnyObject; + /** ��������������� */ + data?: AnyObject; + + /** ��������������� key */ + name?: string; + /** HTTP ������������������������ form data */ + formData?: AnyObject; + /** ��������������������������������� */ + filePath?: string; + /** ������������������������������������ files ������filePath ��� name ������������App���H5��� 2.6.15+��� */ + files?: Array<{ + name?: string; + file?: File; + uri: string; + }>; + /** ������������������������������H5���2.6.15+��������� */ + file?: File; + + /** ��������������� */ + header?: AnyObject; + /** ������������ */ + method?: "GET" | "POST" | "PUT" | "DELETE" | "CONNECT" | "HEAD" | "OPTIONS" | "TRACE" | "UPLOAD" | "DOWNLOAD"; + /** ������������ json��������������������������������������� JSON.parse */ + dataType?: string; + /** ��������������������������������������������������������� */ + responseType?: "text" | "arraybuffer"; + /** ��������������� */ + custom?: AnyObject; + /** ������������������������������������2.10.0������������������������������ */ + timeout?: number; + /** DNS���������������������ipv4������ App-Android ������ (HBuilderX 2.8.0+) */ + firstIpv4?: boolean; + /** ������ ssl ������ ���5+App������������������HBuilderX 2.3.3+��� */ + sslVerify?: boolean; + /** ������������������������������������cookies������H5���������HBuilderX 2.6.15+��� */ + withCredentials?: boolean; + + /** ���������������������task, options������������������������options��� */ + getTask?: (task: T, options: HttpRequestConfig<T>) => void; + /** ������������������������ */ + validateStatus?: (statusCode: number) => boolean | void; +} +export interface HttpResponse<T = any> { + config: HttpRequestConfig; + statusCode: number; + cookies: Array<string>; + data: T; + errMsg: string; + header: AnyObject; +} +export interface HttpUploadResponse<T = any> { + config: HttpRequestConfig; + statusCode: number; + data: T; + errMsg: string; +} +export interface HttpDownloadResponse extends HttpResponse { + tempFilePath: string; +} +export interface HttpError { + config: HttpRequestConfig; + statusCode?: number; + cookies?: Array<string>; + data?: any; + errMsg: string; + header?: AnyObject; +} +export interface HttpInterceptorManager<V, E = V> { + use( + onFulfilled?: (config: V) => Promise<V> | V, + onRejected?: (config: E) => Promise<E> | E + ): void; + eject(id: number): void; +} +export abstract class HttpRequestAbstract { + constructor(config?: HttpRequestConfig); + config: HttpRequestConfig; + interceptors: { + request: HttpInterceptorManager<HttpRequestConfig, HttpRequestConfig>; + response: HttpInterceptorManager<HttpResponse, HttpError>; + } + middleware<T = any>(config: HttpRequestConfig): HttpPromise<T>; + request<T = any>(config: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>; + get<T = any>(url: string, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>; + upload<T = any>(url: string, config?: HttpRequestConfig<UniApp.UploadTask>): HttpPromise<T>; + delete<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>; + head<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>; + post<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>; + put<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>; + connect<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>; + options<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>; + trace<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>; + + download(url: string, config?: HttpRequestConfig<UniApp.DownloadTask>): Promise<HttpDownloadResponse>; + + setConfig(onSend: (config: HttpRequestConfig) => HttpRequestConfig): void; +} + +declare class HttpRequest extends HttpRequestAbstract { } +export default HttpRequest; diff --git a/uni_modules/uview-ui/libs/luch-request/index.js b/uni_modules/uview-ui/libs/luch-request/index.js new file mode 100644 index 0000000..8fb2b44 --- /dev/null +++ b/uni_modules/uview-ui/libs/luch-request/index.js @@ -0,0 +1,3 @@ +import Request from './core/Request' + +export default Request diff --git a/uni_modules/uview-ui/libs/luch-request/utils.js b/uni_modules/uview-ui/libs/luch-request/utils.js new file mode 100644 index 0000000..847283d --- /dev/null +++ b/uni_modules/uview-ui/libs/luch-request/utils.js @@ -0,0 +1,131 @@ +'use strict' + +// utils is a library of generic helper functions non-specific to axios + +const { toString } = Object.prototype + +/** + * Determine if a value is an Array + * + * @param {Object} val The value to test + * @returns {boolean} True if value is an Array, otherwise false + */ +export function isArray(val) { + return toString.call(val) === '[object Array]' +} + +/** + * Determine if a value is an Object + * + * @param {Object} val The value to test + * @returns {boolean} True if value is an Object, otherwise false + */ +export function isObject(val) { + return val !== null && typeof val === 'object' +} + +/** + * Determine if a value is a Date + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Date, otherwise false + */ +export function isDate(val) { + return toString.call(val) === '[object Date]' +} + +/** + * Determine if a value is a URLSearchParams object + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a URLSearchParams object, otherwise false + */ +export function isURLSearchParams(val) { + return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams +} + +/** + * Iterate over an Array or an Object invoking a function for each item. + * + * If `obj` is an Array callback will be called passing + * the value, index, and complete array for each item. + * + * If 'obj' is an Object callback will be called passing + * the value, key, and complete object for each property. + * + * @param {Object|Array} obj The object to iterate + * @param {Function} fn The callback to invoke for each item + */ +export function forEach(obj, fn) { + // Don't bother if no value provided + if (obj === null || typeof obj === 'undefined') { + return + } + + // Force an array if not already something iterable + if (typeof obj !== 'object') { + /* eslint no-param-reassign:0 */ + obj = [obj] + } + + if (isArray(obj)) { + // Iterate over array values + for (let i = 0, l = obj.length; i < l; i++) { + fn.call(null, obj[i], i, obj) + } + } else { + // Iterate over object keys + for (const key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + fn.call(null, obj[key], key, obj) + } + } + } +} + +/** + * ���������boolean ��� + * @param val + * @returns {boolean} + */ +export function isBoolean(val) { + return typeof val === 'boolean' +} + +/** + * ������������������������{} new Object + * @param {any} obj - ��������������� + * @returns {boolean} + */ +export function isPlainObject(obj) { + return Object.prototype.toString.call(obj) === '[object Object]' +} + +/** + * Function equal to merge with the difference being that no reference + * to original objects is kept. + * + * @see merge + * @param {Object} obj1 Object to merge + * @returns {Object} Result of all merge properties + */ +export function deepMerge(/* obj1, obj2, obj3, ... */) { + const result = {} + function assignValue(val, key) { + if (typeof result[key] === 'object' && typeof val === 'object') { + result[key] = deepMerge(result[key], val) + } else if (typeof val === 'object') { + result[key] = deepMerge({}, val) + } else { + result[key] = val + } + } + for (let i = 0, l = arguments.length; i < l; i++) { + forEach(arguments[i], assignValue) + } + return result +} + +export function isUndefined(val) { + return typeof val === 'undefined' +} diff --git a/uni_modules/uview-ui/libs/luch-request/utils/clone.js b/uni_modules/uview-ui/libs/luch-request/utils/clone.js new file mode 100644 index 0000000..2fee704 --- /dev/null +++ b/uni_modules/uview-ui/libs/luch-request/utils/clone.js @@ -0,0 +1,264 @@ +/* eslint-disable */ +var clone = (function() { + 'use strict'; + + function _instanceof(obj, type) { + return type != null && obj instanceof type; + } + + var nativeMap; + try { + nativeMap = Map; + } catch(_) { + // maybe a reference error because no `Map`. Give it a dummy value that no + // value will ever be an instanceof. + nativeMap = function() {}; + } + + var nativeSet; + try { + nativeSet = Set; + } catch(_) { + nativeSet = function() {}; + } + + var nativePromise; + try { + nativePromise = Promise; + } catch(_) { + nativePromise = function() {}; + } + + /** + * Clones (copies) an Object using deep copying. + * + * This function supports circular references by default, but if you are certain + * there are no circular references in your object, you can save some CPU time + * by calling clone(obj, false). + * + * Caution: if `circular` is false and `parent` contains circular references, + * your program may enter an infinite loop and crash. + * + * @param `parent` - the object to be cloned + * @param `circular` - set to true if the object to be cloned may contain + * circular references. (optional - true by default) + * @param `depth` - set to a number if the object is only to be cloned to + * a particular depth. (optional - defaults to Infinity) + * @param `prototype` - sets the prototype to be used when cloning an object. + * (optional - defaults to parent prototype). + * @param `includeNonEnumerable` - set to true if the non-enumerable properties + * should be cloned as well. Non-enumerable properties on the prototype + * chain will be ignored. (optional - false by default) + */ + function clone(parent, circular, depth, prototype, includeNonEnumerable) { + if (typeof circular === 'object') { + depth = circular.depth; + prototype = circular.prototype; + includeNonEnumerable = circular.includeNonEnumerable; + circular = circular.circular; + } + // maintain two arrays for circular references, where corresponding parents + // and children have the same index + var allParents = []; + var allChildren = []; + + var useBuffer = typeof Buffer != 'undefined'; + + if (typeof circular == 'undefined') + circular = true; + + if (typeof depth == 'undefined') + depth = Infinity; + + // recurse this function so we don't reset allParents and allChildren + function _clone(parent, depth) { + // cloning null always returns null + if (parent === null) + return null; + + if (depth === 0) + return parent; + + var child; + var proto; + if (typeof parent != 'object') { + return parent; + } + + if (_instanceof(parent, nativeMap)) { + child = new nativeMap(); + } else if (_instanceof(parent, nativeSet)) { + child = new nativeSet(); + } else if (_instanceof(parent, nativePromise)) { + child = new nativePromise(function (resolve, reject) { + parent.then(function(value) { + resolve(_clone(value, depth - 1)); + }, function(err) { + reject(_clone(err, depth - 1)); + }); + }); + } else if (clone.__isArray(parent)) { + child = []; + } else if (clone.__isRegExp(parent)) { + child = new RegExp(parent.source, __getRegExpFlags(parent)); + if (parent.lastIndex) child.lastIndex = parent.lastIndex; + } else if (clone.__isDate(parent)) { + child = new Date(parent.getTime()); + } else if (useBuffer && Buffer.isBuffer(parent)) { + if (Buffer.from) { + // Node.js >= 5.10.0 + child = Buffer.from(parent); + } else { + // Older Node.js versions + child = new Buffer(parent.length); + parent.copy(child); + } + return child; + } else if (_instanceof(parent, Error)) { + child = Object.create(parent); + } else { + if (typeof prototype == 'undefined') { + proto = Object.getPrototypeOf(parent); + child = Object.create(proto); + } + else { + child = Object.create(prototype); + proto = prototype; + } + } + + if (circular) { + var index = allParents.indexOf(parent); + + if (index != -1) { + return allChildren[index]; + } + allParents.push(parent); + allChildren.push(child); + } + + if (_instanceof(parent, nativeMap)) { + parent.forEach(function(value, key) { + var keyChild = _clone(key, depth - 1); + var valueChild = _clone(value, depth - 1); + child.set(keyChild, valueChild); + }); + } + if (_instanceof(parent, nativeSet)) { + parent.forEach(function(value) { + var entryChild = _clone(value, depth - 1); + child.add(entryChild); + }); + } + + for (var i in parent) { + var attrs = Object.getOwnPropertyDescriptor(parent, i); + if (attrs) { + child[i] = _clone(parent[i], depth - 1); + } + + try { + var objProperty = Object.getOwnPropertyDescriptor(parent, i); + if (objProperty.set === 'undefined') { + // no setter defined. Skip cloning this property + continue; + } + child[i] = _clone(parent[i], depth - 1); + } catch(e){ + if (e instanceof TypeError) { + // when in strict mode, TypeError will be thrown if child[i] property only has a getter + // we can't do anything about this, other than inform the user that this property cannot be set. + continue + } else if (e instanceof ReferenceError) { + //this may happen in non strict mode + continue + } + } + + } + + if (Object.getOwnPropertySymbols) { + var symbols = Object.getOwnPropertySymbols(parent); + for (var i = 0; i < symbols.length; i++) { + // Don't need to worry about cloning a symbol because it is a primitive, + // like a number or string. + var symbol = symbols[i]; + var descriptor = Object.getOwnPropertyDescriptor(parent, symbol); + if (descriptor && !descriptor.enumerable && !includeNonEnumerable) { + continue; + } + child[symbol] = _clone(parent[symbol], depth - 1); + Object.defineProperty(child, symbol, descriptor); + } + } + + if (includeNonEnumerable) { + var allPropertyNames = Object.getOwnPropertyNames(parent); + for (var i = 0; i < allPropertyNames.length; i++) { + var propertyName = allPropertyNames[i]; + var descriptor = Object.getOwnPropertyDescriptor(parent, propertyName); + if (descriptor && descriptor.enumerable) { + continue; + } + child[propertyName] = _clone(parent[propertyName], depth - 1); + Object.defineProperty(child, propertyName, descriptor); + } + } + + return child; + } + + return _clone(parent, depth); + } + + /** + * Simple flat clone using prototype, accepts only objects, usefull for property + * override on FLAT configuration object (no nested props). + * + * USE WITH CAUTION! This may not behave as you wish if you do not know how this + * works. + */ + clone.clonePrototype = function clonePrototype(parent) { + if (parent === null) + return null; + + var c = function () {}; + c.prototype = parent; + return new c(); + }; + +// private utility functions + + function __objToStr(o) { + return Object.prototype.toString.call(o); + } + clone.__objToStr = __objToStr; + + function __isDate(o) { + return typeof o === 'object' && __objToStr(o) === '[object Date]'; + } + clone.__isDate = __isDate; + + function __isArray(o) { + return typeof o === 'object' && __objToStr(o) === '[object Array]'; + } + clone.__isArray = __isArray; + + function __isRegExp(o) { + return typeof o === 'object' && __objToStr(o) === '[object RegExp]'; + } + clone.__isRegExp = __isRegExp; + + function __getRegExpFlags(re) { + var flags = ''; + if (re.global) flags += 'g'; + if (re.ignoreCase) flags += 'i'; + if (re.multiline) flags += 'm'; + return flags; + } + clone.__getRegExpFlags = __getRegExpFlags; + + return clone; +})(); + +export default clone diff --git a/uni_modules/uview-ui/libs/mixin/button.js b/uni_modules/uview-ui/libs/mixin/button.js new file mode 100644 index 0000000..0c019c2 --- /dev/null +++ b/uni_modules/uview-ui/libs/mixin/button.js @@ -0,0 +1,13 @@ +export default { + props: { + lang: String, + sessionFrom: String, + sendMessageTitle: String, + sendMessagePath: String, + sendMessageImg: String, + showMessageCard: Boolean, + appParameter: String, + formType: String, + openType: String + } +} diff --git a/uni_modules/uview-ui/libs/mixin/mixin.js b/uni_modules/uview-ui/libs/mixin/mixin.js new file mode 100644 index 0000000..f41a178 --- /dev/null +++ b/uni_modules/uview-ui/libs/mixin/mixin.js @@ -0,0 +1,160 @@ +module.exports = { + // ������������������������������������������������������������������ + props: { + // ������������������������������������������������������������������������������������ + customStyle: { + type: [Object, String], + default: () => ({}) + }, + customClass: { + type: String, + default: '' + }, + // ��������������������� + url: { + type: String, + default: '' + }, + // ��������������������� + linkType: { + type: String, + default: 'navigateTo' + } + }, + data() { + return {} + }, + onLoad() { + // getRect���������$u���������������������������������in(this)��������������������������������������������������������� + this.$u.getRect = this.$uGetRect + }, + created() { + // ���������������������created���������������������������������������������������created���������������������$u + this.$u.getRect = this.$uGetRect + }, + computed: { + // ���2.x���������������������$u���������uni������������������������������������������uni.$u.xxx������ + // ������������������computed���������������������������this.$u������������������������������js���������uni.$u.xxx + // ������nvue������������������������������������$u������������������������������������������nvue���������������������������������props��������� + $u() { + // #ifndef APP-NVUE + // ������nvue������������props���http���mixin������������������������������setData��������������������������� + return uni.$u.deepMerge(uni.$u, { + props: undefined, + http: undefined, + mixin: undefined + }) + // #endif + // #ifdef APP-NVUE + return uni.$u + // #endif + }, + /** + * ������bem������������ + * ������������������������H5���nvue������������class������������������������:class="[bem()]"��������������������� + * ���������������������������������������������������������������������������������������������������������������������������������['a', 'b', 'c']���'a b c'��������� + * @param {String} name ������������ + * @param {Array} fixed ������������������������ + * @param {Array} change ���������������������true������false������������������������������ + * @returns {Array|string} + */ + bem() { + return function (name, fixed, change) { + // ������������ + const prefix = `u-${name}--` + const classes = {} + if (fixed) { + fixed.map((item) => { + // ��������������������������������� + classes[prefix + this[item]] = true + }) + } + if (change) { + change.map((item) => { + // ���������������������������this[item]���������true������false������������������������������������������ + this[item] ? (classes[prefix + item] = this[item]) : (delete classes[prefix + item]) + }) + } + return Object.keys(classes) + // ������������������������������������������������������������������������������������������������������","������������������ + // #ifdef MP-ALIPAY || MP-TOUTIAO || MP-LARK + .join(' ') + // #endif + } + } + }, + methods: { + // ��������������������� + openPage(urlKey = 'url') { + const url = this[urlKey] + if (url) { + // ������������uni.navigateTo��������� + uni[this.linkType]({ + url + }) + } + }, + // ������������������ + // ���������������������������������������������������������������������������������������������bug(2020-07-21) + // ���������������������������������������������������������������view������ + $uGetRect(selector, all) { + return new Promise((resolve) => { + uni.createSelectorQuery() + .in(this)[all ? 'selectAll' : 'select'](selector) + .boundingClientRect((rect) => { + if (all && Array.isArray(rect) && rect.length) { + resolve(rect) + } + if (!all && rect) { + resolve(rect) + } + }) + .exec() + }) + }, + getParentData(parentName = '') { + // ���������created������������parent������ + if (!this.parent) this.parent = {} + // ������������������������������������������������������(������������u-radio������������u-radio-group���this) + // ������������this���������������������������������������(u-radio���this)���parentData������������������������ + // ���������������������������������������������������������������������������������this.parent.xxx��������������������������������� + // ���������������������������������������������������������������������u-radio-group���������data��������������������������������������������������������������� + this.parent = uni.$u.$parent.call(this, parentName) + if (this.parent.children) { + // ������������������children������������������������������������������������������������������children��� + this.parent.children.indexOf(this) === -1 && this.parent.children.push(this) + } + if (this.parent && this.parentData) { + // ������parentData������������������parent���������������������������parentData + Object.keys(this.parentData).map((key) => { + this.parentData[key] = this.parent[key] + }) + } + }, + // ������������������ + preventEvent(e) { + e && typeof (e.stopPropagation) === 'function' && e.stopPropagation() + }, + // ��������� + noop(e) { + this.preventEvent(e) + } + }, + onReachBottom() { + uni.$emit('uOnReachBottom') + }, + beforeDestroy() { + // ������������������������������parent���chldren������������checkbox���checkbox-group������������������������������������ + // ���������������������������������������������children������������������������������������������������������ + if (this.parent && uni.$u.test.array(this.parent.children)) { + // ���������������������������������������children������������������������ + const childrenList = this.parent.children + childrenList.map((child, index) => { + // ������������������������ + if (child === this) { + childrenList.splice(index, 1) + } + }) + } + } +} diff --git a/uni_modules/uview-ui/libs/mixin/mpMixin.js b/uni_modules/uview-ui/libs/mixin/mpMixin.js new file mode 100644 index 0000000..29e7e65 --- /dev/null +++ b/uni_modules/uview-ui/libs/mixin/mpMixin.js @@ -0,0 +1,8 @@ +export default { + // #ifdef MP-WEIXIN + // ���������������������������������������������������Vue������������������������������������flex������ + options: { + virtualHost: true + } + // #endif +} diff --git a/uni_modules/uview-ui/libs/mixin/mpShare.js b/uni_modules/uview-ui/libs/mixin/mpShare.js new file mode 100644 index 0000000..b07bbd3 --- /dev/null +++ b/uni_modules/uview-ui/libs/mixin/mpShare.js @@ -0,0 +1,13 @@ +module.exports = { + onLoad() { + // ��������������������������� + uni.$u.mpShare = { + title: '', // ������������������������ + path: '', // ��������������������������� + imageUrl: '' // ������������������������������ + } + }, + onShareAppMessage() { + return uni.$u.mpShare + } +} diff --git a/uni_modules/uview-ui/libs/mixin/openType.js b/uni_modules/uview-ui/libs/mixin/openType.js new file mode 100644 index 0000000..1216181 --- /dev/null +++ b/uni_modules/uview-ui/libs/mixin/openType.js @@ -0,0 +1,25 @@ +export default { + props: { + openType: String + }, + methods: { + onGetUserInfo(event) { + this.$emit('getuserinfo', event.detail) + }, + onContact(event) { + this.$emit('contact', event.detail) + }, + onGetPhoneNumber(event) { + this.$emit('getphonenumber', event.detail) + }, + onError(event) { + this.$emit('error', event.detail) + }, + onLaunchApp(event) { + this.$emit('launchapp', event.detail) + }, + onOpenSetting(event) { + this.$emit('opensetting', event.detail) + } + } +} diff --git a/uni_modules/uview-ui/libs/mixin/style.js b/uni_modules/uview-ui/libs/mixin/style.js new file mode 100644 index 0000000..2660180 --- /dev/null +++ b/uni_modules/uview-ui/libs/mixin/style.js @@ -0,0 +1,228 @@ +export default { + props: { + // flex������������ + flexDirection: { + type: String, + default: '' + }, + // flex-direction��������� + fd: { + type: String, + default: '' + }, + // ������������ + display: { + type: String, + default: '' + }, + // display������ + d: { + type: String, + default: '' + }, + // ������������������ + justifyContent: { + type: String, + default: '' + }, + // justifyContent��������� + jc: { + type: String, + default: '' + }, + // ������������������ + alignItems: { + type: String, + default: '' + }, + // align-items��������� + ai: { + type: String, + default: '' + }, + color: { + type: String, + default: '' + }, + // color������ + c: { + type: String, + default: '' + }, + // ������������ + fontSize: { + type: [String, Number], + default: 0 + }, + // font-size������ + fs: { + type: [String, Number], + default: '' + }, + margin: { + type: [String, Number], + default: 0 + }, + // margin������ + m: { + type: [String, Number], + default: 0 + }, + // margin-top + marginTop: { + type: [String, Number], + default: 0 + }, + // margin-top������ + mt: { + type: [String, Number], + default: 0 + }, + // margin-right + marginRight: { + type: [String, Number], + default: 0 + }, + // margin-right������ + mr: { + type: [String, Number], + default: 0 + }, + // margin-bottom + marginBottom: { + type: [String, Number], + default: 0 + }, + // margin-bottom������ + mb: { + type: [String, Number], + default: 0 + }, + // margin-left + marginLeft: { + type: [String, Number], + default: 0 + }, + // margin-left������ + ml: { + type: [String, Number], + default: 0 + }, + // padding-left + paddingLeft: { + type: [String, Number], + default: 0 + }, + // padding-left������ + pl: { + type: [String, Number], + default: 0 + }, + // padding-top + paddingTop: { + type: [String, Number], + default: 0 + }, + // padding-top������ + pt: { + type: [String, Number], + default: 0 + }, + // padding-right + paddingRight: { + type: [String, Number], + default: 0 + }, + // padding-right������ + pr: { + type: [String, Number], + default: 0 + }, + // padding-bottom + paddingBottom: { + type: [String, Number], + default: 0 + }, + // padding-bottom������ + pb: { + type: [String, Number], + default: 0 + }, + // border-radius + borderRadius: { + type: [String, Number], + default: 0 + }, + // border-radius������ + radius: { + type: [String, Number], + default: 0 + }, + // transform + transform: { + type: String, + default: '' + }, + // ������ + position: { + type: String, + default: '' + }, + // position������ + pos: { + type: String, + default: '' + }, + // ������ + width: { + type: [String, Number], + default: null + }, + // width������ + w: { + type: [String, Number], + default: null + }, + // ������ + height: { + type: [String, Number], + default: null + }, + // height������ + h: { + type: [String, Number], + default: null + }, + top: { + type: [String, Number], + default: 0 + }, + right: { + type: [String, Number], + default: 0 + }, + bottom: { + type: [String, Number], + default: 0 + }, + left: { + type: [String, Number], + default: 0 + } + }, + computed: { + viewStyle() { + const style = {} + const addStyle = uni.$u.addStyle(this.width || this.w) && (style.width = addStyle(this.width || this.w))(this.height || this.h) && (style.height = addStyle(this.height || this.h))(this.margin || this.m) && (style.margin = addStyle(this.margin || this.m))(this.marginTop || this.mt) && (style.marginTop = addStyle(this.marginTop || this.mt))(this.marginRight || this.mr) && (style.marginRight = addStyle(this.marginRight || this.mr))(this.marginBottom || this.mb) && (style.marginBottom = addStyle(this.marginBottom || this.mb))(this.marginLeft || this.ml) && (style.marginLeft = addStyle(this.marginLeft || this.ml))(this.padding || this.p) && (style.padding = addStyle(this.padding || this.p))(this.paddingTop || this.pt) && (style.paddingTop = addStyle(this.paddingTop || this.pt))(this.paddingRight || this.pr) && (style.paddingRight = addStyle(this.paddingRight || this.pr))(this.paddingBottom || this.pb) && (style.paddingBottom = addStyle(this.paddingBottom || this.pb))(this.paddingLeft || this.pl) && (style.paddingLeft = addStyle(this.paddingLeft || this.pl))(this.color || this.c) && (style.color = this.color || this.c)(this.fontSize || this.fs) && (style.fontSize = this.fontSize || this.fs)(this.borderRadius || this.radius) && (style.borderRadius = this.borderRadius || this.radius)(this.position || this.pos) && (this.position = this.position || this.pos)(this.flexDirection || this.fd) && (this.flexDirection = this.flexDirection || this.fd)(this.justifyContent || jc) && (this.justifyContent = this.justifyContent || jc)(this.alignItems || ai) && (this.alignItems = this.alignItems || ai) + + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) + } + }, + methods: { + // ������margin������padding������������������padding: 0 20������padding: 0 20px + getUnit(unit = '') { + // ������������������������������������������������������������������������������������������������������������ + return uni.$u.trim(unit).split(' ').map((item) => uni.$u.addUnit(item)).join(' ') + } + } +} diff --git a/uni_modules/uview-ui/libs/mixin/touch.js b/uni_modules/uview-ui/libs/mixin/touch.js new file mode 100644 index 0000000..0ecbd88 --- /dev/null +++ b/uni_modules/uview-ui/libs/mixin/touch.js @@ -0,0 +1,59 @@ +const MIN_DISTANCE = 10 + +function getDirection(x, y) { + if (x > y && x > MIN_DISTANCE) { + return 'horizontal' + } + if (y > x && y > MIN_DISTANCE) { + return 'vertical' + } + return '' +} + +export default { + methods: { + getTouchPoint(e) { + if (!e) { + return { + x: 0, + y: 0 + } + } if (e.touches && e.touches[0]) { + return { + x: e.touches[0].pageX, + y: e.touches[0].pageY + } + } if (e.changedTouches && e.changedTouches[0]) { + return { + x: e.changedTouches[0].pageX, + y: e.changedTouches[0].pageY + } + } + return { + x: e.clientX || 0, + y: e.clientY || 0 + } + }, + resetTouchStatus() { + this.direction = '' + this.deltaX = 0 + this.deltaY = 0 + this.offsetX = 0 + this.offsetY = 0 + }, + touchStart(event) { + this.resetTouchStatus() + const touch = this.getTouchPoint(event) + this.startX = touch.x + this.startY = touch.y + }, + touchMove(event) { + const touch = this.getTouchPoint(event) + this.deltaX = touch.x - this.startX + this.deltaY = touch.y - this.startY + this.offsetX = Math.abs(this.deltaX) + this.offsetY = Math.abs(this.deltaY) + this.direction = this.direction || getDirection(this.offsetX, this.offsetY) + } + } +} diff --git a/uni_modules/uview-ui/libs/util/async-validator.js b/uni_modules/uview-ui/libs/util/async-validator.js new file mode 100644 index 0000000..9e114df --- /dev/null +++ b/uni_modules/uview-ui/libs/util/async-validator.js @@ -0,0 +1,1343 @@ +function _extends() { + _extends = Object.assign || function (target) { + for (let i = 1; i < arguments.length; i++) { + const source = arguments[i] + + for (const key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key] + } + } + } + + return target + } + + return _extends.apply(this, arguments) +} + +/* eslint no-console:0 */ +const formatRegExp = /%[sdj%]/g +let warning = function warning() {} // don't print warning message when in production env or node runtime + +if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV !== 'production' && typeof window + !== 'undefined' && typeof document !== 'undefined') { + warning = function warning(type, errors) { + if (typeof console !== 'undefined' && console.warn) { + if (errors.every((e) => typeof e === 'string')) { + console.warn(type, errors) + } + } + } +} + +function convertFieldsError(errors) { + if (!errors || !errors.length) return null + const fields = {} + errors.forEach((error) => { + const { field } = error + fields[field] = fields[field] || [] + fields[field].push(error) + }) + return fields +} + +function format() { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key] + } + + let i = 1 + const f = args[0] + const len = args.length + + if (typeof f === 'function') { + return f.apply(null, args.slice(1)) + } + + if (typeof f === 'string') { + let str = String(f).replace(formatRegExp, (x) => { + if (x === '%%') { + return '%' + } + + if (i >= len) { + return x + } + + switch (x) { + case '%s': + return String(args[i++]) + + case '%d': + return Number(args[i++]) + + case '%j': + try { + return JSON.stringify(args[i++]) + } catch (_) { + return '[Circular]' + } + + break + + default: + return x + } + }) + + for (let arg = args[i]; i < len; arg = args[++i]) { + str += ` ${arg}` + } + + return str + } + + return f +} + +function isNativeStringType(type) { + return type === 'string' || type === 'url' || type === 'hex' || type === 'email' || type === 'pattern' +} + +function isEmptyValue(value, type) { + if (value === undefined || value === null) { + return true + } + + if (type === 'array' && Array.isArray(value) && !value.length) { + return true + } + + if (isNativeStringType(type) && typeof value === 'string' && !value) { + return true + } + + return false +} + +function asyncParallelArray(arr, func, callback) { + const results = [] + let total = 0 + const arrLength = arr.length + + function count(errors) { + results.push.apply(results, errors) + total++ + + if (total === arrLength) { + callback(results) + } + } + + arr.forEach((a) => { + func(a, count) + }) +} + +function asyncSerialArray(arr, func, callback) { + let index = 0 + const arrLength = arr.length + + function next(errors) { + if (errors && errors.length) { + callback(errors) + return + } + + const original = index + index += 1 + + if (original < arrLength) { + func(arr[original], next) + } else { + callback([]) + } + } + + next([]) +} + +function flattenObjArr(objArr) { + const ret = [] + Object.keys(objArr).forEach((k) => { + ret.push.apply(ret, objArr[k]) + }) + return ret +} + +function asyncMap(objArr, option, func, callback) { + if (option.first) { + const _pending = new Promise((resolve, reject) => { + const next = function next(errors) { + callback(errors) + return errors.length ? reject({ + errors, + fields: convertFieldsError(errors) + }) : resolve() + } + + const flattenArr = flattenObjArr(objArr) + asyncSerialArray(flattenArr, func, next) + }) + + _pending.catch((e) => e) + + return _pending + } + + let firstFields = option.firstFields || [] + + if (firstFields === true) { + firstFields = Object.keys(objArr) + } + + const objArrKeys = Object.keys(objArr) + const objArrLength = objArrKeys.length + let total = 0 + const results = [] + const pending = new Promise((resolve, reject) => { + const next = function next(errors) { + results.push.apply(results, errors) + total++ + + if (total === objArrLength) { + callback(results) + return results.length ? reject({ + errors: results, + fields: convertFieldsError(results) + }) : resolve() + } + } + + if (!objArrKeys.length) { + callback(results) + resolve() + } + + objArrKeys.forEach((key) => { + const arr = objArr[key] + + if (firstFields.indexOf(key) !== -1) { + asyncSerialArray(arr, func, next) + } else { + asyncParallelArray(arr, func, next) + } + }) + }) + pending.catch((e) => e) + return pending +} + +function complementError(rule) { + return function (oe) { + if (oe && oe.message) { + oe.field = oe.field || rule.fullField + return oe + } + + return { + message: typeof oe === 'function' ? oe() : oe, + field: oe.field || rule.fullField + } + } +} + +function deepMerge(target, source) { + if (source) { + for (const s in source) { + if (source.hasOwnProperty(s)) { + const value = source[s] + + if (typeof value === 'object' && typeof target[s] === 'object') { + target[s] = { ...target[s], ...value } + } else { + target[s] = value + } + } + } + } + + return target +} + +/** + * Rule for validating required fields. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param source The source object being validated. + * @param errors An array of errors that this rule may add + * validation errors to. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function required(rule, value, source, errors, options, type) { + if (rule.required && (!source.hasOwnProperty(rule.field) || isEmptyValue(value, type || rule.type))) { + errors.push(format(options.messages.required, rule.fullField)) + } +} + +/** + * Rule for validating whitespace. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param source The source object being validated. + * @param errors An array of errors that this rule may add + * validation errors to. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function whitespace(rule, value, source, errors, options) { + if (/^\s+$/.test(value) || value === '') { + errors.push(format(options.messages.whitespace, rule.fullField)) + } +} + +/* eslint max-len:0 */ + +const pattern = { + // http://emailregex.com/ + email: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, + url: new RegExp( + '^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$', + 'i' + ), + hex: /^#?([a-f0-9]{6}|[a-f0-9]{3})$/i +} +var types = { + integer: function integer(value) { + return /^(-)?\d+$/.test(value); + }, + float: function float(value) { + return /^(-)?\d+(\.\d+)?$/.test(value); + }, + array: function array(value) { + return Array.isArray(value) + }, + regexp: function regexp(value) { + if (value instanceof RegExp) { + return true + } + + try { + return !!new RegExp(value) + } catch (e) { + return false + } + }, + date: function date(value) { + return typeof value.getTime === 'function' && typeof value.getMonth === 'function' && typeof value.getYear + === 'function' + }, + number: function number(value) { + if (isNaN(value)) { + return false + } + + // ������������������������������������������������ + return typeof +value === 'number' + }, + object: function object(value) { + return typeof value === 'object' && !types.array(value) + }, + method: function method(value) { + return typeof value === 'function' + }, + email: function email(value) { + return typeof value === 'string' && !!value.match(pattern.email) && value.length < 255 + }, + url: function url(value) { + return typeof value === 'string' && !!value.match(pattern.url) + }, + hex: function hex(value) { + return typeof value === 'string' && !!value.match(pattern.hex) + } +} +/** + * Rule for validating the type of a value. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param source The source object being validated. + * @param errors An array of errors that this rule may add + * validation errors to. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function type(rule, value, source, errors, options) { + if (rule.required && value === undefined) { + required(rule, value, source, errors, options) + return + } + + const custom = ['integer', 'float', 'array', 'regexp', 'object', 'method', 'email', 'number', 'date', 'url', 'hex'] + const ruleType = rule.type + + if (custom.indexOf(ruleType) > -1) { + if (!types[ruleType](value)) { + errors.push(format(options.messages.types[ruleType], rule.fullField, rule.type)) + } // straight typeof check + } else if (ruleType && typeof value !== rule.type) { + errors.push(format(options.messages.types[ruleType], rule.fullField, rule.type)) + } +} + +/** + * Rule for validating minimum and maximum allowed values. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param source The source object being validated. + * @param errors An array of errors that this rule may add + * validation errors to. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function range(rule, value, source, errors, options) { + const len = typeof rule.len === 'number' + const min = typeof rule.min === 'number' + const max = typeof rule.max === 'number' // ���������������������������U+010000���������U+10FFFF������������������������Supplementary Plane��� + + const spRegexp = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g + let val = value + let key = null + const num = typeof value === 'number' + const str = typeof value === 'string' + const arr = Array.isArray(value) + + if (num) { + key = 'number' + } else if (str) { + key = 'string' + } else if (arr) { + key = 'array' + } // if the value is not of a supported type for range validation + // the validation rule rule should use the + // type property to also test for a particular type + + if (!key) { + return false + } + + if (arr) { + val = value.length + } + + if (str) { + // ������������������U+010000���������length������������������bug������"������������".lenght !== 3 + val = value.replace(spRegexp, '_').length + } + + if (len) { + if (val !== rule.len) { + errors.push(format(options.messages[key].len, rule.fullField, rule.len)) + } + } else if (min && !max && val < rule.min) { + errors.push(format(options.messages[key].min, rule.fullField, rule.min)) + } else if (max && !min && val > rule.max) { + errors.push(format(options.messages[key].max, rule.fullField, rule.max)) + } else if (min && max && (val < rule.min || val > rule.max)) { + errors.push(format(options.messages[key].range, rule.fullField, rule.min, rule.max)) + } +} + +const ENUM = 'enum' +/** + * Rule for validating a value exists in an enumerable list. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param source The source object being validated. + * @param errors An array of errors that this rule may add + * validation errors to. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function enumerable(rule, value, source, errors, options) { + rule[ENUM] = Array.isArray(rule[ENUM]) ? rule[ENUM] : [] + + if (rule[ENUM].indexOf(value) === -1) { + errors.push(format(options.messages[ENUM], rule.fullField, rule[ENUM].join(', '))) + } +} + +/** + * Rule for validating a regular expression pattern. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param source The source object being validated. + * @param errors An array of errors that this rule may add + * validation errors to. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function pattern$1(rule, value, source, errors, options) { + if (rule.pattern) { + if (rule.pattern instanceof RegExp) { + // if a RegExp instance is passed, reset `lastIndex` in case its `global` + // flag is accidentally set to `true`, which in a validation scenario + // is not necessary and the result might be misleading + rule.pattern.lastIndex = 0 + + if (!rule.pattern.test(value)) { + errors.push(format(options.messages.pattern.mismatch, rule.fullField, value, rule.pattern)) + } + } else if (typeof rule.pattern === 'string') { + const _pattern = new RegExp(rule.pattern) + + if (!_pattern.test(value)) { + errors.push(format(options.messages.pattern.mismatch, rule.fullField, value, rule.pattern)) + } + } + } +} + +const rules = { + required, + whitespace, + type, + range, + enum: enumerable, + pattern: pattern$1 +} + +/** + * Performs validation for string types. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function string(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value, 'string') && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options, 'string') + + if (!isEmptyValue(value, 'string')) { + rules.type(rule, value, source, errors, options) + rules.range(rule, value, source, errors, options) + rules.pattern(rule, value, source, errors, options) + + if (rule.whitespace === true) { + rules.whitespace(rule, value, source, errors, options) + } + } + } + + callback(errors) +} + +/** + * Validates a function. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function method(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (value !== undefined) { + rules.type(rule, value, source, errors, options) + } + } + + callback(errors) +} + +/** + * Validates a number. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function number(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (value === '') { + value = undefined + } + + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (value !== undefined) { + rules.type(rule, value, source, errors, options) + rules.range(rule, value, source, errors, options) + } + } + + callback(errors) +} + +/** + * Validates a boolean. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function _boolean(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (value !== undefined) { + rules.type(rule, value, source, errors, options) + } + } + + callback(errors) +} + +/** + * Validates the regular expression type. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function regexp(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (!isEmptyValue(value)) { + rules.type(rule, value, source, errors, options) + } + } + + callback(errors) +} + +/** + * Validates a number is an integer. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function integer(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (value !== undefined) { + rules.type(rule, value, source, errors, options) + rules.range(rule, value, source, errors, options) + } + } + + callback(errors) +} + +/** + * Validates a number is a floating point number. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function floatFn(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (value !== undefined) { + rules.type(rule, value, source, errors, options) + rules.range(rule, value, source, errors, options) + } + } + + callback(errors) +} + +/** + * Validates an array. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function array(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value, 'array') && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options, 'array') + + if (!isEmptyValue(value, 'array')) { + rules.type(rule, value, source, errors, options) + rules.range(rule, value, source, errors, options) + } + } + + callback(errors) +} + +/** + * Validates an object. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function object(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (value !== undefined) { + rules.type(rule, value, source, errors, options) + } + } + + callback(errors) +} + +const ENUM$1 = 'enum' +/** + * Validates an enumerable list. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function enumerable$1(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (value !== undefined) { + rules[ENUM$1](rule, value, source, errors, options) + } + } + + callback(errors) +} + +/** + * Validates a regular expression pattern. + * + * Performs validation when a rule only contains + * a pattern property but is not declared as a string type. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function pattern$2(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value, 'string') && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (!isEmptyValue(value, 'string')) { + rules.pattern(rule, value, source, errors, options) + } + } + + callback(errors) +} + +function date(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (!isEmptyValue(value)) { + let dateObject + + if (typeof value === 'number') { + dateObject = new Date(value) + } else { + dateObject = value + } + + rules.type(rule, dateObject, source, errors, options) + + if (dateObject) { + rules.range(rule, dateObject.getTime(), source, errors, options) + } + } + } + + callback(errors) +} + +function required$1(rule, value, callback, source, options) { + const errors = [] + const type = Array.isArray(value) ? 'array' : typeof value + rules.required(rule, value, source, errors, options, type) + callback(errors) +} + +function type$1(rule, value, callback, source, options) { + const ruleType = rule.type + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value, ruleType) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options, ruleType) + + if (!isEmptyValue(value, ruleType)) { + rules.type(rule, value, source, errors, options) + } + } + + callback(errors) +} + +/** + * Performs validation for any type. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function any(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + } + + callback(errors) +} + +const validators = { + string, + method, + number, + boolean: _boolean, + regexp, + integer, + float: floatFn, + array, + object, + enum: enumerable$1, + pattern: pattern$2, + date, + url: type$1, + hex: type$1, + email: type$1, + required: required$1, + any +} + +function newMessages() { + return { + default: 'Validation error on field %s', + required: '%s is required', + enum: '%s must be one of %s', + whitespace: '%s cannot be empty', + date: { + format: '%s date %s is invalid for format %s', + parse: '%s date could not be parsed, %s is invalid ', + invalid: '%s date %s is invalid' + }, + types: { + string: '%s is not a %s', + method: '%s is not a %s (function)', + array: '%s is not an %s', + object: '%s is not an %s', + number: '%s is not a %s', + date: '%s is not a %s', + boolean: '%s is not a %s', + integer: '%s is not an %s', + float: '%s is not a %s', + regexp: '%s is not a valid %s', + email: '%s is not a valid %s', + url: '%s is not a valid %s', + hex: '%s is not a valid %s' + }, + string: { + len: '%s must be exactly %s characters', + min: '%s must be at least %s characters', + max: '%s cannot be longer than %s characters', + range: '%s must be between %s and %s characters' + }, + number: { + len: '%s must equal %s', + min: '%s cannot be less than %s', + max: '%s cannot be greater than %s', + range: '%s must be between %s and %s' + }, + array: { + len: '%s must be exactly %s in length', + min: '%s cannot be less than %s in length', + max: '%s cannot be greater than %s in length', + range: '%s must be between %s and %s in length' + }, + pattern: { + mismatch: '%s value %s does not match pattern %s' + }, + clone: function clone() { + const cloned = JSON.parse(JSON.stringify(this)) + cloned.clone = this.clone + return cloned + } + } +} +const messages = newMessages() + +/** + * Encapsulates a validation schema. + * + * @param descriptor An object declaring validation rules + * for this schema. + */ + +function Schema(descriptor) { + this.rules = null + this._messages = messages + this.define(descriptor) +} + +Schema.prototype = { + messages: function messages(_messages) { + if (_messages) { + this._messages = deepMerge(newMessages(), _messages) + } + + return this._messages + }, + define: function define(rules) { + if (!rules) { + throw new Error('Cannot configure a schema with no rules') + } + + if (typeof rules !== 'object' || Array.isArray(rules)) { + throw new Error('Rules must be an object') + } + + this.rules = {} + let z + let item + + for (z in rules) { + if (rules.hasOwnProperty(z)) { + item = rules[z] + this.rules[z] = Array.isArray(item) ? item : [item] + } + } + }, + validate: function validate(source_, o, oc) { + const _this = this + + if (o === void 0) { + o = {} + } + + if (oc === void 0) { + oc = function oc() {} + } + + let source = source_ + let options = o + let callback = oc + + if (typeof options === 'function') { + callback = options + options = {} + } + + if (!this.rules || Object.keys(this.rules).length === 0) { + if (callback) { + callback() + } + + return Promise.resolve() + } + + function complete(results) { + let i + let errors = [] + let fields = {} + + function add(e) { + if (Array.isArray(e)) { + let _errors + + errors = (_errors = errors).concat.apply(_errors, e) + } else { + errors.push(e) + } + } + + for (i = 0; i < results.length; i++) { + add(results[i]) + } + + if (!errors.length) { + errors = null + fields = null + } else { + fields = convertFieldsError(errors) + } + + callback(errors, fields) + } + + if (options.messages) { + let messages$1 = this.messages() + + if (messages$1 === messages) { + messages$1 = newMessages() + } + + deepMerge(messages$1, options.messages) + options.messages = messages$1 + } else { + options.messages = this.messages() + } + + let arr + let value + const series = {} + const keys = options.keys || Object.keys(this.rules) + keys.forEach((z) => { + arr = _this.rules[z] + value = source[z] + arr.forEach((r) => { + let rule = r + + if (typeof rule.transform === 'function') { + if (source === source_) { + source = { ...source } + } + + value = source[z] = rule.transform(value) + } + + if (typeof rule === 'function') { + rule = { + validator: rule + } + } else { + rule = { ...rule } + } + + rule.validator = _this.getValidationMethod(rule) + rule.field = z + rule.fullField = rule.fullField || z + rule.type = _this.getType(rule) + + if (!rule.validator) { + return + } + + series[z] = series[z] || [] + series[z].push({ + rule, + value, + source, + field: z + }) + }) + }) + const errorFields = {} + return asyncMap(series, options, (data, doIt) => { + const { rule } = data + let deep = (rule.type === 'object' || rule.type === 'array') && (typeof rule.fields === 'object' || typeof rule.defaultField + === 'object') + deep = deep && (rule.required || !rule.required && data.value) + rule.field = data.field + + function addFullfield(key, schema) { + return { ...schema, fullField: `${rule.fullField}.${key}` } + } + + function cb(e) { + if (e === void 0) { + e = [] + } + + let errors = e + + if (!Array.isArray(errors)) { + errors = [errors] + } + + if (!options.suppressWarning && errors.length) { + Schema.warning('async-validator:', errors) + } + + if (errors.length && rule.message) { + errors = [].concat(rule.message) + } + + errors = errors.map(complementError(rule)) + + if (options.first && errors.length) { + errorFields[rule.field] = 1 + return doIt(errors) + } + + if (!deep) { + doIt(errors) + } else { + // if rule is required but the target object + // does not exist fail at the rule level and don't + // go deeper + if (rule.required && !data.value) { + if (rule.message) { + errors = [].concat(rule.message).map(complementError(rule)) + } else if (options.error) { + errors = [options.error(rule, format(options.messages.required, rule.field))] + } else { + errors = [] + } + + return doIt(errors) + } + + let fieldsSchema = {} + + if (rule.defaultField) { + for (const k in data.value) { + if (data.value.hasOwnProperty(k)) { + fieldsSchema[k] = rule.defaultField + } + } + } + + fieldsSchema = { ...fieldsSchema, ...data.rule.fields } + + for (const f in fieldsSchema) { + if (fieldsSchema.hasOwnProperty(f)) { + const fieldSchema = Array.isArray(fieldsSchema[f]) ? fieldsSchema[f] : [fieldsSchema[f]] + fieldsSchema[f] = fieldSchema.map(addFullfield.bind(null, f)) + } + } + + const schema = new Schema(fieldsSchema) + schema.messages(options.messages) + + if (data.rule.options) { + data.rule.options.messages = options.messages + data.rule.options.error = options.error + } + + schema.validate(data.value, data.rule.options || options, (errs) => { + const finalErrors = [] + + if (errors && errors.length) { + finalErrors.push.apply(finalErrors, errors) + } + + if (errs && errs.length) { + finalErrors.push.apply(finalErrors, errs) + } + + doIt(finalErrors.length ? finalErrors : null) + }) + } + } + + let res + + if (rule.asyncValidator) { + res = rule.asyncValidator(rule, data.value, cb, data.source, options) + } else if (rule.validator) { + res = rule.validator(rule, data.value, cb, data.source, options) + + if (res === true) { + cb() + } else if (res === false) { + cb(rule.message || `${rule.field} fails`) + } else if (res instanceof Array) { + cb(res) + } else if (res instanceof Error) { + cb(res.message) + } + } + + if (res && res.then) { + res.then(() => cb(), (e) => cb(e)) + } + }, (results) => { + complete(results) + }) + }, + getType: function getType(rule) { + if (rule.type === undefined && rule.pattern instanceof RegExp) { + rule.type = 'pattern' + } + + if (typeof rule.validator !== 'function' && rule.type && !validators.hasOwnProperty(rule.type)) { + throw new Error(format('Unknown rule type %s', rule.type)) + } + + return rule.type || 'string' + }, + getValidationMethod: function getValidationMethod(rule) { + if (typeof rule.validator === 'function') { + return rule.validator + } + + const keys = Object.keys(rule) + const messageIndex = keys.indexOf('message') + + if (messageIndex !== -1) { + keys.splice(messageIndex, 1) + } + + if (keys.length === 1 && keys[0] === 'required') { + return validators.required + } + + return validators[this.getType(rule)] || false + } +} + +Schema.register = function register(type, validator) { + if (typeof validator !== 'function') { + throw new Error('Cannot register a validator by type, validator is not a function') + } + + validators[type] = validator +} + +Schema.warning = warning +Schema.messages = messages + +export default Schema +// # sourceMappingURL=index.js.map diff --git a/uni_modules/uview-ui/libs/util/calendar.js b/uni_modules/uview-ui/libs/util/calendar.js new file mode 100644 index 0000000..e006dea --- /dev/null +++ b/uni_modules/uview-ui/libs/util/calendar.js @@ -0,0 +1,546 @@ +/** +* @1900-2100��������������������������������� +* @charset UTF-8 +* @github https://github.com/jjonline/calendar.js +* @Author Jea���(JJonline@JJonline.Cn) +* @Time 2014-7-21 +* @Time 2016-8-13 Fixed 2033hex���Attribution Annals +* @Time 2016-9-25 Fixed lunar LeapMonth Param Bug +* @Time 2017-7-24 Fixed use getTerm Func Param Error.use solar year,NOT lunar year +* @Version 1.0.3 +* @������������������calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0] +* @������������������calendar.lunar2solar(1987,09,10); //[you can ignore params of prefix 0] +*/ +/* eslint-disable */ +var calendar = { + + /** + * ������1900-2100��������������������� + * @Array Of Property + * @return Hex + */ + lunarInfo: [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, // 1900-1909 + 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, // 1910-1919 + 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, // 1920-1929 + 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, // 1930-1939 + 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, // 1940-1949 + 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, // 1950-1959 + 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, // 1960-1969 + 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, // 1970-1979 + 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, // 1980-1989 + 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, // 1990-1999 + 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, // 2000-2009 + 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, // 2010-2019 + 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, // 2020-2029 + 0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, // 2030-2039 + 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, // 2040-2049 + /** Add By JJonline@JJonline.Cn**/ + 0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0, // 2050-2059 + 0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, // 2060-2069 + 0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, // 2070-2079 + 0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, // 2080-2089 + 0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, // 2090-2099 + 0x0d520], // 2100 + + /** + * ������������������������������������ + * @Array Of Property + * @return Number + */ + solarMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], + + /** + * ������������������������������ + * @Array Of Property trans["���","���","���","���","���","���","���","���","���","���"] + * @return Cn string + */ + Gan: ['\u7532', '\u4e59', '\u4e19', '\u4e01', '\u620a', '\u5df1', '\u5e9a', '\u8f9b', '\u58ec', '\u7678'], + + /** + * ������������������������������ + * @Array Of Property + * @trans["���","���","���","���","���","���","���","���","���","���","���","���"] + * @return Cn string + */ + Zhi: ['\u5b50', '\u4e11', '\u5bc5', '\u536f', '\u8fb0', '\u5df3', '\u5348', '\u672a', '\u7533', '\u9149', '\u620c', '\u4ea5'], + + /** + * ������������������������������<=>������ + * @Array Of Property + * @trans["���","���","���","���","���","���","���","���","���","���","���","���"] + * @return Cn string + */ + Animals: ['\u9f20', '\u725b', '\u864e', '\u5154', '\u9f99', '\u86c7', '\u9a6c', '\u7f8a', '\u7334', '\u9e21', '\u72d7', '\u732a'], + + /** + * 24��������������� + * @Array Of Property + * @trans["������","������","������","������","������","������","������","������","������","������","������","������","������","������","������","������","������","������","������","������","������","������","������","������"] + * @return Cn string + */ + solarTerm: ['\u5c0f\u5bd2', '\u5927\u5bd2', '\u7acb\u6625', '\u96e8\u6c34', '\u60ca\u86f0', '\u6625\u5206', '\u6e05\u660e', '\u8c37\u96e8', '\u7acb\u590f', '\u5c0f\u6ee1', '\u8292\u79cd', '\u590f\u81f3', '\u5c0f\u6691', '\u5927\u6691', '\u7acb\u79cb', '\u5904\u6691', '\u767d\u9732', '\u79cb\u5206', '\u5bd2\u9732', '\u971c\u964d', '\u7acb\u51ac', '\u5c0f\u96ea', '\u5927\u96ea', '\u51ac\u81f3'], + + /** + * 1900-2100���������24��������������������� + * @Array Of Property + * @return 0x string For splice + */ + sTermInfo: ['9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', + '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', + '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', + 'b027097bd097c36b0b6fc9274c91aa', '9778397bd19801ec9210c965cc920e', '97b6b97bd19801ec95f8c965cc920f', + '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd197c36c9210c9274c91aa', + '97b6b97bd19801ec95f8c965cc920e', '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', + '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec95f8c965cc920e', '97bcf97c3598082c95f8e1cfcc920f', + '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', + '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', + '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', + '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', + '97bcf97c359801ec95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd097bd07f595b0b6fc920fb0722', + '9778397bd097c36b0b6fc9210c8dc2', '9778397bd19801ec9210c9274c920e', '97b6b97bd19801ec95f8c965cc920f', + '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e', + '97b6b97bd19801ec95f8c965cc920f', '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', + '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bd07f1487f595b0b0bc920fb0722', + '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', + '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', + '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f531b0b0bb0b6fb0722', + '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', + '97bcf7f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', + '9778397bd097c36b0b6fc9210c91aa', '97b6b97bd197c36c9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', + '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e', + '97b6b7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', + '9778397bd097c36b0b70c9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722', + '7f0e397bd097c35b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', + '7f0e27f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', + '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', + '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', + '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', + '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9274c91aa', + '97b6b7f0e47f531b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', + '9778397bd097c36b0b6fc9210c91aa', '97b6b7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', + '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '977837f0e37f149b0723b0787b0721', + '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c35b0b6fc9210c8dc2', + '977837f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722', + '7f0e397bd097c35b0b6fc9210c8dc2', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', + '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '977837f0e37f14998082b0787b06bd', + '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', + '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', + '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', + '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', + '7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', + '977837f0e37f14998082b0723b06bd', '7f07e7f0e37f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', + '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b0721', + '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f595b0b0bb0b6fb0722', '7f0e37f0e37f14898082b0723b02d5', + '7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f531b0b0bb0b6fb0722', + '7f0e37f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', + '7f0e37f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd', + '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', + '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', + '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f149b0723b0787b0721', + '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0723b06bd', + '7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', '7f0e37f0e366aa89801eb072297c35', + '7ec967f0e37f14998082b0723b06bd', '7f07e7f0e37f14998083b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', + '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14898082b0723b02d5', '7f07e7f0e37f14998082b0787b0721', + '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66aa89801e9808297c35', '665f67f0e37f14898082b0723b02d5', + '7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66a449801e9808297c35', + '665f67f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', + '7f0e36665b66a449801e9808297c35', '665f67f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd', + '7f07e7f0e47f531b0723b0b6fb0721', '7f0e26665b66a449801e9808297c35', '665f67f0e37f1489801eb072297c35', + '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722'], + + /** + * ������������������������ + * @Array Of Property + * @trans ['���','���','���','���','���','���','���','���','���','���','���'] + * @return Cn string + */ + nStr1: ['\u65e5', '\u4e00', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341'], + + /** + * ������������������������������ + * @Array Of Property + * @trans ['���','���','���','���'] + * @return Cn string + */ + nStr2: ['\u521d', '\u5341', '\u5eff', '\u5345'], + + /** + * ������������������������������ + * @Array Of Property + * @trans ['���','���','���','���','���','���','���','���','���','���','���','���','���'] + * @return Cn string + */ + nStr3: ['\u6b63', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341', '\u51ac', '\u814a'], + + /** + * ������������y������������������������ + * @param lunar Year + * @return Number + * @eg:var count = calendar.lYearDays(1987) ;//count=387 + */ + lYearDays: function (y) { + var i; var sum = 348 + for (i = 0x8000; i > 0x8; i >>= 1) { sum += (this.lunarInfo[y - 1900] & i) ? 1 : 0 } + return (sum + this.leapDays(y)) + }, + + /** + * ������������y���������������������������y��������������� ���������0 + * @param lunar Year + * @return Number (0-12) + * @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6 + */ + leapMonth: function (y) { // ������������ \u95f0 + return (this.lunarInfo[y - 1900] & 0xf) + }, + + /** + * ������������y������������������ ������������������������������0 + * @param lunar Year + * @return Number (0���29���30) + * @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29 + */ + leapDays: function (y) { + if (this.leapMonth(y)) { + return ((this.lunarInfo[y - 1900] & 0x10000) ? 30 : 29) + } + return (0) + }, + + /** + * ������������y���m���������������������������������������m������������������������������leapDays������ + * @param lunar Year + * @return Number (-1���29���30) + * @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29 + */ + monthDays: function (y, m) { + if (m > 12 || m < 1) { return -1 }// ���������������1���12���������������������-1 + return ((this.lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29) + }, + + /** + * ������������(!)y���m������������ + * @param solar Year + * @return Number (-1���28���29���30���31) + * @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30 + */ + solarDays: function (y, m) { + if (m > 12 || m < 1) { return -1 } // ��������������� ������-1 + var ms = m - 1 + if (ms == 1) { // 2������������������������������������������28���29 + return (((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)) ? 29 : 28) + } else { + return (this.solarMonth[ms]) + } + }, + + /** + * ��������������������������������� + * @param lYear ��������������������� + * @return Cn string + */ + toGanZhiYear: function (lYear) { + var ganKey = (lYear - 3) % 10 + var zhiKey = (lYear - 3) % 12 + if (ganKey == 0) ganKey = 10// ���������������0������������������������ + if (zhiKey == 0) zhiKey = 12// ���������������0������������������������ + return this.Gan[ganKey - 1] + this.Zhi[zhiKey - 1] + }, + + /** + * ��������������������������������� + * @param cMonth [description] + * @param cDay [description] + * @return Cn string + */ + toAstro: function (cMonth, cDay) { + var s = '\u9b54\u7faf\u6c34\u74f6\u53cc\u9c7c\u767d\u7f8a\u91d1\u725b\u53cc\u5b50\u5de8\u87f9\u72ee\u5b50\u5904\u5973\u5929\u79e4\u5929\u874e\u5c04\u624b\u9b54\u7faf' + var arr = [20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22] + return s.substr(cMonth * 2 - (cDay < arr[cMonth - 1] ? 2 : 0), 2) + '\u5ea7'// ��� + }, + + /** + * ������offset��������������������� + * @param offset ������������������������ + * @return Cn string + */ + toGanZhi: function (offset) { + return this.Gan[offset % 10] + this.Zhi[offset % 12] + }, + + /** + * ������������(!)y������������������n������������������������ + * @param y���������(1900-2100)���n������������������������������������(1~24)������n=1(������)������ + * @return day Number + * @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;������1987���2���4��������� + */ + getTerm: function (y, n) { + if (y < 1900 || y > 2100) { return -1 } + if (n < 1 || n > 24) { return -1 } + var _table = this.sTermInfo[y - 1900] + var _info = [ + parseInt('0x' + _table.substr(0, 5)).toString(), + parseInt('0x' + _table.substr(5, 5)).toString(), + parseInt('0x' + _table.substr(10, 5)).toString(), + parseInt('0x' + _table.substr(15, 5)).toString(), + parseInt('0x' + _table.substr(20, 5)).toString(), + parseInt('0x' + _table.substr(25, 5)).toString() + ] + var _calday = [ + _info[0].substr(0, 1), + _info[0].substr(1, 2), + _info[0].substr(3, 1), + _info[0].substr(4, 2), + + _info[1].substr(0, 1), + _info[1].substr(1, 2), + _info[1].substr(3, 1), + _info[1].substr(4, 2), + + _info[2].substr(0, 1), + _info[2].substr(1, 2), + _info[2].substr(3, 1), + _info[2].substr(4, 2), + + _info[3].substr(0, 1), + _info[3].substr(1, 2), + _info[3].substr(3, 1), + _info[3].substr(4, 2), + + _info[4].substr(0, 1), + _info[4].substr(1, 2), + _info[4].substr(3, 1), + _info[4].substr(4, 2), + + _info[5].substr(0, 1), + _info[5].substr(1, 2), + _info[5].substr(3, 1), + _info[5].substr(4, 2) + ] + return parseInt(_calday[n - 1]) + }, + + /** + * ��������������������������������������������������� + * @param lunar month + * @return Cn string + * @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='������' + */ + toChinaMonth: function (m) { // ��� => \u6708 + if (m > 12 || m < 1) { return -1 } // ��������������� ������-1 + var s = this.nStr3[m - 1] + s += '\u6708'// ������������ + return s + }, + + /** + * ��������������������������������������������� + * @param lunar day + * @return Cn string + * @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='������' + */ + toChinaDay: function (d) { // ��� => \u65e5 + var s + switch (d) { + case 10: + s = '\u521d\u5341'; break + case 20: + s = '\u4e8c\u5341'; break + break + case 30: + s = '\u4e09\u5341'; break + break + default: + s = this.nStr2[Math.floor(d / 10)] + s += this.nStr1[d % 10] + } + return (s) + }, + + /** + * ���������������[!������������������] => ������������������������������������������ + * @param y year + * @return Cn string + * @eg:var animal = calendar.getAnimal(1987) ;//animal='���' + */ + getAnimal: function (y) { + return this.Animals[(y - 4) % 12] + }, + + /** + * ���������������������������������������������������object������ <=>JSON + * @param y solar year + * @param m solar month + * @param d solar day + * @return JSON object + * @eg:console.log(calendar.solar2lunar(1987,11,01)); + */ + solar2lunar: function (y, m, d) { // ������������1900.1.31~2100.12.31 + // ��������������������� + if (y < 1900 || y > 2100) { + return -1// undefined���������������������NaN + } + // ��������������������� + if (y == 1900 && m == 1 && d < 31) { + return -1 + } + // ��������� ������������ + if (!y) { + var objDate = new Date() + } else { + var objDate = new Date(y, parseInt(m) - 1, d) + } + var i; var leap = 0; var temp = 0 + // ������ymd������ + var y = objDate.getFullYear() + var m = objDate.getMonth() + 1 + var d = objDate.getDate() + var offset = (Date.UTC(objDate.getFullYear(), objDate.getMonth(), objDate.getDate()) - Date.UTC(1900, 0, 31)) / 86400000 + for (i = 1900; i < 2101 && offset > 0; i++) { + temp = this.lYearDays(i) + offset -= temp + } + if (offset < 0) { + offset += temp; i-- + } + + // ������������ + var isTodayObj = new Date() + var isToday = false + if (isTodayObj.getFullYear() == y && isTodayObj.getMonth() + 1 == m && isTodayObj.getDate() == d) { + isToday = true + } + // ��������� + var nWeek = objDate.getDay() + var cWeek = this.nStr1[nWeek] + // ��������������������������������������������������� + if (nWeek == 0) { + nWeek = 7 + } + // ��������� + var year = i + var leap = this.leapMonth(i) // ������������ + var isLeap = false + + // ������������ + for (i = 1; i < 13 && offset > 0; i++) { + // ������ + if (leap > 0 && i == (leap + 1) && isLeap == false) { + --i + isLeap = true; temp = this.leapDays(year) // ������������������������ + } else { + temp = this.monthDays(year, i)// ��������������������������� + } + // ������������ + if (isLeap == true && i == (leap + 1)) { isLeap = false } + offset -= temp + } + // ������������������������������������ + if (offset == 0 && leap > 0 && i == leap + 1) { + if (isLeap) { + isLeap = false + } else { + isLeap = true; --i + } + } + if (offset < 0) { + offset += temp; --i + } + // ��������� + var month = i + // ��������� + var day = offset + 1 + // ������������������ + var sm = m - 1 + var gzY = this.toGanZhiYear(year) + + // ��������������������� + // bugfix-2017-7-24 11:03:38 use lunar Year Param `y` Not `year` + var firstNode = this.getTerm(y, (m * 2 - 1))// ������������������������������������ + var secondNode = this.getTerm(y, (m * 2))// ������������������������������������ + + // ������12��������������������� + var gzM = this.toGanZhi((y - 1900) * 12 + m + 11) + if (d >= firstNode) { + gzM = this.toGanZhi((y - 1900) * 12 + m + 12) + } + + // ������������������������������ + var isTerm = false + var Term = null + if (firstNode == d) { + isTerm = true + Term = this.solarTerm[m * 2 - 2] + } + if (secondNode == d) { + isTerm = true + Term = this.solarTerm[m * 2 - 1] + } + // ������ ��������������� 1900/1/1 ������������ + var dayCyclical = Date.UTC(y, sm, 1, 0, 0, 0, 0) / 86400000 + 25567 + 10 + var gzD = this.toGanZhi(dayCyclical + d - 1) + // ������������������������ + var astro = this.toAstro(m, d) + + return { 'lYear': year, 'lMonth': month, 'lDay': day, 'Animal': this.getAnimal(year), 'IMonthCn': (isLeap ? '\u95f0' : '') + this.toChinaMonth(month), 'IDayCn': this.toChinaDay(day), 'cYear': y, 'cMonth': m, 'cDay': d, 'gzYear': gzY, 'gzMonth': gzM, 'gzDay': gzD, 'isToday': isToday, 'isLeap': isLeap, 'nWeek': nWeek, 'ncWeek': '\u661f\u671f' + cWeek, 'isTerm': isTerm, 'Term': Term, 'astro': astro } + }, + + /** + * ������������������������������������������������������������������������������������object������ <=>JSON + * @param y lunar year + * @param m lunar month + * @param d lunar day + * @param isLeapMonth lunar month is leap or not.[������������������������������������������true������] + * @return JSON object + * @eg:console.log(calendar.lunar2solar(1987,9,10)); + */ + lunar2solar: function (y, m, d, isLeapMonth) { // ������������1900.1.31~2100.12.1 + var isLeapMonth = !!isLeapMonth + var leapOffset = 0 + var leapMonth = this.leapMonth(y) + var leapDay = this.leapDays(y) + if (isLeapMonth && (leapMonth != m)) { return -1 }// ��������������������������������� ��������������������������������������������������� + if (y == 2100 && m == 12 && d > 1 || y == 1900 && m == 1 && d < 31) { return -1 }// ������������������������ + var day = this.monthDays(y, m) + var _day = day + // bugFix 2016-9-25 + // if month is leap, _day use leapDays method + if (isLeapMonth) { + _day = this.leapDays(y, m) + } + if (y < 1900 || y > 2100 || d > _day) { return -1 }// ��������������������� + + // ������������������������ + var offset = 0 + for (var i = 1900; i < y; i++) { + offset += this.lYearDays(i) + } + var leap = 0; var isAdd = false + for (var i = 1; i < m; i++) { + leap = this.leapMonth(y) + if (!isAdd) { // ������������ + if (leap <= i && leap > 0) { + offset += this.leapDays(y); isAdd = true + } + } + offset += this.monthDays(y, i) + } + // ������������������ ��������������������������������������������� + if (isLeapMonth) { offset += day } + // 1900���������������������������������������1900���1���30���0���0���0���(���������������������������������������������) + var stmap = Date.UTC(1900, 1, 30, 0, 0, 0) + var calObj = new Date((offset + d - 31) * 86400000 + stmap) + var cY = calObj.getUTCFullYear() + var cM = calObj.getUTCMonth() + 1 + var cD = calObj.getUTCDate() + + return this.solar2lunar(cY, cM, cD) + } +} + +export default calendar diff --git a/uni_modules/uview-ui/libs/util/dayjs.js b/uni_modules/uview-ui/libs/util/dayjs.js new file mode 100644 index 0000000..c4efea0 --- /dev/null +++ b/uni_modules/uview-ui/libs/util/dayjs.js @@ -0,0 +1,308 @@ +!(function (t, e) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = e() : typeof define === 'function' + && define.amd ? define(e) : t.dayjs = e() +}(this, () => { + 'use strict' + + const t = 'millisecond' + const e = 'second' + const n = 'minute' + const r = 'hour' + const i = 'day' + const s = 'week' + const u = 'month' + const a = 'quarter' + const o = 'year' + const f = 'date' + const h = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[^0-9]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?.?(\d+)?$/ + const c = /\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g + const d = { + name: 'en', + weekdays: 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + months: 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_') + } + const $ = function (t, e, n) { + const r = String(t) + return !r || r.length >= e ? t : `${Array(e + 1 - r.length).join(n)}${t}` + } + const l = { + s: $, + z(t) { + const e = -t.utcOffset() + const n = Math.abs(e) + const r = Math.floor(n / 60) + const i = n % 60 + return `${(e <= 0 ? '+' : '-') + $(r, 2, '0')}:${$(i, 2, '0')}` + }, + m: function t(e, n) { + if (e.date() < n.date()) return -t(n, e) + const r = 12 * (n.year() - e.year()) + (n.month() - e.month()) + const i = e.clone().add(r, u) + const s = n - i < 0 + const a = e.clone().add(r + (s ? -1 : 1), u) + return +(-(r + (n - i) / (s ? i - a : a - i)) || 0) + }, + a(t) { + return t < 0 ? Math.ceil(t) || 0 : Math.floor(t) + }, + p(h) { + return { + M: u, + y: o, + w: s, + d: i, + D: f, + h: r, + m: n, + s: e, + ms: t, + Q: a + }[h] || String(h || '').toLowerCase().replace(/s$/, '') + }, + u(t) { + return void 0 === t + } + } + let y = 'en' + const M = {} + M[y] = d + const m = function (t) { + return t instanceof S + } + const D = function (t, e, n) { + let r + if (!t) return y + if (typeof t === 'string') M[t] && (r = t), e && (M[t] = e, r = t) + else { + const i = t.name + M[i] = t, r = i + } + return !n && r && (y = r), r || !n && y + } + const v = function (t, e) { + if (m(t)) return t.clone() + const n = typeof e === 'object' ? e : {} + return n.date = t, n.args = arguments, new S(n) + } + const g = l + g.l = D, g.i = m, g.w = function (t, e) { + return v(t, { + locale: e.$L, + utc: e.$u, + x: e.$x, + $offset: e.$offset + }) + } + var S = (function () { + function d(t) { + this.$L = D(t.locale, null, !0), this.parse(t) + } + const $ = d.prototype + return $.parse = function (t) { + this.$d = (function (t) { + const e = t.date + const n = t.utc + if (e === null) return new Date(NaN) + if (g.u(e)) return new Date() + if (e instanceof Date) return new Date(e) + if (typeof e === 'string' && !/Z$/i.test(e)) { + const r = e.match(h) + if (r) { + const i = r[2] - 1 || 0 + const s = (r[7] || '0').substring(0, 3) + return n ? new Date(Date.UTC(r[1], i, r[3] || 1, r[4] || 0, r[5] || 0, r[6] || 0, s)) : new Date(r[1], i, r[3] + || 1, r[4] || 0, r[5] || 0, r[6] || 0, s) + } + } + return new Date(e) + }(t)), this.$x = t.x || {}, this.init() + }, $.init = function () { + const t = this.$d + this.$y = t.getFullYear(), this.$M = t.getMonth(), this.$D = t.getDate(), this.$W = t.getDay(), this.$H = t.getHours(), + this.$m = t.getMinutes(), this.$s = t.getSeconds(), this.$ms = t.getMilliseconds() + }, $.$utils = function () { + return g + }, $.isValid = function () { + return !(this.$d.toString() === 'Invalid Date') + }, $.isSame = function (t, e) { + const n = v(t) + return this.startOf(e) <= n && n <= this.endOf(e) + }, $.isAfter = function (t, e) { + return v(t) < this.startOf(e) + }, $.isBefore = function (t, e) { + return this.endOf(e) < v(t) + }, $.$g = function (t, e, n) { + return g.u(t) ? this[e] : this.set(n, t) + }, $.unix = function () { + return Math.floor(this.valueOf() / 1e3) + }, $.valueOf = function () { + return this.$d.getTime() + }, $.startOf = function (t, a) { + const h = this + const c = !!g.u(a) || a + const d = g.p(t) + const $ = function (t, e) { + const n = g.w(h.$u ? Date.UTC(h.$y, e, t) : new Date(h.$y, e, t), h) + return c ? n : n.endOf(i) + } + const l = function (t, e) { + return g.w(h.toDate()[t].apply(h.toDate('s'), (c ? [0, 0, 0, 0] : [23, 59, 59, 999]).slice(e)), h) + } + const y = this.$W + const M = this.$M + const m = this.$D + const D = `set${this.$u ? 'UTC' : ''}` + switch (d) { + case o: + return c ? $(1, 0) : $(31, 11) + case u: + return c ? $(1, M) : $(0, M + 1) + case s: + var v = this.$locale().weekStart || 0 + var S = (y < v ? y + 7 : y) - v + return $(c ? m - S : m + (6 - S), M) + case i: + case f: + return l(`${D}Hours`, 0) + case r: + return l(`${D}Minutes`, 1) + case n: + return l(`${D}Seconds`, 2) + case e: + return l(`${D}Milliseconds`, 3) + default: + return this.clone() + } + }, $.endOf = function (t) { + return this.startOf(t, !1) + }, $.$set = function (s, a) { + let h; const c = g.p(s) + const d = `set${this.$u ? 'UTC' : ''}` + const $ = (h = {}, h[i] = `${d}Date`, h[f] = `${d}Date`, h[u] = `${d}Month`, h[o] = `${d}FullYear`, h[r] = `${d}Hours`, + h[n] = `${d}Minutes`, h[e] = `${d}Seconds`, h[t] = `${d}Milliseconds`, h)[c] + const l = c === i ? this.$D + (a - this.$W) : a + if (c === u || c === o) { + const y = this.clone().set(f, 1) + y.$d[$](l), y.init(), this.$d = y.set(f, Math.min(this.$D, y.daysInMonth())).$d + } else $ && this.$d[$](l) + return this.init(), this + }, $.set = function (t, e) { + return this.clone().$set(t, e) + }, $.get = function (t) { + return this[g.p(t)]() + }, $.add = function (t, a) { + let f; const + h = this + t = Number(t) + const c = g.p(a) + const d = function (e) { + const n = v(h) + return g.w(n.date(n.date() + Math.round(e * t)), h) + } + if (c === u) return this.set(u, this.$M + t) + if (c === o) return this.set(o, this.$y + t) + if (c === i) return d(1) + if (c === s) return d(7) + const $ = (f = {}, f[n] = 6e4, f[r] = 36e5, f[e] = 1e3, f)[c] || 1 + const l = this.$d.getTime() + t * $ + return g.w(l, this) + }, $.subtract = function (t, e) { + return this.add(-1 * t, e) + }, $.format = function (t) { + const e = this + if (!this.isValid()) return 'Invalid Date' + const n = t || 'YYYY-MM-DDTHH:mm:ssZ' + const r = g.z(this) + const i = this.$locale() + const s = this.$H + const u = this.$m + const a = this.$M + const o = i.weekdays + const f = i.months + const h = function (t, r, i, s) { + return t && (t[r] || t(e, n)) || i[r].substr(0, s) + } + const d = function (t) { + return g.s(s % 12 || 12, t, '0') + } + const $ = i.meridiem || function (t, e, n) { + const r = t < 12 ? 'AM' : 'PM' + return n ? r.toLowerCase() : r + } + const l = { + YY: String(this.$y).slice(-2), + YYYY: this.$y, + M: a + 1, + MM: g.s(a + 1, 2, '0'), + MMM: h(i.monthsShort, a, f, 3), + MMMM: h(f, a), + D: this.$D, + DD: g.s(this.$D, 2, '0'), + d: String(this.$W), + dd: h(i.weekdaysMin, this.$W, o, 2), + ddd: h(i.weekdaysShort, this.$W, o, 3), + dddd: o[this.$W], + H: String(s), + HH: g.s(s, 2, '0'), + h: d(1), + hh: d(2), + a: $(s, u, !0), + A: $(s, u, !1), + m: String(u), + mm: g.s(u, 2, '0'), + s: String(this.$s), + ss: g.s(this.$s, 2, '0'), + SSS: g.s(this.$ms, 3, '0'), + Z: r + } + return n.replace(c, (t, e) => e || l[t] || r.replace(':', '')) + }, $.utcOffset = function () { + return 15 * -Math.round(this.$d.getTimezoneOffset() / 15) + }, $.diff = function (t, f, h) { + let c; const d = g.p(f) + const $ = v(t) + const l = 6e4 * ($.utcOffset() - this.utcOffset()) + const y = this - $ + let M = g.m(this, $) + return M = (c = {}, c[o] = M / 12, c[u] = M, c[a] = M / 3, c[s] = (y - l) / 6048e5, c[i] = (y - l) / 864e5, c[r] = y / 36e5, c[n] = y / 6e4, c[e] = y / 1e3, c)[d] || y, h ? M : g.a(M) + }, $.daysInMonth = function () { + return this.endOf(u).$D + }, $.$locale = function () { + return M[this.$L] + }, $.locale = function (t, e) { + if (!t) return this.$L + const n = this.clone() + const r = D(t, e, !0) + return r && (n.$L = r), n + }, $.clone = function () { + return g.w(this.$d, this) + }, $.toDate = function () { + return new Date(this.valueOf()) + }, $.toJSON = function () { + return this.isValid() ? this.toISOString() : null + }, $.toISOString = function () { + return this.$d.toISOString() + }, $.toString = function () { + return this.$d.toUTCString() + }, d + }()) + const p = S.prototype + return v.prototype = p, [ + ['$ms', t], + ['$s', e], + ['$m', n], + ['$H', r], + ['$W', i], + ['$M', u], + ['$y', o], + ['$D', f] + ].forEach((t) => { + p[t[1]] = function (e) { + return this.$g(e, t[0], t[1]) + } + }), v.extend = function (t, e) { + return t.$i || (t(e, S, v), t.$i = !0), v + }, v.locale = D, v.isDayjs = m, v.unix = function (t) { + return v(1e3 * t) + }, v.en = M[y], v.Ls = M, v.p = {}, v +})) diff --git a/uni_modules/uview-ui/libs/util/emitter.js b/uni_modules/uview-ui/libs/util/emitter.js new file mode 100644 index 0000000..1e64044 --- /dev/null +++ b/uni_modules/uview-ui/libs/util/emitter.js @@ -0,0 +1,51 @@ +/** + * ������������ call ������this������ + * @param componentName // ��������������������������� + * @param eventName // ������������ + * @param params // ��������������������� + */ +function broadcast(componentName, eventName, params) { + // ��������������������������������������������� ������ ������ ��������������� + this.$children.map((child) => { + if (componentName === child.$options.name) { + child.$emit.apply(child, [eventName].concat(params)) + } else { + broadcast.apply(child, [componentName, eventName].concat(params)) + } + }) +} +export default { + methods: { + /** + * ������ (������������) (������) + * @param componentName // ��������������������������� + * @param eventName // ������������ + * @param params // ��������������������� + */ + dispatch(componentName, eventName, params) { + let parent = this.$parent || this.$root// $parent ������������������������ $root ��������� + let { name } = parent.$options // ���������������������������name + // ��������������������� && ��������������� ��� ������������������������������������������������������������������������������ + // ��������������������������������������������� + while (parent && (!name || name !== componentName)) { + parent = parent.$parent + if (parent) { + name = parent.$options.name + } + } + // ������������������������������name��������������� + if (parent) { + parent.$emit.apply(parent, [eventName].concat(params)) + } + }, + /** + * ������ (������������) (������������) + * @param componentName // ��������������������������� + * @param eventName // ������������ + * @param params // ��������������������� + */ + broadcast(componentName, eventName, params) { + broadcast.call(this, componentName, eventName, params) + } + } +} diff --git a/uni_modules/uview-ui/libs/util/route.js b/uni_modules/uview-ui/libs/util/route.js new file mode 100644 index 0000000..2afeea5 --- /dev/null +++ b/uni_modules/uview-ui/libs/util/route.js @@ -0,0 +1,124 @@ +/** + * ���������������������������������������������������uni.xxx������������������������������������ + * ������������������������������ + */ + +class Router { + constructor() { + // ������������������ + this.config = { + type: 'navigateTo', + url: '', + delta: 1, // navigateBack���������������,��������������� + params: {}, // ��������������� + animationType: 'pop-in', // ������������,������APP������ + animationDuration: 300, // ������������������������,������������,������APP������ + intercept: false // ������������������ + } + // ������route������������������������������������������������������������route���������������this������������route��������������� + // ������������������������������this������ + this.route = this.route.bind(this) + } + + // ������url���������������"/"��������������������������������������������� + addRootPath(url) { + return url[0] === '/' ? url : `/${url}` + } + + // ������������������ + mixinParam(url, params) { + url = url && this.addRootPath(url) + + // ���������������������������������������������������"/","?","="������������/page/index/index?name=mary" + // ���������url������get������������������������������"?" + let query = '' + if (/.*\/.*\?.*=.*/.test(url)) { + // object������������get��������������� + query = uni.$u.queryParams(params, false) + // ������������get������,���������������������������������������"&"������ + return url += `&${query}` + } + // ���������������������������������url������������������query���������������������"?/&"��������������� + query = uni.$u.queryParams(params) + return url += query + } + + // ��������������������� + async route(options = {}, params = {}) { + // ��������������������������������������������� + let mergeConfig = {} + + if (typeof options === 'string') { + // ������options���������������������route(url, params)��������� + mergeConfig.url = this.mixinParam(options, params) + mergeConfig.type = 'navigateTo' + } else { + mergeConfig = uni.$u.deepMerge(this.config, options) + // ������������������mergeConfig������url���params������������ + mergeConfig.url = this.mixinParam(options.url, options.params) + } + + // ��������������������������������������������������������������������������������������������������������������������������������������������������������� + if (mergeConfig.url === uni.$u.page()) return + + if (params.intercept) { + this.config.intercept = params.intercept + } + // params������������������������ + mergeConfig.params = params + // ��������������������� + mergeConfig = uni.$u.deepMerge(this.config, mergeConfig) + // ������������������������������������ + if (typeof uni.$u.routeIntercept === 'function') { + // ���������promise���������������������resolve(true)������resolve(false)��������������������������������� + const isNext = await new Promise((resolve, reject) => { + uni.$u.routeIntercept(mergeConfig, resolve) + }) + // ������isNext���true������������������������ + isNext && this.openPage(mergeConfig) + } else { + this.openPage(mergeConfig) + } + } + + // ������������������ + openPage(config) { + // ������������ + const { + url, + type, + delta, + animationType, + animationDuration + } = config + if (config.type == 'navigateTo' || config.type == 'to') { + uni.navigateTo({ + url, + animationType, + animationDuration + }) + } + if (config.type == 'redirectTo' || config.type == 'redirect') { + uni.redirectTo({ + url + }) + } + if (config.type == 'switchTab' || config.type == 'tab') { + uni.switchTab({ + url + }) + } + if (config.type == 'reLaunch' || config.type == 'launch') { + uni.reLaunch({ + url + }) + } + if (config.type == 'navigateBack' || config.type == 'back') { + uni.navigateBack({ + delta + }) + } + } +} + +export default (new Router()).route diff --git a/uni_modules/uview-ui/package.json b/uni_modules/uview-ui/package.json new file mode 100644 index 0000000..e1169e5 --- /dev/null +++ b/uni_modules/uview-ui/package.json @@ -0,0 +1,84 @@ +{ + "id": "uview-ui", + "name": "uview-ui", + "displayName": "uView2.0������������������������������������������", + "version": "2.0.36", + "description": "uView UI���������������nvue������������������������������������������������������������������������", + "keywords": [ + "uview", + "uview", + "ui", + "ui", + "uni-app", + "uni-app", + "ui" + ], + "repository": "https://github.com/umicro/uView2.0", + "engines": { + "HBuilderX": "^3.1.0" + }, + "dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "1416956117" + }, + "declaration": { + "ads": "���", + "data": "���", + "permissions": "���" + }, + "npmurl": "https://www.npmjs.com/package/uview-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "Vue": { + "vue2": "y", + "vue3": "n" + }, + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "���������������(Android)": "y", + "QQ���������(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "���������": { + "������": "y", + "������": "y", + "������": "y", + "������������": "y", + "QQ": "y" + }, + "���������": { + "������": "y", + "������": "y" + } + } + } + } +} diff --git a/uni_modules/uview-ui/theme.scss b/uni_modules/uview-ui/theme.scss new file mode 100644 index 0000000..331b30f --- /dev/null +++ b/uni_modules/uview-ui/theme.scss @@ -0,0 +1,44 @@ +// ������������uView������������������������������������������������uni.scss������������������������������ +// uni.scss��������������������������������������������������������������������������������������������������������������������������� +// ���uni.scss������������scss���������������������������������������������������main.js������App.vue������ + +$u-main-color: #303133; +$u-content-color: #606266; +$u-tips-color: #909193; +$u-light-color: #c0c4cc; +$u-border-color: #dadbde; +$u-bg-color: #f3f4f6; +$u-disabled-color: #c8c9cc; + +$u-primary: #3c9cff; +$u-primary-dark: #398ade; +$u-primary-disabled: #9acafc; +$u-primary-light: #ecf5ff; + +$u-warning: #f9ae3d; +$u-warning-dark: #f1a532; +$u-warning-disabled: #f9d39b; +$u-warning-light: #fdf6ec; + +$u-success: #5ac725; +$u-success-dark: #53c21d; +$u-success-disabled: #a9e08f; +$u-success-light: #f5fff0; + +$u-error: #f56c6c; +$u-error-dark: #e45656; +$u-error-disabled: #f7b2b2; +$u-error-light: #fef0f0; + +$u-info: #909399; +$u-info-dark: #767a82; +$u-info-disabled: #c4c6c9; +$u-info-light: #f4f4f5; + +// scss���������������������������#ifndef +@mixin flex($direction: row) { + /* #ifndef APP-NVUE */ + display: flex; + /* #endif */ + flex-direction: $direction; +} diff --git a/unpackage/.gitkeep b/unpackage/.gitkeep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/unpackage/.gitkeep diff --git a/utils/http.js b/utils/http.js new file mode 100644 index 0000000..dd26b93 --- /dev/null +++ b/utils/http.js @@ -0,0 +1,28 @@ +import request from "./request"; + +// ������������������������������������������������������������������������������������������������������������������������������������ +export function httpGet(url, params) { + return new Promise((resolve, reject) => { + request + .get(url, params) + .then((result) => { + resolve(result); + }) + .catch((err) => { + reject(err); + }); + }); +} + +export function httpPost(url, params) { + return new Promise((resolve, reject) => { + request + .post(url, params) + .then((result) => { + resolve(result); + }) + .catch((err) => { + reject(err); + }); + }); +} diff --git a/utils/login.js b/utils/login.js new file mode 100644 index 0000000..aec9bba --- /dev/null +++ b/utils/login.js @@ -0,0 +1,42 @@ +import request from '@/utils/request' +export function login(params) { + return new Promise((resolve, reject) => { + request.post('/AppUser/logins', params, false).then(result => { + resolve(result) + }).catch(err => { + reject(err) + }) + }) +} +export function logout() { + return request({ + url: '/logout', + method: 'post', + }) +} +export function getUserInfor(token) { + request.post('/getUserInfo', token).then(result => { + uni.setStorageSync('userInfo', JSON.stringify(result.data)) + }) +} +export function getDic() { + request.get('/dict/list').then(result => { + uni.setStorageSync('dict', JSON.stringify(result.data)) + uni.setStorageSync('dictObj', JSON.stringify(objToArr(result.data))) + }) +} + +function arrToObj(arr) { + return arr.reduce((obj, item) => { + obj[item.value] = item.name + return obj + }, {}) +} + +function objToArr(obj) { + const objde = {} + for (const key in obj) { + objde[key] = arrToObj(obj[key]) + } + return objde +} \ No newline at end of file diff --git a/utils/request.js b/utils/request.js new file mode 100644 index 0000000..8496956 --- /dev/null +++ b/utils/request.js @@ -0,0 +1,74 @@ +import storage from './storage' // ������������ +export default { + console(options) { + if (config.debug) { + console.log('<<===============================================>>') + // console.log("request start"); + // console.log("header" + JSON.stringify(options.header)); + // console.log("method: " + options.method + " URL: " + options.url); + // console.log(options.data); + // console.log("request end"); + // console.log("<<===============================================>>"); + } + }, + domain() { + return config.uni_app_web_api_url.replace('api', '') + }, + send(options = {}, isLogin = true) { + const baseUrl = process.uniEnv.baseUrl + storage.set('baseUrl', baseUrl) + // loading������ + uni.showLoading({ title: '���������', }) + // ��������������������������������������������� + options.url = baseUrl + '' + options.url + // ������������ + options.method = options.method || 'GET' + // ������������������ + if (isLogin) { + let token = storage.get('token') + console.log('tokentoken', token) + if (token !== null) { + // options.header["token"] = token; + options.header = { + token: token, + Authorization: token, + } + } + } + // this.console(options); // ��������������������������������������������������� + // ������Promise������ + return new Promise((resolve, reject) => { + uni.request(options).then(data => { + var [error, res] = data + if (error != null) { + reject(error) + } else { + // ��������������������������������������������������������������������������� + if (res.data.code === 0) { + uni.hideLoading() + // uni.navigateTo({ + // url: "/pages/Login/login/login", + // }); + resolve(res.data) + } else { + uni.hideLoading() + reject(res.data.message) + } + } + }) + }) + }, + get(url = '', data = {}, isLogin = true) { + return this.send({ + url: url, + data: data, + }, isLogin) + }, + post(url = '', data = {}, isLogin = true) { + return this.send({ + url: url, + data: data, + method: 'POST', + }, isLogin) + }, +} \ No newline at end of file diff --git a/utils/storage.js b/utils/storage.js new file mode 100644 index 0000000..64b7e43 --- /dev/null +++ b/utils/storage.js @@ -0,0 +1,30 @@ +export default { + set(name, value) { + uni.setStorageSync(name, value); + }, + + setJson(name, value) { + uni.setStorageSync(name, JSON.stringify(value)); + }, + + get(name) { + return uni.getStorageSync(name); + }, + + getJson(name) { + const content = uni.getStorageSync(name); + if (!content) { + return null; + } + + return JSON.parse(content); + }, + + remove(name) { + uni.removeStorageSync(name); + }, + + clear() { + uni.clearStorageSync(); + }, +}; diff --git a/utils/utils.js b/utils/utils.js new file mode 100644 index 0000000..299edff --- /dev/null +++ b/utils/utils.js @@ -0,0 +1,179 @@ +import dayjs from "dayjs"; +export function msg(content, time = 3000) { + uni.showToast({ + icon: "none", + title: content, + duration: time, + }); +} + +export function showLoading(content = "���������������...", mask = true) { + uni.showLoading({ + title: content, + mask: mask, + }); +} + +export function hideLoading(timer = 0) { + if (timer > 0) { + var t = setTimeout(function () { + uni.hideLoading(); + clearTimeout(t); + }, timer); + } else { + uni.hideLoading(); + } +} + +export function in_array(search, array) { + let flag = false; + for (let i in array) { + if (array[i] == search) { + flag = true; + break; + } + } + + return flag; +} + +export function isDataType(data, type) { + return Object.prototype.toString.call(data) === "[object " + type + "]"; +} +// ��������������� +export function dateFormatter(dateObj) { + return dateObj ? dayjs(dateObj).format("YYYY-MM-DD") : ""; +} + +export function ltrim(str, char) { + let pos = str.indexOf(char); + let sonstr = str.substr(pos + 1); + return sonstr; +} + +export function rtrim(str, char) { + let pos = str.lastIndexOf(char); + let sonstr = str.substr(0, pos); + return sonstr; +} + +/** + * ���������������������������������������������������������������uni.navigateBack��������������������������� + */ +export function navigateTo(url, params) { + uni.navigateTo({ + url: parseUrl(url, params), + }); +} + +/** + * ��������������������������������������������������������� + */ +export function redirectTo(url, params) { + uni.redirectTo({ + url: parseUrl(url, params), + }); +} + +/** + * ��������������������������������������������������������� + */ +export function reLaunch(url, params) { + uni.reLaunch({ + url: parseUrl(url, params), + }); +} + +/** + * ��������� tabBar ��������������������������������� tabBar ��������� + */ +export function switchTab(url, params) { + uni.switchTab({ + url: parseUrl(url, params), + }); +} + +/** + * ������������������������������������������������������ + */ +export function navigateBack(delta) { + uni.navigateBack({ + delta: delta, + }); +} + +/** + * ������������������������������������������������������������������������������������������������ + */ +export function preloadPage(url, params) { + uni.preloadPage({ + url: parseUrl(url, params), + }); +} + +export function prePage() { + let pages = getCurrentPages(); + let prePage = pages[pages.length - 2]; + // #ifdef H5 + return prePage; + // #endif + return prePage.$vm; +} + +/** + * rpx���px + * @param int|float num + */ +export function rpx2px(num) { + // const info = uni.getSystemInfoSync() + // let scale = 750 / info.windowWidth; + // return (Number.isNaN(parseFloat(num)) ? 0 : parseFloat(num)) / scale; + return uni.upx2px(num); +} + +/** + * @param int|float num + */ +export function px2rpx(num) { + return num / (uni.upx2px(num) / num); +} + +/** + * ��������������������� + */ +export function getSystemInfo() { + const info = uni.getSystemInfoSync(); + return { + w: info.windowWidth, + h: info.windowHeight, + }; +} + +function parseUrl(url, params) { + let arr = []; + let string = ""; + for (let i in params) { + arr.push(i + "=" + params[i]); + } + + string = "/pages/" + url; + if (arr.length > 0) { + string += "?" + arr.join("&"); + } + + return string; +} +export function arrToObj(arr) { + return arr.reduce((obj, item) => { + obj[item.value] = item.name; + return obj; + }, {}); +} +export function objToArr(obj) { + const objde = {}; + + for (const key in obj) { + objde[key] = arrToObj(obj[key]); + } + return objde; +} -- Gitblit v1.8.0