From 1cd4b94cfe0e2b0e5283aeb8fe9b2d8ed883e6de Mon Sep 17 00:00:00 2001 From: yujialong <479214531@qq.com> Date: Mon, 20 Feb 2023 11:27:44 +0800 Subject: [PATCH] initial --- .gitignore | 1 + .hbuilderx/launch.json | 16 + App.vue | 36 + README.md | 1 + apis/modules/client.js | 54 + apis/modules/order.js | 38 + apis/modules/parner.js | 26 + apis/modules/product.js | 6 + apis/modules/user.js | 52 + apis/request.js | 89 + components/empty/empty.vue | 40 + components/filter-popup/components/mask.vue | 130 + components/filter-popup/components/popup.vue | 510 ++++ components/filter-popup/detail.md | 155 ++ components/filter-popup/filter-popup.vue | 466 ++++ components/uni-section/uni-section.vue | 140 + config/product.js | 10 + config/request.js | 21 + directives/auth.js | 16 + directives/index.js | 12 + index.html | 14 + libs/WXBizDataCrypt.js | 35 + libs/util.js | 107 + main.js | 39 + manifest.json | 60 + order/addCourse/addCourse.vue | 329 +++ order/curClient/curClient.vue | 266 ++ order/editCourse/editCourse.vue | 420 +++ order/orderDetail/orderDetail.vue | 644 +++++ order/ordered/ordered.vue | 270 ++ order/orders/orders.vue | 311 +++ package.json | 12 + pages.json | 231 ++ pages/account/account.vue | 61 + pages/addStaff/addStaff.vue | 51 + pages/clientDetail/clientDetail.vue | 372 +++ pages/clients/clients.vue | 244 ++ pages/email/email.vue | 113 + pages/index/index.vue | 349 +++ pages/login/login.vue | 236 ++ pages/password/password.vue | 62 + pages/person/person.vue | 140 + pages/phone/phone.vue | 119 + pages/plans/plans.vue | 199 ++ pages/products/products.vue | 217 ++ pages/qrcode/qrcode.vue | 108 + pages/send/send.vue | 105 + pages/setting/setting.vue | 90 + pages/teams/teams.vue | 162 ++ static/iconfont/iconfont.css | 32 + static/iconfont/iconfont.ttf | Bin 0 -> 2748 bytes static/image/arrow-down.png | Bin 0 -> 257 bytes static/image/avatar.png | Bin 0 -> 1459 bytes static/image/index/index1.png | Bin 0 -> 39359 bytes static/image/index/index10.png | Bin 0 -> 230 bytes static/image/index/index2.png | Bin 0 -> 73554 bytes static/image/index/index3.png | Bin 0 -> 1068 bytes static/image/index/index4.png | Bin 0 -> 840 bytes static/image/index/index5.png | Bin 0 -> 319 bytes static/image/index/index6.png | Bin 0 -> 727 bytes static/image/index/index7.png | Bin 0 -> 295 bytes static/image/index/index8.png | Bin 0 -> 844 bytes static/image/index/index9.png | Bin 0 -> 672 bytes static/image/login1.png | Bin 0 -> 11269 bytes static/image/login2.png | Bin 0 -> 5095 bytes static/image/logo.png | Bin 0 -> 4819 bytes static/image/none.png | Bin 0 -> 7894 bytes static/image/person-bg.png | Bin 0 -> 30195 bytes static/image/person1.png | Bin 0 -> 572 bytes static/image/person2.png | Bin 0 -> 654 bytes static/image/person3.png | Bin 0 -> 557 bytes static/image/person4.png | Bin 0 -> 1406 bytes static/image/phone.png | Bin 0 -> 313 bytes static/image/qrcode.png | Bin 0 -> 325 bytes static/image/school.png | Bin 0 -> 296 bytes static/image/tab1-1.png | Bin 0 -> 604 bytes static/image/tab1.png | Bin 0 -> 645 bytes static/image/tab2-1.png | Bin 0 -> 859 bytes static/image/tab2.png | Bin 0 -> 784 bytes static/image/tab3-1.png | Bin 0 -> 680 bytes static/image/tab3.png | Bin 0 -> 627 bytes static/image/trash.png | Bin 0 -> 416 bytes static/image/wechat.png | Bin 0 -> 552 bytes styles/common.scss | 221 ++ uni.scss | 3 + uni_modules/Sansnn-uQRCode/changelog.md | 44 + .../u-qrcode/gcanvas/bridge/bridge-weex.js | 241 ++ .../context-2d/FillStyleLinearGradient.js | 18 + .../gcanvas/context-2d/FillStylePattern.js | 8 + .../context-2d/FillStyleRadialGradient.js | 17 + .../gcanvas/context-2d/RenderingContext.js | 666 +++++ .../gcanvas/context-webgl/ActiveInfo.js | 11 + .../u-qrcode/gcanvas/context-webgl/Buffer.js | 21 + .../gcanvas/context-webgl/Framebuffer.js | 21 + .../u-qrcode/gcanvas/context-webgl/GLenum.js | 298 +++ .../gcanvas/context-webgl/GLmethod.js | 142 + .../u-qrcode/gcanvas/context-webgl/GLtype.js | 23 + .../u-qrcode/gcanvas/context-webgl/Program.js | 21 + .../gcanvas/context-webgl/Renderbuffer.js | 21 + .../gcanvas/context-webgl/RenderingContext.js | 1191 +++++++++ .../u-qrcode/gcanvas/context-webgl/Shader.js | 22 + .../context-webgl/ShaderPrecisionFormat.js | 11 + .../u-qrcode/gcanvas/context-webgl/Texture.js | 22 + .../gcanvas/context-webgl/UniformLocation.js | 22 + .../gcanvas/context-webgl/classUtils.js | 3 + .../components/u-qrcode/gcanvas/env/canvas.js | 74 + .../components/u-qrcode/gcanvas/env/image.js | 96 + .../components/u-qrcode/gcanvas/env/tool.js | 24 + .../components/u-qrcode/gcanvas/index.js | 39 + .../components/u-qrcode/u-qrcode.vue | 684 +++++ .../Sansnn-uQRCode/js_sdk/u-qrcode/license.md | 201 ++ .../Sansnn-uQRCode/js_sdk/u-qrcode/module.js | 2285 +++++++++++++++++ .../js_sdk/u-qrcode/package.json | 24 + .../Sansnn-uQRCode/js_sdk/u-qrcode/readme.md | 274 ++ .../js_sdk/u-qrcode/u-qrcode.js | 2285 +++++++++++++++++ uni_modules/Sansnn-uQRCode/package.json | 83 + uni_modules/Sansnn-uQRCode/readme.md | 274 ++ uni_modules/hpy-form-select/changelog.md | 2 + .../hpy-form-select/hpy-form-select.vue | 255 ++ uni_modules/hpy-form-select/package.json | 87 + uni_modules/hpy-form-select/readme.md | 169 ++ uni_modules/uni-badge/changelog.md | 29 + .../components/uni-badge/uni-badge.vue | 268 ++ uni_modules/uni-badge/package.json | 88 + uni_modules/uni-badge/readme.md | 10 + uni_modules/uni-calendar/changelog.md | 16 + .../components/uni-calendar/calendar.js | 546 ++++ .../components/uni-calendar/i18n/en.json | 12 + .../components/uni-calendar/i18n/index.js | 8 + .../components/uni-calendar/i18n/zh-Hans.json | 12 + .../components/uni-calendar/i18n/zh-Hant.json | 12 + .../uni-calendar/uni-calendar-item.vue | 181 ++ .../components/uni-calendar/uni-calendar.vue | 554 ++++ .../components/uni-calendar/util.js | 354 +++ uni_modules/uni-calendar/package.json | 88 + uni_modules/uni-calendar/readme.md | 103 + uni_modules/uni-card/changelog.md | 26 + .../uni-card/components/uni-card/uni-card.vue | 270 ++ uni_modules/uni-card/package.json | 90 + uni_modules/uni-card/readme.md | 12 + uni_modules/uni-collapse/changelog.md | 36 + .../uni-collapse-item/uni-collapse-item.vue | 402 +++ .../components/uni-collapse/uni-collapse.vue | 147 ++ uni_modules/uni-collapse/package.json | 89 + uni_modules/uni-collapse/readme.md | 12 + uni_modules/uni-combox/changelog.md | 15 + .../components/uni-combox/uni-combox.vue | 275 ++ uni_modules/uni-combox/package.json | 90 + uni_modules/uni-combox/readme.md | 11 + uni_modules/uni-countdown/changelog.md | 24 + .../components/uni-countdown/i18n/en.json | 6 + .../components/uni-countdown/i18n/index.js | 8 + .../uni-countdown/i18n/zh-Hans.json | 6 + .../uni-countdown/i18n/zh-Hant.json | 6 + .../uni-countdown/uni-countdown.vue | 271 ++ uni_modules/uni-countdown/package.json | 86 + uni_modules/uni-countdown/readme.md | 10 + uni_modules/uni-data-checkbox/changelog.md | 41 + .../uni-data-checkbox/uni-data-checkbox.vue | 817 ++++++ uni_modules/uni-data-checkbox/package.json | 87 + uni_modules/uni-data-checkbox/readme.md | 18 + uni_modules/uni-data-picker/changelog.md | 56 + .../components/uni-data-picker/keypress.js | 45 + .../uni-data-picker/uni-data-picker.vue | 539 ++++ .../uni-data-pickerview/uni-data-picker.js | 563 ++++ .../uni-data-pickerview.vue | 333 +++ uni_modules/uni-data-picker/package.json | 92 + uni_modules/uni-data-picker/readme.md | 22 + uni_modules/uni-dateformat/changelog.md | 10 + .../components/uni-dateformat/date-format.js | 200 ++ .../uni-dateformat/uni-dateformat.vue | 88 + uni_modules/uni-dateformat/package.json | 88 + uni_modules/uni-dateformat/readme.md | 11 + uni_modules/uni-datetime-picker/changelog.md | 89 + .../uni-datetime-picker/calendar-item.vue | 185 ++ .../uni-datetime-picker/calendar.vue | 898 +++++++ .../uni-datetime-picker/i18n/en.json | 19 + .../uni-datetime-picker/i18n/index.js | 8 + .../uni-datetime-picker/i18n/zh-Hans.json | 19 + .../uni-datetime-picker/i18n/zh-Hant.json | 19 + .../uni-datetime-picker/keypress.js | 45 + .../uni-datetime-picker/time-picker.vue | 927 +++++++ .../uni-datetime-picker.vue | 997 +++++++ .../components/uni-datetime-picker/util.js | 410 +++ uni_modules/uni-datetime-picker/package.json | 90 + uni_modules/uni-datetime-picker/readme.md | 21 + uni_modules/uni-drawer/changelog.md | 13 + .../components/uni-drawer/keypress.js | 45 + .../components/uni-drawer/uni-drawer.vue | 183 ++ uni_modules/uni-drawer/package.json | 87 + uni_modules/uni-drawer/readme.md | 10 + uni_modules/uni-easyinput/changelog.md | 35 + .../components/uni-easyinput/common.js | 56 + .../uni-easyinput/uni-easyinput.vue | 461 ++++ uni_modules/uni-easyinput/package.json | 90 + uni_modules/uni-easyinput/readme.md | 11 + uni_modules/uni-fab/changelog.md | 17 + .../uni-fab/components/uni-fab/uni-fab.vue | 475 ++++ uni_modules/uni-fab/package.json | 87 + uni_modules/uni-fab/readme.md | 9 + uni_modules/uni-fav/changelog.md | 17 + .../uni-fav/components/uni-fav/i18n/en.json | 4 + .../uni-fav/components/uni-fav/i18n/index.js | 8 + .../components/uni-fav/i18n/zh-Hans.json | 4 + .../components/uni-fav/i18n/zh-Hant.json | 4 + .../uni-fav/components/uni-fav/uni-fav.vue | 156 ++ uni_modules/uni-fav/package.json | 89 + uni_modules/uni-fav/readme.md | 10 + uni_modules/uni-file-picker/changelog.md | 61 + .../uni-file-picker/choose-and-upload-file.js | 224 ++ .../uni-file-picker/uni-file-picker.vue | 651 +++++ .../uni-file-picker/upload-file.vue | 325 +++ .../uni-file-picker/upload-image.vue | 292 +++ .../components/uni-file-picker/utils.js | 109 + uni_modules/uni-file-picker/package.json | 86 + uni_modules/uni-file-picker/readme.md | 11 + uni_modules/uni-forms/changelog.md | 60 + .../uni-forms-item/uni-forms-item.vue | 509 ++++ .../components/uni-forms/uni-forms.vue | 472 ++++ .../components/uni-forms/validate.js | 486 ++++ uni_modules/uni-forms/package.json | 90 + uni_modules/uni-forms/readme.md | 23 + uni_modules/uni-goods-nav/changelog.md | 16 + .../components/uni-goods-nav/i18n/en.json | 6 + .../components/uni-goods-nav/i18n/index.js | 8 + .../uni-goods-nav/i18n/zh-Hans.json | 6 + .../uni-goods-nav/i18n/zh-Hant.json | 6 + .../uni-goods-nav/uni-goods-nav.vue | 224 ++ uni_modules/uni-goods-nav/package.json | 88 + uni_modules/uni-goods-nav/readme.md | 10 + uni_modules/uni-grid/changelog.md | 13 + .../uni-grid-item/uni-grid-item.vue | 127 + .../uni-grid/components/uni-grid/uni-grid.vue | 142 + uni_modules/uni-grid/package.json | 86 + uni_modules/uni-grid/readme.md | 11 + uni_modules/uni-group/changelog.md | 14 + .../components/uni-group/uni-group.vue | 130 + uni_modules/uni-group/package.json | 87 + uni_modules/uni-group/readme.md | 9 + uni_modules/uni-icons/changelog.md | 22 + .../uni-icons/components/uni-icons/icons.js | 1169 +++++++++ .../components/uni-icons/uni-icons.vue | 96 + .../components/uni-icons/uniicons.css | 663 +++++ .../components/uni-icons/uniicons.ttf | Bin 0 -> 35760 bytes uni_modules/uni-icons/package.json | 86 + uni_modules/uni-icons/readme.md | 8 + uni_modules/uni-indexed-list/changelog.md | 17 + .../uni-indexed-list-item.vue | 144 ++ .../uni-indexed-list/uni-indexed-list.vue | 367 +++ uni_modules/uni-indexed-list/package.json | 89 + uni_modules/uni-indexed-list/readme.md | 11 + uni_modules/uni-link/changelog.md | 17 + .../uni-link/components/uni-link/uni-link.vue | 128 + uni_modules/uni-link/package.json | 87 + uni_modules/uni-link/readme.md | 11 + uni_modules/uni-list/changelog.md | 20 + .../components/uni-list-ad/uni-list-ad.vue | 107 + .../uni-list-chat/uni-list-chat.scss | 58 + .../uni-list-chat/uni-list-chat.vue | 538 ++++ .../uni-list-item/uni-list-item.vue | 454 ++++ .../uni-list/components/uni-list/uni-list.vue | 108 + .../components/uni-list/uni-refresh.vue | 65 + .../components/uni-list/uni-refresh.wxs | 87 + uni_modules/uni-list/package.json | 91 + uni_modules/uni-list/readme.md | 346 +++ uni_modules/uni-load-more/changelog.md | 19 + .../components/uni-load-more/i18n/en.json | 5 + .../components/uni-load-more/i18n/index.js | 8 + .../uni-load-more/i18n/zh-Hans.json | 5 + .../uni-load-more/i18n/zh-Hant.json | 5 + .../uni-load-more/uni-load-more.vue | 399 +++ uni_modules/uni-load-more/package.json | 86 + uni_modules/uni-load-more/readme.md | 14 + uni_modules/uni-nav-bar/changelog.md | 37 + .../components/uni-nav-bar/uni-nav-bar.vue | 343 +++ .../components/uni-nav-bar/uni-status-bar.vue | 27 + uni_modules/uni-nav-bar/package.json | 89 + uni_modules/uni-nav-bar/readme.md | 15 + uni_modules/uni-notice-bar/changelog.md | 16 + .../uni-notice-bar/uni-notice-bar.vue | 395 +++ uni_modules/uni-notice-bar/package.json | 90 + uni_modules/uni-notice-bar/readme.md | 13 + uni_modules/uni-number-box/changelog.md | 25 + .../uni-number-box/uni-number-box.vue | 221 ++ uni_modules/uni-number-box/package.json | 85 + uni_modules/uni-number-box/readme.md | 13 + uni_modules/uni-pagination/changelog.md | 20 + .../components/uni-pagination/i18n/en.json | 4 + .../components/uni-pagination/i18n/es.json | 4 + .../components/uni-pagination/i18n/fr.json | 4 + .../components/uni-pagination/i18n/index.js | 12 + .../uni-pagination/i18n/zh-Hans.json | 4 + .../uni-pagination/i18n/zh-Hant.json | 4 + .../uni-pagination/uni-pagination.vue | 409 +++ uni_modules/uni-pagination/package.json | 86 + uni_modules/uni-pagination/readme.md | 13 + uni_modules/uni-popup/changelog.md | 60 + .../components/uni-popup-dialog/keypress.js | 45 + .../uni-popup-dialog/uni-popup-dialog.vue | 271 ++ .../uni-popup-message/uni-popup-message.vue | 143 ++ .../uni-popup-share/uni-popup-share.vue | 187 ++ .../components/uni-popup/i18n/en.json | 7 + .../components/uni-popup/i18n/index.js | 8 + .../components/uni-popup/i18n/zh-Hans.json | 7 + .../components/uni-popup/i18n/zh-Hant.json | 7 + .../components/uni-popup/keypress.js | 45 + .../uni-popup/components/uni-popup/popup.js | 26 + .../components/uni-popup/uni-popup.vue | 474 ++++ uni_modules/uni-popup/package.json | 90 + uni_modules/uni-popup/readme.md | 17 + uni_modules/uni-rate/changelog.md | 25 + .../uni-rate/components/uni-rate/uni-rate.vue | 361 +++ uni_modules/uni-rate/package.json | 88 + uni_modules/uni-rate/readme.md | 12 + uni_modules/uni-row/changelog.md | 10 + .../uni-row/components/uni-col/uni-col.vue | 317 +++ .../uni-row/components/uni-row/uni-row.vue | 190 ++ uni_modules/uni-row/package.json | 87 + uni_modules/uni-row/readme.md | 10 + uni_modules/uni-scss/changelog.md | 8 + uni_modules/uni-scss/index.scss | 1 + uni_modules/uni-scss/package.json | 82 + uni_modules/uni-scss/readme.md | 4 + uni_modules/uni-scss/styles/index.scss | 7 + .../uni-scss/styles/setting/_border.scss | 3 + .../uni-scss/styles/setting/_color.scss | 66 + .../uni-scss/styles/setting/_radius.scss | 55 + .../uni-scss/styles/setting/_space.scss | 56 + .../uni-scss/styles/setting/_styles.scss | 167 ++ .../uni-scss/styles/setting/_text.scss | 24 + .../uni-scss/styles/setting/_variables.scss | 146 ++ .../uni-scss/styles/tools/functions.scss | 19 + uni_modules/uni-scss/theme.scss | 31 + uni_modules/uni-scss/variables.scss | 62 + uni_modules/uni-search-bar/changelog.md | 27 + .../components/uni-search-bar/i18n/en.json | 4 + .../components/uni-search-bar/i18n/index.js | 8 + .../uni-search-bar/i18n/zh-Hans.json | 4 + .../uni-search-bar/i18n/zh-Hant.json | 4 + .../uni-search-bar/uni-search-bar.vue | 287 +++ uni_modules/uni-search-bar/package.json | 89 + uni_modules/uni-search-bar/readme.md | 14 + .../uni-segmented-control/changelog.md | 9 + .../uni-segmented-control.vue | 145 ++ .../uni-segmented-control/package.json | 87 + uni_modules/uni-segmented-control/readme.md | 13 + uni_modules/uni-steps/changelog.md | 16 + .../components/uni-steps/uni-steps.vue | 269 ++ uni_modules/uni-steps/package.json | 89 + uni_modules/uni-steps/readme.md | 13 + uni_modules/uni-swipe-action/changelog.md | 33 + .../uni-swipe-action-item/bindingx.js | 300 +++ .../components/uni-swipe-action-item/isPC.js | 12 + .../uni-swipe-action-item/mpalipay.js | 193 ++ .../uni-swipe-action-item/mpother.js | 257 ++ .../components/uni-swipe-action-item/mpwxs.js | 82 + .../uni-swipe-action-item/render.js | 270 ++ .../uni-swipe-action-item.vue | 344 +++ .../components/uni-swipe-action-item/wx.wxs | 341 +++ .../uni-swipe-action/uni-swipe-action.vue | 60 + uni_modules/uni-swipe-action/package.json | 87 + uni_modules/uni-swipe-action/readme.md | 11 + uni_modules/uni-swiper-dot/changelog.md | 12 + .../uni-swiper-dot/uni-swiper-dot.vue | 218 ++ uni_modules/uni-swiper-dot/package.json | 87 + uni_modules/uni-swiper-dot/readme.md | 11 + uni_modules/uni-table/changelog.md | 21 + .../components/uni-table/uni-table.vue | 455 ++++ .../components/uni-tbody/uni-tbody.vue | 29 + .../uni-table/components/uni-td/uni-td.vue | 90 + .../components/uni-th/filter-dropdown.vue | 503 ++++ .../uni-table/components/uni-th/uni-th.vue | 274 ++ .../components/uni-thead/uni-thead.vue | 129 + .../components/uni-tr/table-checkbox.vue | 179 ++ .../uni-table/components/uni-tr/uni-tr.vue | 171 ++ uni_modules/uni-table/i18n/en.json | 9 + uni_modules/uni-table/i18n/es.json | 9 + uni_modules/uni-table/i18n/fr.json | 9 + uni_modules/uni-table/i18n/index.js | 12 + uni_modules/uni-table/i18n/zh-Hans.json | 9 + uni_modules/uni-table/i18n/zh-Hant.json | 9 + uni_modules/uni-table/package.json | 86 + uni_modules/uni-table/readme.md | 13 + uni_modules/uni-tag/changelog.md | 21 + .../uni-tag/components/uni-tag/uni-tag.vue | 252 ++ uni_modules/uni-tag/package.json | 87 + uni_modules/uni-tag/readme.md | 13 + uni_modules/uni-test/changelog.md | 39 + .../uni-test/components/uni-test/uni-test.vue | 26 + uni_modules/uni-test/package.json | 83 + uni_modules/uni-test/readme.md | 10 + uni_modules/uni-title/changelog.md | 8 + .../components/uni-title/uni-title.vue | 171 ++ uni_modules/uni-title/package.json | 88 + uni_modules/uni-title/readme.md | 14 + uni_modules/uni-transition/changelog.md | 20 + .../uni-transition/createAnimation.js | 128 + .../uni-transition/uni-transition.vue | 277 ++ uni_modules/uni-transition/package.json | 87 + uni_modules/uni-transition/readme.md | 11 + uni_modules/uni-ui/changelog.md | 383 +++ .../uni-ui/components/uni-ui/uni-ui.vue | 7 + uni_modules/uni-ui/package.json | 128 + uni_modules/uni-ui/readme.md | 248 ++ 404 files changed, 52264 insertions(+) create mode 100644 .gitignore create mode 100644 .hbuilderx/launch.json create mode 100644 App.vue create mode 100644 README.md create mode 100644 apis/modules/client.js create mode 100644 apis/modules/order.js create mode 100644 apis/modules/parner.js create mode 100644 apis/modules/product.js create mode 100644 apis/modules/user.js create mode 100644 apis/request.js create mode 100644 components/empty/empty.vue create mode 100644 components/filter-popup/components/mask.vue create mode 100644 components/filter-popup/components/popup.vue create mode 100644 components/filter-popup/detail.md create mode 100644 components/filter-popup/filter-popup.vue create mode 100644 components/uni-section/uni-section.vue create mode 100644 config/product.js create mode 100644 config/request.js create mode 100644 directives/auth.js create mode 100644 directives/index.js create mode 100644 index.html create mode 100644 libs/WXBizDataCrypt.js create mode 100644 libs/util.js create mode 100644 main.js create mode 100644 manifest.json create mode 100644 order/addCourse/addCourse.vue create mode 100644 order/curClient/curClient.vue create mode 100644 order/editCourse/editCourse.vue create mode 100644 order/orderDetail/orderDetail.vue create mode 100644 order/ordered/ordered.vue create mode 100644 order/orders/orders.vue create mode 100644 package.json create mode 100644 pages.json create mode 100644 pages/account/account.vue create mode 100644 pages/addStaff/addStaff.vue create mode 100644 pages/clientDetail/clientDetail.vue create mode 100644 pages/clients/clients.vue create mode 100644 pages/email/email.vue create mode 100644 pages/index/index.vue create mode 100644 pages/login/login.vue create mode 100644 pages/password/password.vue create mode 100644 pages/person/person.vue create mode 100644 pages/phone/phone.vue create mode 100644 pages/plans/plans.vue create mode 100644 pages/products/products.vue create mode 100644 pages/qrcode/qrcode.vue create mode 100644 pages/send/send.vue create mode 100644 pages/setting/setting.vue create mode 100644 pages/teams/teams.vue create mode 100644 static/iconfont/iconfont.css create mode 100644 static/iconfont/iconfont.ttf create mode 100644 static/image/arrow-down.png create mode 100644 static/image/avatar.png create mode 100644 static/image/index/index1.png create mode 100644 static/image/index/index10.png create mode 100644 static/image/index/index2.png create mode 100644 static/image/index/index3.png create mode 100644 static/image/index/index4.png create mode 100644 static/image/index/index5.png create mode 100644 static/image/index/index6.png create mode 100644 static/image/index/index7.png create mode 100644 static/image/index/index8.png create mode 100644 static/image/index/index9.png create mode 100644 static/image/login1.png create mode 100644 static/image/login2.png create mode 100644 static/image/logo.png create mode 100644 static/image/none.png create mode 100644 static/image/person-bg.png create mode 100644 static/image/person1.png create mode 100644 static/image/person2.png create mode 100644 static/image/person3.png create mode 100644 static/image/person4.png create mode 100644 static/image/phone.png create mode 100644 static/image/qrcode.png create mode 100644 static/image/school.png create mode 100644 static/image/tab1-1.png create mode 100644 static/image/tab1.png create mode 100644 static/image/tab2-1.png create mode 100644 static/image/tab2.png create mode 100644 static/image/tab3-1.png create mode 100644 static/image/tab3.png create mode 100644 static/image/trash.png create mode 100644 static/image/wechat.png create mode 100644 styles/common.scss create mode 100644 uni.scss create mode 100644 uni_modules/Sansnn-uQRCode/changelog.md create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/bridge/bridge-weex.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/FillStyleLinearGradient.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/FillStylePattern.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/FillStyleRadialGradient.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/RenderingContext.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/ActiveInfo.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Buffer.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Framebuffer.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/GLenum.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/GLmethod.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/GLtype.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Program.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Renderbuffer.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/RenderingContext.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Shader.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/ShaderPrecisionFormat.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Texture.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/UniformLocation.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/classUtils.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/env/canvas.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/env/image.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/env/tool.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/index.js create mode 100644 uni_modules/Sansnn-uQRCode/components/u-qrcode/u-qrcode.vue create mode 100644 uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/license.md create mode 100644 uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/module.js create mode 100644 uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/package.json create mode 100644 uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/readme.md create mode 100644 uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/u-qrcode.js create mode 100644 uni_modules/Sansnn-uQRCode/package.json create mode 100644 uni_modules/Sansnn-uQRCode/readme.md create mode 100644 uni_modules/hpy-form-select/changelog.md create mode 100644 uni_modules/hpy-form-select/components/hpy-form-select/hpy-form-select.vue create mode 100644 uni_modules/hpy-form-select/package.json create mode 100644 uni_modules/hpy-form-select/readme.md create mode 100644 uni_modules/uni-badge/changelog.md create mode 100644 uni_modules/uni-badge/components/uni-badge/uni-badge.vue create mode 100644 uni_modules/uni-badge/package.json create mode 100644 uni_modules/uni-badge/readme.md create mode 100644 uni_modules/uni-calendar/changelog.md create mode 100644 uni_modules/uni-calendar/components/uni-calendar/calendar.js create mode 100644 uni_modules/uni-calendar/components/uni-calendar/i18n/en.json create mode 100644 uni_modules/uni-calendar/components/uni-calendar/i18n/index.js create mode 100644 uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json create mode 100644 uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json create mode 100644 uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue create mode 100644 uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue create mode 100644 uni_modules/uni-calendar/components/uni-calendar/util.js create mode 100644 uni_modules/uni-calendar/package.json create mode 100644 uni_modules/uni-calendar/readme.md create mode 100644 uni_modules/uni-card/changelog.md create mode 100644 uni_modules/uni-card/components/uni-card/uni-card.vue create mode 100644 uni_modules/uni-card/package.json create mode 100644 uni_modules/uni-card/readme.md create mode 100644 uni_modules/uni-collapse/changelog.md create mode 100644 uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue create mode 100644 uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue create mode 100644 uni_modules/uni-collapse/package.json create mode 100644 uni_modules/uni-collapse/readme.md create mode 100644 uni_modules/uni-combox/changelog.md create mode 100644 uni_modules/uni-combox/components/uni-combox/uni-combox.vue create mode 100644 uni_modules/uni-combox/package.json create mode 100644 uni_modules/uni-combox/readme.md create mode 100644 uni_modules/uni-countdown/changelog.md create mode 100644 uni_modules/uni-countdown/components/uni-countdown/i18n/en.json create mode 100644 uni_modules/uni-countdown/components/uni-countdown/i18n/index.js create mode 100644 uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hans.json create mode 100644 uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hant.json create mode 100644 uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue create mode 100644 uni_modules/uni-countdown/package.json create mode 100644 uni_modules/uni-countdown/readme.md create mode 100644 uni_modules/uni-data-checkbox/changelog.md create mode 100644 uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue create mode 100644 uni_modules/uni-data-checkbox/package.json create mode 100644 uni_modules/uni-data-checkbox/readme.md create mode 100644 uni_modules/uni-data-picker/changelog.md create mode 100644 uni_modules/uni-data-picker/components/uni-data-picker/keypress.js create mode 100644 uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue create mode 100644 uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js create mode 100644 uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue create mode 100644 uni_modules/uni-data-picker/package.json create mode 100644 uni_modules/uni-data-picker/readme.md create mode 100644 uni_modules/uni-dateformat/changelog.md create mode 100644 uni_modules/uni-dateformat/components/uni-dateformat/date-format.js create mode 100644 uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue create mode 100644 uni_modules/uni-dateformat/package.json create mode 100644 uni_modules/uni-dateformat/readme.md create mode 100644 uni_modules/uni-datetime-picker/changelog.md create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/index.js create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hans.json create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hant.json create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/keypress.js create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js create mode 100644 uni_modules/uni-datetime-picker/package.json create mode 100644 uni_modules/uni-datetime-picker/readme.md create mode 100644 uni_modules/uni-drawer/changelog.md create mode 100644 uni_modules/uni-drawer/components/uni-drawer/keypress.js create mode 100644 uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue create mode 100644 uni_modules/uni-drawer/package.json create mode 100644 uni_modules/uni-drawer/readme.md create mode 100644 uni_modules/uni-easyinput/changelog.md create mode 100644 uni_modules/uni-easyinput/components/uni-easyinput/common.js create mode 100644 uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue create mode 100644 uni_modules/uni-easyinput/package.json create mode 100644 uni_modules/uni-easyinput/readme.md create mode 100644 uni_modules/uni-fab/changelog.md create mode 100644 uni_modules/uni-fab/components/uni-fab/uni-fab.vue create mode 100644 uni_modules/uni-fab/package.json create mode 100644 uni_modules/uni-fab/readme.md create mode 100644 uni_modules/uni-fav/changelog.md create mode 100644 uni_modules/uni-fav/components/uni-fav/i18n/en.json create mode 100644 uni_modules/uni-fav/components/uni-fav/i18n/index.js create mode 100644 uni_modules/uni-fav/components/uni-fav/i18n/zh-Hans.json create mode 100644 uni_modules/uni-fav/components/uni-fav/i18n/zh-Hant.json create mode 100644 uni_modules/uni-fav/components/uni-fav/uni-fav.vue create mode 100644 uni_modules/uni-fav/package.json create mode 100644 uni_modules/uni-fav/readme.md create mode 100644 uni_modules/uni-file-picker/changelog.md create mode 100644 uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js create mode 100644 uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue create mode 100644 uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue create mode 100644 uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue create mode 100644 uni_modules/uni-file-picker/components/uni-file-picker/utils.js create mode 100644 uni_modules/uni-file-picker/package.json create mode 100644 uni_modules/uni-file-picker/readme.md create mode 100644 uni_modules/uni-forms/changelog.md create mode 100644 uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue create mode 100644 uni_modules/uni-forms/components/uni-forms/uni-forms.vue create mode 100644 uni_modules/uni-forms/components/uni-forms/validate.js create mode 100644 uni_modules/uni-forms/package.json create mode 100644 uni_modules/uni-forms/readme.md create mode 100644 uni_modules/uni-goods-nav/changelog.md create mode 100644 uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/en.json create mode 100644 uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/index.js create mode 100644 uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hans.json create mode 100644 uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hant.json create mode 100644 uni_modules/uni-goods-nav/components/uni-goods-nav/uni-goods-nav.vue create mode 100644 uni_modules/uni-goods-nav/package.json create mode 100644 uni_modules/uni-goods-nav/readme.md create mode 100644 uni_modules/uni-grid/changelog.md create mode 100644 uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue create mode 100644 uni_modules/uni-grid/components/uni-grid/uni-grid.vue create mode 100644 uni_modules/uni-grid/package.json create mode 100644 uni_modules/uni-grid/readme.md create mode 100644 uni_modules/uni-group/changelog.md create mode 100644 uni_modules/uni-group/components/uni-group/uni-group.vue create mode 100644 uni_modules/uni-group/package.json create mode 100644 uni_modules/uni-group/readme.md create mode 100644 uni_modules/uni-icons/changelog.md create mode 100644 uni_modules/uni-icons/components/uni-icons/icons.js create mode 100644 uni_modules/uni-icons/components/uni-icons/uni-icons.vue create mode 100644 uni_modules/uni-icons/components/uni-icons/uniicons.css create mode 100644 uni_modules/uni-icons/components/uni-icons/uniicons.ttf create mode 100644 uni_modules/uni-icons/package.json create mode 100644 uni_modules/uni-icons/readme.md create mode 100644 uni_modules/uni-indexed-list/changelog.md create mode 100644 uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue create mode 100644 uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue create mode 100644 uni_modules/uni-indexed-list/package.json create mode 100644 uni_modules/uni-indexed-list/readme.md create mode 100644 uni_modules/uni-link/changelog.md create mode 100644 uni_modules/uni-link/components/uni-link/uni-link.vue create mode 100644 uni_modules/uni-link/package.json create mode 100644 uni_modules/uni-link/readme.md create mode 100644 uni_modules/uni-list/changelog.md create mode 100644 uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue create mode 100644 uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss create mode 100644 uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue create mode 100644 uni_modules/uni-list/components/uni-list-item/uni-list-item.vue create mode 100644 uni_modules/uni-list/components/uni-list/uni-list.vue create mode 100644 uni_modules/uni-list/components/uni-list/uni-refresh.vue create mode 100644 uni_modules/uni-list/components/uni-list/uni-refresh.wxs create mode 100644 uni_modules/uni-list/package.json create mode 100644 uni_modules/uni-list/readme.md create mode 100644 uni_modules/uni-load-more/changelog.md create mode 100644 uni_modules/uni-load-more/components/uni-load-more/i18n/en.json create mode 100644 uni_modules/uni-load-more/components/uni-load-more/i18n/index.js create mode 100644 uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json create mode 100644 uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json create mode 100644 uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue create mode 100644 uni_modules/uni-load-more/package.json create mode 100644 uni_modules/uni-load-more/readme.md create mode 100644 uni_modules/uni-nav-bar/changelog.md create mode 100644 uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue create mode 100644 uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue create mode 100644 uni_modules/uni-nav-bar/package.json create mode 100644 uni_modules/uni-nav-bar/readme.md create mode 100644 uni_modules/uni-notice-bar/changelog.md create mode 100644 uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue create mode 100644 uni_modules/uni-notice-bar/package.json create mode 100644 uni_modules/uni-notice-bar/readme.md create mode 100644 uni_modules/uni-number-box/changelog.md create mode 100644 uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue create mode 100644 uni_modules/uni-number-box/package.json create mode 100644 uni_modules/uni-number-box/readme.md create mode 100644 uni_modules/uni-pagination/changelog.md create mode 100644 uni_modules/uni-pagination/components/uni-pagination/i18n/en.json create mode 100644 uni_modules/uni-pagination/components/uni-pagination/i18n/es.json create mode 100644 uni_modules/uni-pagination/components/uni-pagination/i18n/fr.json create mode 100644 uni_modules/uni-pagination/components/uni-pagination/i18n/index.js create mode 100644 uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hans.json create mode 100644 uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hant.json create mode 100644 uni_modules/uni-pagination/components/uni-pagination/uni-pagination.vue create mode 100644 uni_modules/uni-pagination/package.json create mode 100644 uni_modules/uni-pagination/readme.md create mode 100644 uni_modules/uni-popup/changelog.md create mode 100644 uni_modules/uni-popup/components/uni-popup-dialog/keypress.js create mode 100644 uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue create mode 100644 uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue create mode 100644 uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue create mode 100644 uni_modules/uni-popup/components/uni-popup/i18n/en.json create mode 100644 uni_modules/uni-popup/components/uni-popup/i18n/index.js create mode 100644 uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json create mode 100644 uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json create mode 100644 uni_modules/uni-popup/components/uni-popup/keypress.js create mode 100644 uni_modules/uni-popup/components/uni-popup/popup.js create mode 100644 uni_modules/uni-popup/components/uni-popup/uni-popup.vue create mode 100644 uni_modules/uni-popup/package.json create mode 100644 uni_modules/uni-popup/readme.md create mode 100644 uni_modules/uni-rate/changelog.md create mode 100644 uni_modules/uni-rate/components/uni-rate/uni-rate.vue create mode 100644 uni_modules/uni-rate/package.json create mode 100644 uni_modules/uni-rate/readme.md create mode 100644 uni_modules/uni-row/changelog.md create mode 100644 uni_modules/uni-row/components/uni-col/uni-col.vue create mode 100644 uni_modules/uni-row/components/uni-row/uni-row.vue create mode 100644 uni_modules/uni-row/package.json create mode 100644 uni_modules/uni-row/readme.md create mode 100644 uni_modules/uni-scss/changelog.md create mode 100644 uni_modules/uni-scss/index.scss create mode 100644 uni_modules/uni-scss/package.json create mode 100644 uni_modules/uni-scss/readme.md create mode 100644 uni_modules/uni-scss/styles/index.scss create mode 100644 uni_modules/uni-scss/styles/setting/_border.scss create mode 100644 uni_modules/uni-scss/styles/setting/_color.scss create mode 100644 uni_modules/uni-scss/styles/setting/_radius.scss create mode 100644 uni_modules/uni-scss/styles/setting/_space.scss create mode 100644 uni_modules/uni-scss/styles/setting/_styles.scss create mode 100644 uni_modules/uni-scss/styles/setting/_text.scss create mode 100644 uni_modules/uni-scss/styles/setting/_variables.scss create mode 100644 uni_modules/uni-scss/styles/tools/functions.scss create mode 100644 uni_modules/uni-scss/theme.scss create mode 100644 uni_modules/uni-scss/variables.scss create mode 100644 uni_modules/uni-search-bar/changelog.md create mode 100644 uni_modules/uni-search-bar/components/uni-search-bar/i18n/en.json create mode 100644 uni_modules/uni-search-bar/components/uni-search-bar/i18n/index.js create mode 100644 uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json create mode 100644 uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json create mode 100644 uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue create mode 100644 uni_modules/uni-search-bar/package.json create mode 100644 uni_modules/uni-search-bar/readme.md create mode 100644 uni_modules/uni-segmented-control/changelog.md create mode 100644 uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue create mode 100644 uni_modules/uni-segmented-control/package.json create mode 100644 uni_modules/uni-segmented-control/readme.md create mode 100644 uni_modules/uni-steps/changelog.md create mode 100644 uni_modules/uni-steps/components/uni-steps/uni-steps.vue create mode 100644 uni_modules/uni-steps/package.json create mode 100644 uni_modules/uni-steps/readme.md create mode 100644 uni_modules/uni-swipe-action/changelog.md create mode 100644 uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js create mode 100644 uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js create mode 100644 uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js create mode 100644 uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js create mode 100644 uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js create mode 100644 uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js create mode 100644 uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue create mode 100644 uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs create mode 100644 uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue create mode 100644 uni_modules/uni-swipe-action/package.json create mode 100644 uni_modules/uni-swipe-action/readme.md create mode 100644 uni_modules/uni-swiper-dot/changelog.md create mode 100644 uni_modules/uni-swiper-dot/components/uni-swiper-dot/uni-swiper-dot.vue create mode 100644 uni_modules/uni-swiper-dot/package.json create mode 100644 uni_modules/uni-swiper-dot/readme.md create mode 100644 uni_modules/uni-table/changelog.md create mode 100644 uni_modules/uni-table/components/uni-table/uni-table.vue create mode 100644 uni_modules/uni-table/components/uni-tbody/uni-tbody.vue create mode 100644 uni_modules/uni-table/components/uni-td/uni-td.vue create mode 100644 uni_modules/uni-table/components/uni-th/filter-dropdown.vue create mode 100644 uni_modules/uni-table/components/uni-th/uni-th.vue create mode 100644 uni_modules/uni-table/components/uni-thead/uni-thead.vue create mode 100644 uni_modules/uni-table/components/uni-tr/table-checkbox.vue create mode 100644 uni_modules/uni-table/components/uni-tr/uni-tr.vue create mode 100644 uni_modules/uni-table/i18n/en.json create mode 100644 uni_modules/uni-table/i18n/es.json create mode 100644 uni_modules/uni-table/i18n/fr.json create mode 100644 uni_modules/uni-table/i18n/index.js create mode 100644 uni_modules/uni-table/i18n/zh-Hans.json create mode 100644 uni_modules/uni-table/i18n/zh-Hant.json create mode 100644 uni_modules/uni-table/package.json create mode 100644 uni_modules/uni-table/readme.md create mode 100644 uni_modules/uni-tag/changelog.md create mode 100644 uni_modules/uni-tag/components/uni-tag/uni-tag.vue create mode 100644 uni_modules/uni-tag/package.json create mode 100644 uni_modules/uni-tag/readme.md create mode 100644 uni_modules/uni-test/changelog.md create mode 100644 uni_modules/uni-test/components/uni-test/uni-test.vue create mode 100644 uni_modules/uni-test/package.json create mode 100644 uni_modules/uni-test/readme.md create mode 100644 uni_modules/uni-title/changelog.md create mode 100644 uni_modules/uni-title/components/uni-title/uni-title.vue create mode 100644 uni_modules/uni-title/package.json create mode 100644 uni_modules/uni-title/readme.md create mode 100644 uni_modules/uni-transition/changelog.md create mode 100644 uni_modules/uni-transition/components/uni-transition/createAnimation.js create mode 100644 uni_modules/uni-transition/components/uni-transition/uni-transition.vue create mode 100644 uni_modules/uni-transition/package.json create mode 100644 uni_modules/uni-transition/readme.md create mode 100644 uni_modules/uni-ui/changelog.md create mode 100644 uni_modules/uni-ui/components/uni-ui/uni-ui.vue create mode 100644 uni_modules/uni-ui/package.json create mode 100644 uni_modules/uni-ui/readme.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..efe7735 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +unpackage \ 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..55be1b2 --- /dev/null +++ b/App.vue @@ -0,0 +1,36 @@ + + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..654e9e1 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# 或然中台小程序端 \ No newline at end of file diff --git a/apis/modules/client.js b/apis/modules/client.js new file mode 100644 index 0000000..560370c --- /dev/null +++ b/apis/modules/client.js @@ -0,0 +1,54 @@ +import request from '@/apis/request.js' +const { get, post } = request + +export const queryCustomer = (data) => { + return post('nakadai/nakadai/customer/queryCustomer', data) +} + +export const list = (data) => { + return post('nakadai/nakadai/applets/customer/getCustomerListBasedOnBusinessManagerId', data) +} + +export const all = (data) => { + return post('nakadai/nakadai/applets/customer/customerList', data) +} + +export const queryCustomerDetails = (data) => { + return get('nakadai/nakadai/customer/queryCustomerDetails', data) +} + +export const querySchool = (data) => { + return get('nakadai/nakadai/school/querySchool', data) +} + +export const queryIndustryClass = (data) => { + return get('nakadai/nakadai/hrIndustryClass/queryIndustryClass', data) +} + +export const queryIndustry = (data) => { + return get('nakadai/nakadai/hrIndustry/queryIndustry', data) +} + +export const queryCustomerIsExists = (data) => { + return get('nakadai/nakadai/customer/queryCustomerIsExists', data) +} + +export const addCustomer = (data) => { + return post('nakadai/nakadai/customer/addCustomer', data) +} + +export const updateCustomer = (data) => { + return post('nakadai/nakadai/customer/updateCustomer', data) +} + +export const getProductsSubscribedByCustomers = (data) => { + return get('nakadai/nakadai/customer/getProductsSubscribedByCustomers', data) +} + +export const getTeamsByAccountId = (data) => { + return post('nakadai/nakadai/applets/customer/getTeamsByAccountId', data) +} + +export const getTheBusinessManagerIdsUnderTheTeam = id => { + return post(`nakadai/nakadai/applets/customer/getTheBusinessManagerIdsUnderTheTeam?id=${id}`) +} \ No newline at end of file diff --git a/apis/modules/order.js b/apis/modules/order.js new file mode 100644 index 0000000..0d8332b --- /dev/null +++ b/apis/modules/order.js @@ -0,0 +1,38 @@ +import request from '@/apis/request.js' +const { get, post } = request + +export const getOrderOtherTime = (data) => { + return post('nakadai/nakadai/orderOther/getOrderOtherTime', data) +} + +export const add = (data) => { + return post('nakadai/nakadai/order/add', data) +} + +export const update = (data) => { + return post('nakadai/nakadai/order/update', data) +} + +export const getDetail = (data) => { + return get('nakadai/nakadai/order/get', data) +} + +export const renew = (data) => { + return post('nakadai/nakadai/orderOther/renew', data) +} + +export const list = (data) => { + return post('nakadai/nakadai/applets/order/orderList', data) +} + +export const orderList = (data) => { + return post('nakadai/nakadai/order/list', data) +} + +export const del = (data) => { + return post('nakadai/nakadai/order/delete', data) +} + +export const miniProgramOrderRecord = (data) => { + return post('nakadai/nakadai/applets/order/miniProgramOrderRecord', data) +} \ No newline at end of file diff --git a/apis/modules/parner.js b/apis/modules/parner.js new file mode 100644 index 0000000..8d9925e --- /dev/null +++ b/apis/modules/parner.js @@ -0,0 +1,26 @@ +import request from '@/apis/request.js' +const { get, post } = request + +export const savePartnerAccount = (data) => { + return post('nakadai/nakadai/partnerAccount/savePartnerAccount', data) +} + +export const teamList = (data) => { + return post('nakadai/nakadai/partnerAccount/partnerAccountList', data) +} + +export const generateInvitationCode = accountId => { + return post(`nakadai/nakadai/partnerAccount/generateInvitationCode?accountId=${accountId}`) +} + +export const treeList = (data) => { + return post('nakadai/nakadai/partnerClassification/treeList', data) +} + +export const my = (data) => { + return get('nakadai/nakadai/partner-team/my', data) +} + +export const mailFileSend = (data) => { + return post('nakadai/nakadai/partnerAccount/mailFileSend', data) +} \ No newline at end of file diff --git a/apis/modules/product.js b/apis/modules/product.js new file mode 100644 index 0000000..739f421 --- /dev/null +++ b/apis/modules/product.js @@ -0,0 +1,6 @@ +import request from '@/apis/request.js' +const { get, post } = request + +export const AppletsDataProductList = (data) => { + return post('nakadai/nakadai/dataProduct/AppletsDataProductList', data) +} \ No newline at end of file diff --git a/apis/modules/user.js b/apis/modules/user.js new file mode 100644 index 0000000..3b8b175 --- /dev/null +++ b/apis/modules/user.js @@ -0,0 +1,52 @@ +import request from '@/apis/request.js' +const { get, post } = request + +export const login = (data) => { + return post('users/users/user/weChatAppletCallback', data) +} + +export const userBinding = (data) => { + return post('users/users/user/userBinding', data) +} + +export const examinePassword = (data) => { + return post('users/users/userAccount/examinePassword', data) +} + +export const getUserRolesPermissionMenu = (data) => { + return get('users/users/user-role/getUserRolesPermissionMenu', data) +} + +export const updatePersonCenter = (data) => { + return post('users/users/userAccount/updatePersonCenter', data) +} + +export const queryUserInfoDetails = () => { + return get('users/users/userAccount/queryUserInfoDetails') +} + +export const updateMyEmail = (data) => { + return post('nakadai/nakadai/partner-team/updateMyEmail', data) +} + +export const mailCodeSend = (data) => { + return post('nakadai/nakadai/partner-team/mailCodeSend', data) +} + +export const changeAccount = account => { + return post(`users/users/applets/mine/changeAccount?account=${account}`) +} + +export const changePhoneNumber = (phone, code) => { + return post(`users/users/applets/mine/changePhoneNumber?phone=${phone}&code=${code}`) +} + +export const checkIfAnAccountExists = account => { + return post(`users/users/applets/mine/checkIfAnAccountExists?account=${account}`) +} + +export const checkIfThePhoneNumberExists = phone => { + return post(`users/users/applets/mine/checkIfThePhoneNumberExists?phone=${phone}`) +} + +export const updateUserAvatars = `http://39.108.250.202:9000/users/users/userAccount/updateUserAvatars` \ No newline at end of file diff --git a/apis/request.js b/apis/request.js new file mode 100644 index 0000000..a75d827 --- /dev/null +++ b/apis/request.js @@ -0,0 +1,89 @@ +import config from '@/config/request' +let HTTP_COUNT = 0 // loading次数 + +const request = options => { + HTTP_COUNT++ + if (config.showLoading) { + // 请求数据时的loading + // uni.showToast({ + // title: '加载中', + // duration: 200, + // icon: 'loading' + // }) + } + const header = Object.assign({}, config.headers, { + token: uni.getStorageSync('token') + }) + const otherUrl = ['getTeamsByAccountId'] + return new Promise((resolve, reject)=>{ + const { url } = options + uni.request({ + header, + // url: (otherUrl.map(e => config.baseURL.includes(e)) ? 'http://192.168.31.137:9000/' : config.baseURL) + url, + url: config.baseURL + url, + method: options.method || 'GET', // 请求类型,默认为GET + data: options.data || {}, // 请求参数,默认空对象 + success: ({ data }) => { + const { status, message } = data + // 状态判断,根据后台定义并提示 + if (status === 200) { + resolve(data) + } else if (status == 401) { + // 登录过期 + uni.clearStorageSync() + uni.showToast({ + title: message, + icon: 'none' + }) + setTimeout(() => { + uni.navigateTo({ + url: '../login/login' + }) + }, 1500) + reject(data) + } else if (!status) { + resolve(data) + } else { + uni.showToast({ + title: message, + icon: 'none' + }) + reject(data) + } + }, + fail: err => { + uni.showToast({ + title: '请求失败!', + icon: 'none' + }) + reject(err) + }, + complete: () => { + if (config.showLoading) { + // HTTP_COUNT-- + // HTTP_COUNT || uni.hideLoading() + } + } + }) + }) +} + +const get = (url, data, options = {}) => { + options.method = 'GET' + options.data = data + options.url = url + return request(options) +} + +const post = (url, data, options = {}) => { + options.method = 'POST' + options.data = data + options.url = url + return request(options) +} + +export default { + request, + get, + post +} \ No newline at end of file diff --git a/components/empty/empty.vue b/components/empty/empty.vue new file mode 100644 index 0000000..42d2f06 --- /dev/null +++ b/components/empty/empty.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/components/filter-popup/components/mask.vue b/components/filter-popup/components/mask.vue new file mode 100644 index 0000000..521f0d9 --- /dev/null +++ b/components/filter-popup/components/mask.vue @@ -0,0 +1,130 @@ + + + + + diff --git a/components/filter-popup/components/popup.vue b/components/filter-popup/components/popup.vue new file mode 100644 index 0000000..fffcfdc --- /dev/null +++ b/components/filter-popup/components/popup.vue @@ -0,0 +1,510 @@ + + + + + diff --git a/components/filter-popup/detail.md b/components/filter-popup/detail.md new file mode 100644 index 0000000..e704412 --- /dev/null +++ b/components/filter-popup/detail.md @@ -0,0 +1,155 @@ +## 导入即用 全端支持 + +### 有问题 + wx : zy597172583 标注来意 可评论 看到及时回复 +1.使用方式 + +```javascript + + + diff --git a/components/uni-section/uni-section.vue b/components/uni-section/uni-section.vue new file mode 100644 index 0000000..a68c7b7 --- /dev/null +++ b/components/uni-section/uni-section.vue @@ -0,0 +1,140 @@ + + + + diff --git a/config/product.js b/config/product.js new file mode 100644 index 0000000..206e21d --- /dev/null +++ b/config/product.js @@ -0,0 +1,10 @@ +/** +/** + * 产品 配置文件 + * @author yujialong + */ + +export default { + normalIcon: 'https://huoran.oss-cn-shenzhen.aliyuncs.com/20220609/png/1534733700683030528.png', // 通用图标 + dataIcon: 'https://huoran.oss-cn-shenzhen.aliyuncs.com/20220627/png/1541256164447641600.png' // 数据图标 +} diff --git a/config/request.js b/config/request.js new file mode 100644 index 0000000..3b20681 --- /dev/null +++ b/config/request.js @@ -0,0 +1,21 @@ +/** +/** + * 请求配置文件 + * @author yujialong + */ + +export default { + baseURL: 'https://huorantech.cn/', + // baseURL: 'http://192.168.31.137:9000/', + // baseURL: 'http://121.37.12.51/', + headers: { + 'Content-Type': 'application/json;charset=UTF-8' + }, + data: {}, + method: 'POST', + responseType: 'json', // 响应数据类型 + withCredentials: false, // 携带cookie + // ======================== 以下为注入axios的配置项 ============================= + showLoading: true, // 是否显示加载动画 + isFormData: false // 是否序列化表单数据 +} diff --git a/directives/auth.js b/directives/auth.js new file mode 100644 index 0000000..be3a722 --- /dev/null +++ b/directives/auth.js @@ -0,0 +1,16 @@ +/** + * @description 鉴权指令 + * 当传入的权限当前用户没有时,会移除该组件 + * 用例:text 或者:text + * */ +export default { + inserted(el, binding, vnode) { + const btnText = el.innerText + const btnPermissions = uni.getStorageSync('auth') + if (btnText && btnPermissions && btnPermissions.length) { + const isPermission = btnPermissions.includes(btnText) + // 如果按钮集合里没有该权限,就把该按钮给去除 + !isPermission && el.parentNode && el.parentNode.removeChild(el) + } + }, +}; diff --git a/directives/index.js b/directives/index.js new file mode 100644 index 0000000..63e26af --- /dev/null +++ b/directives/index.js @@ -0,0 +1,12 @@ +/** + * 插件 + * */ + +import auth from './auth' + +export default { + async install(Vue, options) { + // 指令 + Vue.directive('auth', auth) + } +}; \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..9efb733 --- /dev/null +++ b/index.html @@ -0,0 +1,14 @@ + + + + + + + + + + +
+ + + diff --git a/libs/WXBizDataCrypt.js b/libs/WXBizDataCrypt.js new file mode 100644 index 0000000..36b3de1 --- /dev/null +++ b/libs/WXBizDataCrypt.js @@ -0,0 +1,35 @@ +var crypto = require('crypto') + +function WXBizDataCrypt(appId, sessionKey) { + this.appId = appId + this.sessionKey = sessionKey +} + +WXBizDataCrypt.prototype.decryptData = function (encryptedData, iv) { + // base64 decode + var sessionKey = new Buffer(this.sessionKey, 'base64') + encryptedData = new Buffer(encryptedData, 'base64') + iv = new Buffer(iv, 'base64') + + try { + // 解密 + var decipher = crypto.createDecipheriv('aes-128-cbc', sessionKey, iv) + // 设置自动 padding 为 true,删除填充补位 + decipher.setAutoPadding(true) + var decoded = decipher.update(encryptedData, 'binary', 'utf8') + decoded += decipher.final('utf8') + + decoded = JSON.parse(decoded) + + } catch (err) { + throw new Error('Illegal Buffer') + } + + if (decoded.watermark.appid !== this.appId) { + throw new Error('Illegal Buffer') + } + + return decoded +} + +module.exports = WXBizDataCrypt \ No newline at end of file diff --git a/libs/util.js b/libs/util.js new file mode 100644 index 0000000..70d94da --- /dev/null +++ b/libs/util.js @@ -0,0 +1,107 @@ +import Product from '@/config/product' + +const files = [ + 'https://huorantech.cn/%E7%94%A8%E6%88%B7%E6%9C%8D%E5%8A%A1%E5%8D%8F%E8%AE%AE.docx', // 用户服务协议 + 'https://huorantech.cn/%E7%94%A8%E6%88%B7%E9%9A%90%E7%A7%81%E5%8D%8F%E8%AE%AE.docx', // 用户隐私协议 + 'https://huorantech.cn/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD%E5%AE%9E%E9%AA%8C%E5%AE%A4%E5%BB%BA%E8%AE%BE%E6%96%B9%E6%A1%88-2020.1.docx', // 人工智能 + 'https://huorantech.cn/%E5%A4%A7%E6%95%B0%E6%8D%AE%E7%AE%A1%E7%90%86%E4%B8%8E%E5%BA%94%E7%94%A8%E4%B8%93%E4%B8%9A%E5%BB%BA%E8%AE%BE%E6%96%B9%E6%A1%88.docx', // 大数据 + 'https://huorantech.cn/%E9%87%91%E8%9E%8D%E7%A7%91%E6%8A%80%E5%AE%9E%E9%AA%8C%E5%AE%A4%E5%BB%BA%E8%AE%BE%E6%96%B9%E6%A1%88V2.0.docx', // 金融科技 +] +export default { + // 路由跳转 + to(url) { + uni.navigateTo({ + url + }) + }, + // 成功提示 + sucMsg(title, duration = 1500) { + uni.showToast({ + title, + duration + }) + }, + // 错误提示 + errMsg(title, duration = 1500) { + uni.showToast({ + title, + icon: 'none', + duration + }) + }, + // 如果非数字,则返回0 + handleNaN(val) { + return isNaN(val) ? 0 : val + }, + // 小于10,返回0+传入值 + preZero(val) { + return val < 10 ? '0' + val : val + }, + //返回格式化时间,传参例如:"yyyy-MM-dd hh:mm:ss" + formatDate(date, fmt = 'yyyy-MM-dd hh:mm:ss') { + var date = date ? date : new Date() + var o = { + "M+" : date.getMonth()+1, //月份 + "d+" : date.getDate(), //日 + "h+" : date.getHours(), //小时 + "m+" : date.getMinutes(), //分 + "s+" : date.getSeconds(), //秒 + "q+" : Math.floor((date.getMonth()+3)/3), //季度 + "S" : date.getMilliseconds() //毫秒 + } + if(/(y+)/.test(fmt)) { + fmt=fmt.replace(RegExp.$1, (date.getFullYear()+"").substr(4 - RegExp.$1.length)) + } + for(var k in o) { + if(new RegExp("("+ k +")").test(fmt)){ + fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length))) + } + } + return fmt + }, + // 获取商务经理id + getBmId(val) { + return uni.getStorageSync('team').partnerId + }, + // 获取商务经理名称 + getBmName(val) { + return uni.getStorageSync('team').partnerClassificationName + }, + // 返回图标。如果有图标,则直接返回,否则判断是否是数据产品,即productType=2,如果是,则取数据图标,否则则显示通用图标,这两个图标都在config/product.js里有配置 + getIcon(e) { + return e.miniProgramPictureAddress || (e.productType === 2 ? Product.dataIcon : Product.normalIcon) + }, + // 预览文档 + openFile(id) { + uni.showLoading({ + title: '加载中', + mask: true + }) + // 下载文件资源到本地 + uni.downloadFile({ + url: files[id], + success: function(res) { + uni.hideLoading(); + uni.showLoading({ + title: '正在打开', + mask: true + }) + // 新开页面打开文档,支持格式:doc, xls, ppt, pdf, docx, xlsx, pptx。 + uni.openDocument({ + filePath: res.tempFilePath, + fileType: 'docx', // 文件类型,指定文件类型打开文件,有效值 doc, xls, ppt, pdf, docx, xlsx, pptx + showMenu: true, // 允许出现分享功能 + success: res => { + uni.hideLoading() + }, + fail: openError => { + uni.hideLoading() + } + }) + }, + fail: function(err) { + uni.hideLoading() + } + }) + } +} \ No newline at end of file diff --git a/main.js b/main.js new file mode 100644 index 0000000..a0768de --- /dev/null +++ b/main.js @@ -0,0 +1,39 @@ + +// #ifndef VUE3 +import Vue from 'vue' +import App from './App' +import util from '@/libs/util' +import plugins from '@/directives' + +Vue.config.productionTip = false +Vue.prototype.$util = util +Vue.use(plugins) + +App.mpType = 'app' + +// 权限控制 +Vue.prototype.auth = function(text){ + const auth = uni.getStorageSync('auth') + if (text && auth && auth.length) { + const isPermission = auth.includes(text) + return auth.includes(text) + } + // return true +} + +const app = new Vue({ + ...App +}) +app.$mount() +// #endif + +// #ifdef VUE3 +import { createSSRApp } from 'vue' +import App from './App.vue' +export function createApp() { + const app = createSSRApp(App) + return { + app + } +} +// #endif \ No newline at end of file diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..58d36e2 --- /dev/null +++ b/manifest.json @@ -0,0 +1,60 @@ +{ + "name" : "或然crm", + "appid" : "__UNI__2E89BA6", + "description" : "", + "versionName" : "1.0.0", + "versionCode" : "100", + "transformPx" : false, + "app-plus" : { + /* 5+App特有相关 */ + "usingComponents" : true, + "nvueCompiler" : "uni-app", + "splashscreen" : { + "alwaysShowBeforeRender" : true, + "waiting" : true, + "autoclose" : true, + "delay" : 0 + }, + "modules" : {}, + /* 模块配置 */ + "distribute" : { + /* 应用发布信息 */ + "android" : { + /* android打包配置 */ + "permissions" : [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ] + }, + "ios" : {}, + /* ios打包配置 */ + "sdkConfigs" : {} + } + }, + /* SDK配置 */ + "quickapp" : {}, + /* 快应用特有相关 */ + "mp-weixin" : { + "appid" : "wx88cd6037d54f230a", + "setting" : { + "urlCheck" : false, + "es6" : true, + "minified" : true + }, + "usingComponents" : true + }, + "vueVersion" : "2" +} diff --git a/order/addCourse/addCourse.vue b/order/addCourse/addCourse.vue new file mode 100644 index 0000000..ddcac1d --- /dev/null +++ b/order/addCourse/addCourse.vue @@ -0,0 +1,329 @@ + + + + + diff --git a/order/curClient/curClient.vue b/order/curClient/curClient.vue new file mode 100644 index 0000000..1fa3992 --- /dev/null +++ b/order/curClient/curClient.vue @@ -0,0 +1,266 @@ + + + + + diff --git a/order/editCourse/editCourse.vue b/order/editCourse/editCourse.vue new file mode 100644 index 0000000..ae21e0e --- /dev/null +++ b/order/editCourse/editCourse.vue @@ -0,0 +1,420 @@ + + + + + diff --git a/order/orderDetail/orderDetail.vue b/order/orderDetail/orderDetail.vue new file mode 100644 index 0000000..39a8e04 --- /dev/null +++ b/order/orderDetail/orderDetail.vue @@ -0,0 +1,644 @@ + + + + + diff --git a/order/ordered/ordered.vue b/order/ordered/ordered.vue new file mode 100644 index 0000000..e412121 --- /dev/null +++ b/order/ordered/ordered.vue @@ -0,0 +1,270 @@ + + + + + diff --git a/order/orders/orders.vue b/order/orders/orders.vue new file mode 100644 index 0000000..17fa698 --- /dev/null +++ b/order/orders/orders.vue @@ -0,0 +1,311 @@ + + + + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..de153de --- /dev/null +++ b/package.json @@ -0,0 +1,12 @@ +{ + "id": "filter-popup", + "name": "筛选 菜单 筛选菜单 上拉筛选 ", + "version": "1.0.4", + "description": "筛选菜单,支持单选和多选 , 选择后的数据通过.sync双向绑定,全端支持 导入即用", + "keywords": [ + "筛选", + "菜单", + "筛选菜单", + "上拉筛选" + ] +} \ No newline at end of file diff --git a/pages.json b/pages.json new file mode 100644 index 0000000..89bba10 --- /dev/null +++ b/pages.json @@ -0,0 +1,231 @@ +{ + "pages": [ + { + "path" : "pages/login/login", + "style" : + { + "navigationBarTitleText": "登录", + "enablePullDownRefresh": false + } + }, + { + "path" : "pages/index/index", + "style" : + { + "navigationBarTitleText": "", + "enablePullDownRefresh": false + } + }, + { + "path" : "pages/qrcode/qrcode", + "style" : + { + "navigationBarTitleText": "邀请加入", + "enablePullDownRefresh": false + } + }, + { + "path" : "pages/clients/clients", + "style" : + { + "navigationBarTitleText": "客户列表", + "enablePullDownRefresh": true + } + }, + { + "path" : "pages/products/products", + "style" : + { + "navigationBarTitleText": "产品", + "enablePullDownRefresh": true + } + }, + { + "path" : "pages/clientDetail/clientDetail", + "style" : + { + "navigationBarTitleText": "客户详情", + "enablePullDownRefresh": false + } + }, + { + "path" : "pages/addStaff/addStaff", + "style" : + { + "navigationBarTitleText": "邀请成员", + "enablePullDownRefresh": false + } + }, + { + "path" : "pages/plans/plans", + "style" : + { + "navigationBarTitleText": "产品方案", + "enablePullDownRefresh": false + } + }, + { + "path" : "pages/person/person", + "style" : + { + "navigationBarTitleText": "我的", + "enablePullDownRefresh": false + } + }, + { + "path" : "pages/send/send", + "style" : + { + "navigationBarTitleText": "下载发送", + "enablePullDownRefresh": false + } + }, + { + "path" : "pages/password/password", + "style" : + { + "navigationBarTitleText": "修改密码", + "enablePullDownRefresh": false + } + }, + { + "path" : "pages/setting/setting", + "style" : + { + "navigationBarTitleText": "设置", + "enablePullDownRefresh": false + } + }, + { + "path" : "pages/teams/teams", + "style" : + { + "navigationBarTitleText": "团队", + "enablePullDownRefresh": true + } + }, + { + "path" : "pages/account/account", + "style" : + { + "navigationBarTitleText": "修改账号", + "enablePullDownRefresh": false + } + } + ,{ + "path" : "pages/phone/phone", + "style" : + { + "navigationBarTitleText": "修改手机号", + "enablePullDownRefresh": false + } + } + ,{ + "path" : "pages/email/email", + "style" : + { + "navigationBarTitleText": "修改邮箱", + "enablePullDownRefresh": false + } + } + ], + "subPackages": [{ + "root": "order", + "pages": [ + { + "path": "orders/orders", + "style" : + { + "navigationBarTitleText": "订单列表", + "enablePullDownRefresh": true + } + }, + { + "path" : "addCourse/addCourse", + "style" : + { + "navigationBarTitleText": "选择产品", + "enablePullDownRefresh": true + } + }, + { + "path" : "orderDetail/orderDetail", + "style" : + { + "navigationBarTitleText": "订单详情", + "enablePullDownRefresh": false + } + }, + { + "path" : "ordered/ordered", + "style" : + { + "navigationBarTitleText": "已订阅产品", + "enablePullDownRefresh": false + } + }, + { + "path" : "editCourse/editCourse", + "style" : + { + "navigationBarTitleText": "编辑产品", + "enablePullDownRefresh": false + } + }, + { + "path" : "curClient/curClient", + "style" : + { + "navigationBarTitleText": "订单记录", + "enablePullDownRefresh": false + } + } + ] + }], + "preloadRule": { + "order/orders/orders": { + "network": "all", + "packages": ["__APP__"] + } + }, + "condition": { //模式配置,仅开发期间生效 + "current": 0, //当前激活的模式(list 的索引项) + "list": [{ + "name": "test", //模式名称 + "path": "pages/login/login" //启动页面,必选 + }] + }, + "globalStyle": { + "navigationBarTextStyle": "white", + "navigationBarTitleText": "或然中台", + "navigationBarBackgroundColor": "#007EFF", + "backgroundColor": "#f5f5f5", + "app-plus": { + "background": "#efeff4" + } + }, + "tabBar": { + "color": "#B8B9B8", + "selectedColor": "#007FFF", + "borderStyle": "white", + "backgroundColor": "#ffffff", + "fontSize": "16px", + "iconWidth": "30px", + "list": [{ + "pagePath": "pages/index/index", + "iconPath": "static/image/tab1.png", + "selectedIconPath": "static/image/tab1-1.png", + "text": "首页" + }, { + "pagePath": "pages/teams/teams", + "iconPath": "static/image/tab2.png", + "selectedIconPath": "static/image/tab2-1.png", + "text": "团队" + }, { + "pagePath": "pages/person/person", + "iconPath": "static/image/tab3.png", + "selectedIconPath": "static/image/tab3-1.png", + "text": "我的" + }] + } +} diff --git a/pages/account/account.vue b/pages/account/account.vue new file mode 100644 index 0000000..991902e --- /dev/null +++ b/pages/account/account.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/pages/addStaff/addStaff.vue b/pages/addStaff/addStaff.vue new file mode 100644 index 0000000..a48c611 --- /dev/null +++ b/pages/addStaff/addStaff.vue @@ -0,0 +1,51 @@ + + + + + diff --git a/pages/clientDetail/clientDetail.vue b/pages/clientDetail/clientDetail.vue new file mode 100644 index 0000000..df4f45c --- /dev/null +++ b/pages/clientDetail/clientDetail.vue @@ -0,0 +1,372 @@ + + + + + diff --git a/pages/clients/clients.vue b/pages/clients/clients.vue new file mode 100644 index 0000000..1853502 --- /dev/null +++ b/pages/clients/clients.vue @@ -0,0 +1,244 @@ + + + + + diff --git a/pages/email/email.vue b/pages/email/email.vue new file mode 100644 index 0000000..64f7850 --- /dev/null +++ b/pages/email/email.vue @@ -0,0 +1,113 @@ + + + + + diff --git a/pages/index/index.vue b/pages/index/index.vue new file mode 100644 index 0000000..29eae03 --- /dev/null +++ b/pages/index/index.vue @@ -0,0 +1,349 @@ + + + + + diff --git a/pages/login/login.vue b/pages/login/login.vue new file mode 100644 index 0000000..40ca523 --- /dev/null +++ b/pages/login/login.vue @@ -0,0 +1,236 @@ + + + + + diff --git a/pages/password/password.vue b/pages/password/password.vue new file mode 100644 index 0000000..94d0c0b --- /dev/null +++ b/pages/password/password.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/pages/person/person.vue b/pages/person/person.vue new file mode 100644 index 0000000..accb003 --- /dev/null +++ b/pages/person/person.vue @@ -0,0 +1,140 @@ + + + + + diff --git a/pages/phone/phone.vue b/pages/phone/phone.vue new file mode 100644 index 0000000..37c178b --- /dev/null +++ b/pages/phone/phone.vue @@ -0,0 +1,119 @@ + + + + + diff --git a/pages/plans/plans.vue b/pages/plans/plans.vue new file mode 100644 index 0000000..bdac8e1 --- /dev/null +++ b/pages/plans/plans.vue @@ -0,0 +1,199 @@ + + + + + diff --git a/pages/products/products.vue b/pages/products/products.vue new file mode 100644 index 0000000..a5676df --- /dev/null +++ b/pages/products/products.vue @@ -0,0 +1,217 @@ + + + + + diff --git a/pages/qrcode/qrcode.vue b/pages/qrcode/qrcode.vue new file mode 100644 index 0000000..4f9171b --- /dev/null +++ b/pages/qrcode/qrcode.vue @@ -0,0 +1,108 @@ + + + + + diff --git a/pages/send/send.vue b/pages/send/send.vue new file mode 100644 index 0000000..fe861e4 --- /dev/null +++ b/pages/send/send.vue @@ -0,0 +1,105 @@ + + + + + diff --git a/pages/setting/setting.vue b/pages/setting/setting.vue new file mode 100644 index 0000000..34e99a7 --- /dev/null +++ b/pages/setting/setting.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/pages/teams/teams.vue b/pages/teams/teams.vue new file mode 100644 index 0000000..3d0ac79 --- /dev/null +++ b/pages/teams/teams.vue @@ -0,0 +1,162 @@ + + + + + diff --git a/static/iconfont/iconfont.css b/static/iconfont/iconfont.css new file mode 100644 index 0000000..3a65ec5 --- /dev/null +++ b/static/iconfont/iconfont.css @@ -0,0 +1,32 @@ +@font-face { + font-family: "iconfont"; src: url('/static/iconfont/iconfont.ttf') format('truetype'); +} + +.iconfont { + font-family: "iconfont" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-qrcode:before { + content: "\e7dd"; +} + +.icon-dingdan:before { + content: "\e601"; +} + +.icon-product:before { + content: "\e788"; +} + +.icon-edit:before { + content: "\e621"; +} + +.icon-filter:before { + content: "\e6b9"; +} + diff --git a/static/iconfont/iconfont.ttf b/static/iconfont/iconfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..9db285d98e975304ef3231633c3fb0db66a3ea4b GIT binary patch literal 2748 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 N002ovPDHLkV1mHH19|`e literal 0 HcmV?d00001 diff --git a/static/image/index/index1.png b/static/image/index/index1.png new file mode 100644 index 0000000000000000000000000000000000000000..bdbfa6711d9296c59b6c23e159a2a47e1d0a0491 GIT binary patch literal 39359 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 V**i44$rjF6*2UngIEQUGe|` literal 0 HcmV?d00001 diff --git a/static/image/index/index2.png b/static/image/index/index2.png new file mode 100644 index 0000000000000000000000000000000000000000..1f007f4ba14a2975978136d507ebcb26abd50037 GIT binary patch literal 73554 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 Ns-lKMjhsdJ{{eM?+LHhP literal 0 HcmV?d00001 diff --git a/static/image/index/index3.png b/static/image/index/index3.png new file mode 100644 index 0000000000000000000000000000000000000000..a4024d1b508a742a4d9caba751f1d91b4ff0b34c GIT binary patch literal 1068 zcmXX^doY_>9Q}w$V;U-imaQi1QLnZveI?r|6)fAPG}dFwu&NPck_u_iOqF_!M>@8f z@#xalQcVfz(2b266uX2@rQVAr&GzAwNQWBTL3{U$`s4o2x#ym9W_~lbD1;V>GqEv& zAP5)q9rXf&H2v9yLZ&=jc?5y=kh5X_2trE$(f|kskPdv!0wmV<6;ZzE2+`=p16TB~ zU$}*Ihd|4Eg6KrHejeZg!v%d1@sm=v{YZ&+yHl(0hX62sxf9U`Q-J+;r@k3+!hnd7 zW#D)PSXTfuDKHt>DFFZwIl$mG*dqZ}mB2O!*ku7?8omG_xKshG zMPTheu&@Ni)Ic!{9`*x54cI3H!3DrO1AKE8{BgBagDie5{Q`{+ZS3ze*;pSQD9w1k z_=;2|5EzM~@E_n-w)^L~(T;jH`NUBx%x3G#D@CKYAU`0$)lxTklY4S%Hv}0L+5?Ux|!CT+btds|2@;jv^LXCVY0dRacrdTRIlYB2VYm|kHrt((wQ`Z zm)JP9A=yoq+@MZ?C2HWOXfWsU%4z(U;m+)m6wT!=bd}xEPfqf?=EYuFoo#4Y{>a2M z`JAwSU-gH}pPair3pLE>@)$IF@o+{*3A4Ia5;%{EUQMqcDih!^@l!S2;&Xp!G%Dn{ z3N|Jx8L)_Rk5)vf5$Lp)bBc(`hmF5`TjkX}UAQfeO!avAH^r53;b?VVUR zzPq+6#x0MGxFr6 z?E540r86q@i&Xb_%67Z;2ii9%0}Lweq16u_J=y#W7rru4Fj0s5ocYYK(#iOj6PgxenDev2VZzP^^QsHby6>Vzkjm^q3cxymZwsK8-r(KL$A<&=i zBAp+DEl3Fk2GTW@+_uZDX-}IccJIhyJeB>FGPOT{3eQ;a%iZAl#d9kc6OKNo8wK%a{>+iEl}BWh zq<-IDCX$>@1H<3-FL7Htq9rdT-mp4K;$0MQFca$-qh|H|^_%Qq@@x~yJQ!ylRhLJF z-wv&`a9c|17qbY3W61>RMV|$gwmxe*`B?Spt%hY$O+Xtj^3+K`EEaouAoli6p7hC@ R4*9we6y#5%ww#H}{U1p+AS?g? literal 0 HcmV?d00001 diff --git a/static/image/index/index4.png b/static/image/index/index4.png new file mode 100644 index 0000000000000000000000000000000000000000..f7ca20f2a1d824bd2de2c16c11a0915959543413 GIT binary patch literal 840 zcmeAS@N?(olHy`uVBq!ia0vp^ejv=j3?z4!T+jzn4+DHcT!FNF=6|J}|B5;P`4|0H z$oVgy{a-N`#KnSgK`J3gF$<~-s7wi{J{!y}`Oom|Kf?=OZ5HkGn<_R^rU%7kY6wZ_s`cX z-f~8NC-qcDe!YHh@0tdU_YYUhPPP~3`FwHz)ltfYnjpd8J*VK!DoUzw#aeU$&%X zTzYcq>U%!DZ;KNDYIYt?+8Cjcs{i)M5}lVPt8!1XFnCvF-QIT2Xu|}7NGrb`J8ddf zcs*&}Rl+4OrMD!YH|c0gXv{gy!+sAPb*+=)wN&pg^O~J{y@q{juz}(f;ktm^yN`Bp z=9^3n7Y==~I{iM||M{()R?W=b zx7Rm{E!$B!ZF92znkig=cD~=>HtXZP4IvJ9|Lx95bQ5HEFWFM%|9GczcK5M;8cXFj zoZ`E`^z{Ls`F^Ddt+9vHD;W$HmfW4^Sn)Qsy(Eu^gZpu*N4>AYfk*M$_y3>$YRBkW z(;gde<#p2o>o!{p*w=op?2XI3 zb-_I$65IY)gnqkQpZ4X@sjJhig&sVJ>H8jea+7j=;-jK_hmNRjFwoSBn89Nvrq&$S zAbDA#=*mU|NfBP|$p?=fO3_H&U?8cZiz Q08mdKI;Vst0L8bUSpWb4 literal 0 HcmV?d00001 diff --git a/static/image/index/index5.png b/static/image/index/index5.png new file mode 100644 index 0000000000000000000000000000000000000000..79c9e17512a8d1d83f44988e250ca9f4f7627311 GIT binary patch literal 319 zcmeAS@N?(olHy`uVBq!ia0vp^ejv=k3?yq>Z1sSYL4Z$)E09*o`Oom`zao%)^ItvZ zKadL%0SW>cKmcT1fAas=@BhI)|L;7$VF=X2RTAVE%y9W*L+Mi>0JA=EhZB ziBR)~SJ&>}=4JlW!DHElrmGkCiCxvXG9a=_*MvA|)tq#}KgS)1bdYGQvwm$Ej@y$R62F7!qE{-7)hu>bgS=3}8((usv zhWXUc0PZ~Z!k3@^`Cku9^NWu5XxjOb=l@*ePrghi8#iv;Xy~_Y@oWE9r5wBDA2*GR zg?}@EA>~djbY92`zG}*nQd-d-MxDm@-NSPZeBE3 z!KOPm`^O57n)S06A53&ReJ}Qw;)VHDmb<39KA#w=!j`*m{^DrM_q(>`OusDfq9dNLVmv4OfWxM6 z=aSi*KZMKVO?EC%+cM$N8Xk*O>BMv04hw2jkGx#TnY1>&=lIKN;UnD4*N*$H7J5>Y zyT5z31=|U6>&yEs?)N1|xGlY3tW%I!k@iZk{IE&Ih7(G8;SEi%mZmmk=3X~2Gc)^E bU(Fu4ikoq&{GM!JQeg0O^>bP0l+XkKq61)3 literal 0 HcmV?d00001 diff --git a/static/image/index/index7.png b/static/image/index/index7.png new file mode 100644 index 0000000000000000000000000000000000000000..d311da3746a45137d67d4b07bc75c1035cc7fbcf GIT binary patch literal 295 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)j!3-ol&c;6kQuYBpA+A8060ljdNgt?Rq$J2M zn1N&eJ1?n5#V498?#!_Kc6LF(Zw!Az?{=Vkv!{z=h{pM==T7rAIS9C1l$y0{rnvs= z|NBFmB~2Fg=EW3jD-Ud4K81N!T-6@Q%nUZZ`;({XIGsv-q_R_EfpYBPq=zwIFRnJz z4qt05&arsAsHQ^mbf%x)m;7IvJxDkj_wtEV=4;v8^J=PJ#r&_(=qYgF651`{mvo#( hc-IjI??){uJD5*Y3-(UruDcELuBWS?%Q~loCIGXoSf2m@ literal 0 HcmV?d00001 diff --git a/static/image/index/index8.png b/static/image/index/index8.png new file mode 100644 index 0000000000000000000000000000000000000000..287d75215f13867f0a959bb022402a8b817907fa GIT binary patch literal 844 zcmV-S1GD^zP)z{|}!36P^Dxe*Y4j|22O9D2o3%eE%el{}Y}6Hh=#lj{g&#|2BXB6P^Dwg8w9s z{}Y}6Gk*UIq5nF1{~eS6GlBmNq5m3}|1O6AJAD5PqyIa6{|lx6IDG&A|Njo3|1E|8 zHhupVnEx7;|Fqlx5}f}iiT^o!|1p989+Lm#@&6=^|1^OAx7h!!)BmZ}{~?e6)an27 z`2XMS|ESmh+wK3!RnN z|BAW)!`}a!$^VqY|9iv#m%#sCx&LRf|6im3G@JiMjQ^<2|2wMxMWX*9qW?6K|L`94 z=KufzA#_qsQvekR%=q~0>(|W6q@c{{90o6%F zK~y-)b<^j1f-n?-;Ztz$I=UB9#i~`RAns9Dr*_}}rSzB+F$#Wvd7qHL35ccRk)Yq} z^`AuIX>jlGqFB7es-;p%RnHGy$jwnvFxXunxkIF@;;zA>l4uTswy82hs1iC5%#qVD zR0-Hh3hpzNdPw5vYQL$Mqx@X9S-y1|X18lLIxkCZ%4IquKYMlFQ-pdmGWlcn4as~O z%1*||%H;D2L>GiQilawDX8>uwAJd6UG*~VLaoSMTZ6z|f7(~dF-1bB!7lz>ahYfX8 zB&IfC29v>$gqgQ?yJPgsuA+3!o-wM`rUOC+A9%^A^LG1TU5$E0f~Md>M8omLkYFrp zoM#4+pNu-kr;jb8*|@)NG>w*KS=K8VeBB8db@=jx&o?zk(*c>R3=uwv!{^pEYE1@Y zvSEnx;h5>V{(tLm(bV}P~k;$e2&S}VIOpxLA$(*i61r7H1%#_gd z7Y&vGEWn3#F&54Ey+9@dtCEah^`Aw5V&PsU{r7L$4|WZ#C?Phi>z`_yOQ56>4L#;C zvSeS*0GhhnIvMc_hxV*Ph9^bc%%ud|C69Ma<{F$O&O~#X0QXX{u|k3?#4J%UA`Z<_GwMxB}__+Zq3FV*sJ;4F6X# z{9g?g*~IXFKhysMO#jz_xj@EY=KpIMKwO~sdPbCzmehpA*TQP zfQnf_<^aJSMi65gWci!~a_i|Ns8@|NZIzcgOzU?fQSU^8a?J|4*0v zzg7AFnEn4lGXJ-;|9`pd|D}x8JERqWPLwYR@(X78rzpz7eD;LPkJqoSpFMtL$&48p z84(dbu3x{tWQog<|2~U1F)%Pr^mK6yu{fQ3C45@50S{|H>%t}G3bxIRlP@r7ZvMZu zS1^xJZvS_WPaAn&81C6>d;5L*w_C;u2G{aLyYA$j%u4@y_J>4P+sY>EDukX}ZBiZnpR%i<-GI zlb91))heIItEmg=&JJ}vBK2%nrQ*RKJdx`AzPwiw{Vd`#v$^$k_p+0#mqpIH7JjkGduHH xL2I1O{fj3rZBH<0tB&+hpZxOC8>t0P<@qMIyiuFm+7FCJ22WQ%mvv4FO#q|dNR$8o literal 0 HcmV?d00001 diff --git a/static/image/login1.png b/static/image/login1.png new file mode 100644 index 0000000000000000000000000000000000000000..49f7dc18ab46c41ead09f47e353c8efaf13f051a GIT binary patch literal 11269 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 W`{)MD=hMkw37we{8u8N5CH8*;^Y2dp literal 0 HcmV?d00001 diff --git a/static/image/none.png b/static/image/none.png new file mode 100644 index 0000000000000000000000000000000000000000..66d55dd533c14881c8698ddd38174a43ee24a6ce GIT binary patch literal 7894 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 literal 0 HcmV?d00001 diff --git a/static/image/person-bg.png b/static/image/person-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..73c9a96904ffc1ec4dcf690d1007750a60b7f546 GIT binary patch literal 30195 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%0Ds{Z*l7m{&lHIgOzaHm!h^*?WNlD9_+9 zBcY)TV^oWSJF1-6-FyH$<=meMeyw{Tz5oi;3ed+?Y>FNbw{JCkzpIpnw2fz|fg+PM zq9ez~>nKXmOpGbKW%V=I?vS$E1&s9xEVm3!eKfGIho1h4GIJ*b=@W23`HXl6oXL~) z0%hNOXa2d`sn%5HK^DQinrktRrmRcpWl8e2F!*@~7MQ;XP+i3qtQf3lr-;PXq>zX^ z_^*x>v@$*js~~(b6YQ#M^nItpp`B^__+)0x6=f!0_lc*8wsQke z001gf4$diZxER)Vr(`=~Cc?^g)Uc6h%zBVIZacm75A)1Ze-?w3!Fq)Tk(?tQ&a z1cdPu3Y{s%)#RO-`aHV9beYanC%6~1(PDz5n{yokcGKDjoEiXOv;x>rLx@?XR;Qj> z%w8D$#?-StR@Nf6L22>PNAblAe1*Lfg7eeyexBQIIMwD}VE?Y<4w^gUzE)-kxD$0R z%FLR+Cqc3ln~Z74u+pnrWu7Ya`gb?DNS1IDj%nY;IWJ)vQsaexbR zHS#ocrpex!t}Rmu)@^)lrp3(cVY3;*sD%k?0G?5`0*+w^Nk#%Fu8eZ%jS&mHRwRKG zd4WAviX={RIG*E|NU!EJXNw@dk3ut7BLDsIl#ivi<3c;q*UAjtZPH*?X0ED{sktc^ zn_hBl^*mpLP;g!BGE4tJM-#P4Z<7&n2kn#5oz<=)MGy_AP&W#YE_e+-f|Mr3iN2GE z*!Nh>V%N~Uzd&=g2;v;~@C07K`kw_o(p@_FvOxiSfEJbJxhq3>E4= zc_YIRfSFg!8TZnS&iCIh6=q{1S8c1a6Xa*6gKm1Rkm!u`sE(E)VGjkcFbP-VTYqp6 zXysrTK9c94T(l%6a*Ww5wwp;Z%eDR%yx+dr18{AxO86@1vGw+HT~lW64frP)P?X3( zAFUn(l@ZusqBC7LBr8FSj~(DXuf5LPdrvF0iD%%6zItcBW zWG^806ciy6L?BupoMP)+uYEjiSMg`-&(H63nE(0IrMt9pe81kltSy1QQfBT}WDh4v zE0AK65MmIDp|#dV_3Zy8-my*GBTHV~rv8~H_)+wBEcEs@tGTAk+*OOr%1lursrgVN zhw~FXPHo!84Y{_O6MOMQ&PmOl@ZlUdH`7c!f0*bDv7kCeK$^W40wphS)d)>whnagw z4@!{N-U_ScU3)D`SQ@F-ZCHRt zB}&7Jz@v5($Z8S~C*VjnvV_>YaZU!qW%}E61dzz6N6A4f)K>=OziggL^ zZx#>=9HOn{u%Q}Yu7ay=?#e|K^SPpD5A zpSU^(1#s+0dq6QDoS^?YBzB`%Yl~r^!tC6l9h9th5DUTMfZ`qsX=W|o!w3aEs zwW5izC_+g0fspCDja}6<=~oA<5mbOs^Ttr*6trUH6Wp)LGixb+pVrOsPPbQ_Rt)BP z=k^2X?VrzSU!SG772uyh2P8FS?gKtxjG;|j#u*rc0mh{nOT($Qx(70ODSOk8l_sPW z&-=KRDZ$h!0MB(w;O#`;!9D0GfW(>v%x}qR&?ts*`$nu_B5BX683&6^?wRT{@o|;? zw~Bk={Q{S{I!x#>^!97BP1nfBz5VU$$a7}UaK1UDPo^^{bmnx#!3plI!Ax*3BKyKW zaC)1WHk~w@>fizWT7d;-=mCDM;Vr^Z0}^Ud#QD6kL4hQ+imad!cxDxp&v-vk_RsNN zZ;SUk5t@vNwGI9f;^_hO_6s1MgL%znaDTnM#1kg=g2TMpl>|hiH1HTrt`~#By@^`z(xq^ zH=}GGEjB0UUu603!8_l|bWv__O@XGz(c1y~@>>4XH;Jdr+Os0V6Mc6f{|FG;P|O4= z!?$%iSqWO457#I?PD@jynUnj{uH7kuQym~o6ZVJk-tAriQl{dl;R6LB95q;lE@~Ev zf=K)xqK$d9*nTaxuaI8Wjp9xT{&JI3xi9e$dOH^LWUgzHt26YsQD#o8oj#~L&(!x{ zF46Y}&P`)DUQ7}rhmpSL#9sEMC5~$|daca|eh{%4ATxN-Kge zv!HrqkaC>_^87BOSifs;vmBX7%AewWkBwr!W93^3z#8p~_~8=d0_WElOu5fX`Fn$S zLc>{^39eLF&*=MMQs09+m6}4AtTWRQ2W7l9su}3gqcgmh=>(a?J79n4LH4ZzD^!C3 z_N^XKjb9PurG^zim`UK0wWjKnCJ9HY70ba|>r*pdhVmNq3nsHU-a&k~u^bC3vqBC1 zXt0klBVqJM7YG|hQD!tII-^%+F>aR!t`5~`of(_?Ql2hDH`eKWUkXq2PQF}jRm6}s zb*}CY9jk&D_+rbTyIBgZ4woa~k@R)||BlIQS7t&+^#Op(cwbeUfZ($FKA<6E zTGx(Vf|tV8SADB>_79ZdGu2F)OkX=C0FQIUj6yOxl+olt+B)sd` zHHyWHsFA%VK2sGy&+_~Cub;l-9$E%7jpIe4+1X zhxw6B)b85du6_AEsxyXwOyXz00@O<{d?xXfR&*1`f7U?%3*-e=BQE9opa`7`fa;tU zLWn@`O|3}#rj8@t>n4(jk1E*-1eakw+XiZ2iT5JXZyC2!_|LOD>&MaC zr=U--65De36nwGTR0c{Hk0PoBGT3DvrjZ+{Sg{@M{K zLY>T!N3a&`n{@Q>KrDdLfcQG}fyA_t;SaTEiuyfHc-P1nUTjM*<@fw(+qfO@83mWK z`;V0%3(i-FzB;G9AbxvgCPfG+oaU_0W42u-1e4Ww)3&?zWdwXz%rS(S4Gb`6FLo;u zPZ^!B7SP8XL7}SE)b~Nwqn=v08|WUKdY-t}5+FmuX6KHMS4B(KB{s>_6)tx>3a#go~W!x)<`h0AJvacT7dq z)hG_v0BO5g21gpA7iZjPj{NnzJqhj^?xm4$HcKxn@x@m5F*wys+tmp47HQ55sRJN{ zrq@9KR>5n%J6Z(gY8F5u=|1RRL$s_yYqgCs?N|3}a96v_kG==*ASS*Q0iHEs%0R2^ z&YJbloZr4Q!F=t9{I;0EoldD82U<)PBLHwm2P#$q(-~vBw*3e2X66AdgHc!hfx_-* z^;Sv{$Fl)M!`L36XHIwz!hk&jV)gEg5hP4_e}@&V-&$|A((l$<->YYh8MtSDf~(1X z`?%}YZwmc0OQ|!xeTC@j{n_6G`Wf8IL;@O@180dQoNrfMKyU~y(Rbs`|QSDn&( z>C;{mTJsN~r1ymS(#jWkI+PEJ$@ChaSAc}VPH1w)_rkSeW-&W2fV5!6{C3dR$Dq9T z;$O>tb*9fOn9TR%9k`VZFCn6t^$(*le^Ym^+lk{q5Ppa1w&gauS-u1kNb>$qw<}ph z7z4@do)bKs-3SA7=Fc}erBbOypvO)--N{1!8thBl(axF3;=Jecd|$gwQNEWeCP}2mPN~Yj=*oZ*FqG=#6)4KlLdo$Wlw(i-JMNMY^NN_q<%q zNnn_{%TnL>=A3=Zj*LscFZ_5{mk*YQJev6r4w2NC9$=w5A`aC8B)VoHXw@a5GX!SH zU_<~Fc?X}^iXE-;O4Ono$9>+*N;QA^m+F731QhA6w`M_t@Q7*Lv{QknX?LKkQqj_~ z4M$g&tL1FdVB$}|@25A1Y{C@MzO2V}UM5ffWzp*Lrjkm$yTm(3-Z`#K6^NBX@@j%7 zsHtTEom#{}QEJBVG3N;sW5xTuhYWv%->d(>!rKI4OqrDr^H|^fX033i4*=~P ze$UI)t29BEVULk9)0@4CZshc~pC|USh)*~#t;cNDWI1Di#Cw_LcddZZc_y!@aSCvf zc&C~am{bS6a8*kHLf?`=s}>w0@1)qP!`z+V<>$PYhu^IKMN^sGHR~+_=J zMKe)am0Hv+a1agn#JdKB(aD*2MI@}XhX_%8Agu;vSNWNu+`pOTf4TnOf>oz_2>TQA z?fG~9_3eJ@6KaJ!TFP_0ZcBn@ZO=@gmZI@K#I9of+uPnPs9xs>vI&z-8p_sWUeuPe zeEbQJ;;ONp2q{wFs~soai8$Tw!9WNg(X2h$kvQ?r??!1Q`SPY+S)48&GW<{H9l(F1 z9mu$|-h`9^t#4FY5q|%ky1;_Z!|xYiU~20jwc!}{|MEUxO|}r}#d<6z z3@$IOsfLT2hAX4oys4xW?W%EffC4z!U8PeTm^6*Nn?p7eNGx?;YoYE$teB5RSo|VC zb4ENqY>syT|A~0cle^x4`*?L(!9&k|oh10xx`{g-iak@7s&u$suBK*s)6hosKE+D*xS0&D$V+gk?U40=9~EfTIoo* zeP^v$e;VO2DjLR*5ic9CPpdzb$gER6V4Z*4l3AqOZ#j-n^xI3VaX;HL4!{Q@<7L~a zz2v=XQ90_H*0h7!@B7y`v&g(J^8;Ub8Dz4^El#%P1_j*>>)r$|KDiDPQSVxsqWS(W@2**$$A&p0wOX`ZgyM^;=>#+Hlz1Njr^w-J zem@1kYr{OwIkHh>`1G*Sy@t+uuiD^c{Fir+JBZ(!=6Apbc+d4c?i=&l^Us6618e@D zQMYj~X|eL6?aE<~$U7w?(ojpT$Al>0hyHb6Wy5>DXw8e#U3HxTKBwMYRy85<-Z5BE zLu}%m6YpNdzghrqHSq}c0*FQPsbN*uE3dr|K1c|e_qF+W>)$|G%2xO*YHNObtW`ej z&VK3>>mKg8yAoY=1#VsD9kIH6*rP%Vm!Nn3H1u!%Vrg1k-lz>Ojdd4yw2adEok}l`i&lEn63iTaA53M;H1+$p!68+Hudo(f@3gK} z%?w%gYFgpMJ7A@%J4JvwMZ|sGkpR1s23Sqtku(Qz5Hu$S2iGghO1dCw#d~3U$@^N( z{{{7c_22Z{L4<3ueoga6I8SvS_i}Evb*29dwRye=zS1+MLr=ZwO+UolCUcRUSy(aG zJFR8@r!@Z;Rl|yM;N6Z@!@@xS0>HNevk;OG$)^D<%vwQrLc>Xe#Py0P_%3fZCEnL; zKYp*l_G=ST28(=qF2c9_sripQp&sClk77sO>imw`o-r+4S0&oh9c6EC!`c2L;41W< zg-#aftJFK0j6EgZ6XD}-pv1e1Plo{{gk)E;iVq&)s&Wc5}ybVSj*onc8tE_WLR=M(MmqJ=MnS=f*Qb#-$#jO?Mm#+2#tIbKlu5Qla+C}?p<%VJdu6fD?& zfc;-1;2+@rtbBW6_;KbP8`bW}NrJLwb=USg9T}B_>Cl>CGE;8EG4l$h+APC!}?K(MHK1=w&fUTY5hLD;J9 z=-FE@s_=dr>gKQGoi`AZ!2Cx|p z7zU0-=caij^qzUA^OTzP{k4iGs&-lcKFqw=vtl0-@1GSQfoc|Lk`|<7zWak!UwPk= z+FN0-+N0QDCG%dF`TY^^f5n3J`MA?%_HpIRU>jXF*7X?oODR**!0CTF%%2}}V=>p) zlWC`6-%s%l`GwJ!lLd=7e5Pqgzjq5&(_lWbtp$Xc_Yiq!Hi>unBw$piSxCbNu#LPc z0;#^z$|4-K9lLm*&nlk{_yx_k_f(rW{0$4%JAOOG`W?R=SPJ*GsJU}j$CH77jQeF8 zxI6P6$C7^ky2fTtJxwNt35M6V{pA^trAgBO7peF3Nm22XRXjx%?*)u^0iY7^-tA0; zTE7sW1vQD~_(HSLuAlF%tVmh-6SH{zage;>q>!P$i~V}oZC21cIXHk-zJ0;_y>6#P z?LVu&#~lYQ>GxaPO~!y`-VG+2Ol#tz^=%InsB?ZGVvOs2Sf=h~-z6bVow0gGNvU@n9iVB%+o4 z%e&2g^*ybgho%hM6!7#szkThsubmle&W|beJ?@M2J6+iCZhkYuM)9e2uCIDCw8PX- z=`7!c^LRFC41lYASW-1b#h<^C-JEd*s$Phb14+uKLrw&|TR4imiy~B6;TsaINi=z3 zC;=;?z;@)|)#*jB7U_3}Eem*hy5Amakq^86C$KrrQ~eBgxU&OErTI)b@j;3A&cRWg zl49*(Qdn#%`>BO@HxB@D$nqY%S~nmXa6cmR2CV5Nf{ zSzC_}#iVrnPv%5{!XuIXw+Q$r<4&u5JKa??`OVG9_aEV&=*GvH_XFifflIIHYkr?- z=$pyx^DSj>!)55bMyi~bS*ZAC;l=08*qYO@V-a9?Pz>-VrFd`+j=aArP0*@#JbF~g zi1eQgNO?G=Bjf$ilM)I-ip5HJQB-8gQnD|G`eN8#god8xx2K{7?JJ%M8_Bk>>xa0n zu5RKy$Lp^+K~HF@YTYmm?U0i1Gw;CJX`hFy)O$$|6x(v?URFD21!&qA21pSx6whl| z^h)A;gCQ1B8!W(|J)k_Q_rMT4^?|*xC=TL-k1dy$GUaa+H1u@8y}Z1$R(*PRyqoo7 z+{>XR&heRYy2+)_UkR;2Ynr}pqw~H`^Sddb_j$+~{c0yQ^M3xuJXE=Tsv%a9cSX7L z21GZh?+k|b#QSRp5~9uupie!b;ICd!9Ah+nu-5x<^g$#wk@Vl8U0n`a6g2d#e0!|> zvwQm4tZI+-bKDc}TuyqddGCQ16m`3qrlFtuc(&;^U#)~7c#OSK3H z?=DuYG!Jl@cL(UN`5h_%7{kydlX6f3z|JQ@+JVHPV~OwRxv7D)wNo1M-Yca`PwdR} zay7cU=##Kr0sjQ$zVh4etC@{D?y>#|_hij*-fGJCY|rny9FI)5deAG3fuYGwu{pt1 zmaD~ioZ+IP;?n?H^1cX8vLYB#4B&kPpjFT5&B00%IRvme)UZM+R1=l_^sWe24VCxM zYHAfrkke-r@IONPJXG_r5kd3o?KMCTX#!>dg|x+ zOg{iwvlQMJVr6H(cn8qjGHZqz=q?EuC_#Ll020n`@(Tk{ZC$0D!8(p6g2k;uNFg|^*1%aKh1BCwUjdJ*?miAmsa&hxF_C=es_n`Ue9IT-MJe_ z>n7L7KtVsf&AeAM4<+@!-fLY&40s;U#X&I*kP(1V0O%zE5KS%l5zr@zkG`%TiqM`? zZp?Icgbv4s6=OU$-jZnfh?frEn#0S`T+I3#b7-FCx8Kz=xR;sP+BE+sxZjIMV#1ks zmtjZm+|;DrGt+C*??tl|Q!=kw^V22oL>YU^*i#&YO%y8tzn+qc|EPe`^Hga8y2IS8 zV5r~~(0mF*OQ%^#+jpbYNd9xMfxWjOs26{8ZTfJ!-$ol6W_pg_o{|3Enc1A*p6kzW z&%Cz|W#O8bH($KBiT7cu1{#K;H&Z|KZ*LCBv4Cr*eX)~zJ_mAPPP%!3OM_T5XTnUc zl6E-)u+j|`3sEkp2YnNQ<~e@*lIc}X zNZMNX@kaeA?u&RNl}6YmcPNNYF%C?9TTRqY{S+6gZ*Om<+jShio=PD8pZ3m0y^Y(5 z!b#h>P1ELbW_D)>1hDs|NRtxZ|LH1Vu|!DfVq2mur5-oNl1sb&nxCVCvonLlTWZ!W zjzXVksU(|u@9r0?AUDjs-vY4GlprOphdl$WZUgU}o=mCK@Y+z*c&pZHJabs01ut|2 z{ex!ASl$^kHD2sv?917T4uN{|rM^Ajc&03=bdkCw`A1hGHVU>UJ;od>K8 zAc?ai*=l38=~PpblYJ_qXZPmM?|yp=p1!Ipb9rR?%`67&&54YCdfy~^WDib zJ=20rF%6}0)3)#DQF=FoR6lT`;!k$1g`1b7tRYV7CRr(?P~e?wl#K$+LI89u3$S>U zMgj`^7TgLIWhVf2JG#UH$_#FMPyBF`c&A89KFTBWo=@bXg#D_X7t}aS^L`!v z8dXMVgsQR|=ha@%J2P(^_%Fa6Wd6KgZB5>@)&_)`_bD7w*7ojZ*iL=FjlAd41P;K7(~jKd zcP?v|sU7vapcPw2>QRzfFz#kYre6Wtps1{RfQ2lq@?e@V{uw|OtKAqrRP2PkSUK!t zlT-D%pnqEh|MmU$1n^U8CdM0w{mXDqyfeaYX}?;Z>KTJLgrhdWi`))TzxTB4Ow&B2 zlL3-M=jP{IClUnBDZ@!vUA&uLepB8l#Mk!QGu4-JCf|Rfr7|hL4ENm5ms^|MlHc0`h`iT5 zwLPX#A?aK{rE;;vdy?qcX}@UJ&h6YsrO)Zl*AP?AyqD0?0>hqQF$Uf{p`s%3v00 zwcg)uMSUlYbisr7=PCS5xu03^-*CrDUn6q*PI0Ma-a&o)X}kb;Q0i8ldC!MyQ&BIx z*VJP$2*m{Tv`i;B^8SEJlS?K~3L;UTx-}&c0NDnzV_NPMC@K{IENp{fFP$Z26uo!= zdIykpRJIZ%{N9t-hP&OyYqxZLboDvth*7OBUw%^sPgjgfzx@d{^Y-i8PvZr+pX(WF zkGx~yeS!;{RqFd;irpTmo38@SXA>lCekN<``7^mxxCL;mHIO@EK)5W(3t?4y0YJA+ z3$XN#p$%#?DgoV`<*9Ni1YS3he!uTn#fu!)_aW_>pn2-$H?$<_%8^Ka_I#x`FI~># zCAgpLR~c~Tf_JJzu~j*6BDwYPY!eC)oA(n<^7Zr^R6=Ix7 zl|=MKVn^owYX)68PTchik~8J+puYVyUWR+FpUJ1MlEI%(8+Myw2)tKAAL1sc_m4xW zm&s?>T=I@n-t#EQ#nEZ!mw{Zc431%yin1LQ!Ix~}&2ZhQ9YDft-JttZsUu*=e{N$X5h#nM&up3n*gZARFg1J?uCHa zeJ7E=z^KecFT~8!*NrNn+cQ`^Ho{O(V!W!Xr9UJ35e1W#dtSd%&@}^jvc@yc%sZ%W zKaCgTp8A^%=HGZe%7)1B%znV$t;|$}r%f@#Z*QhJU93W$sJ9ds9qB^1 zM<4z7TrYD{_MY9zh4*~+>g?#`??#(Ai#3m+^{ijGC6ExPwMqc(I{?tTSXJgxwyG8+ z8$+aQ`rXK0o4V_~6}6H^!QVWgV4mgw`axF=fbf)-$uj0WIy5iF9ke`Fg=-hy9bhJ#Ru^0kqod1z$!!8s3)`VZ-FY6G8 z$orX~dBmFe>I$B&6i?PV=E$_anKPF@EnWrpd|X)`6dbiooq2aKhK!qfGR~OEOp*79 z^2~4^d!3|8E{LpwQ{I^pZk*_=SDQpS0igA^07$GUXREQAgh6(k51#i$2~_}Qe%+QV zLQt`+V#oFFu#UvveGcIHVfn8Qk|OJz3nYhFKr`G7eLGBME-2_J$(iEeZR?Ux zk6(&BTrcxp6>%-fC|occMgXne5`a-%1vJ5tDZI7}+9_Eg-Bp%tAiPlq%WYqB`?giiSOF1K@## zUZwS1(SHq3l5$+fZ-3sIdE@hB9*)<%RdeD4?Ep65C7x|!hBxA1B` zjicZ0)T)lnzSCgQqy&GN(7$DZzZUGDs%GA!jsftRxJSZ^Q~;lRnZ=YOGq;(Vp)zjh zhhZ9~pk`uzUwC(MIkjnkWUVjow9AL<^kF6}b7&%xA^|loYyr3TAch`lpl!4*flhe7 zjpSRB?)w6bDCka2G3xlS_Eii$X^px|C12S=ey^kn?XuZ80<9_qqecm+_j8)>D?kNshc$y`KRFS;Uq9Z8&cJ&Bncqj( zRa)~G;W|NdCBOZ7XXc$%4V=U);||(5z|I9@iFMQFe^5}nt?DpVteSe)PuqUG-S*Q- zi{2^kINCL_GA#FN7ja#5P0sTxkZ2%~=QAZGU=J%q43gc7Ea`~Sc^v`jBwFu>Z2=M= zWWNVkrqYUnW!H=NWtt=|y!X65rev;^;9nc|5TEGGyidP9#Vg|uv`Myu4IR5!={S+2 zE@)fRcIdZ*3Eg~K({HDb{Yi^nI+X8%_hne{f>ezdE0=hu8i+))m-y{a4R4#M(P^*D zfIkdmLCUMCCG~(cVgW1rHrO~eeB1+m-xsVF{gw`}lVBZDGyOFC&l)?L*qfv>v zooPqgsP2=Zsm}N=GS_Eo`rzsc9u2)#oF?s0a%SFHh5JdoKJK*Pl-en2nRu~GO|2_X zPc%)HBWGy3>5Vblk2guFl;;i%IIj3}GYHDF>d7{(F6nt)5b<5Kfu0dA>5FhxkLGn*pM#!t zX5QBXrOUVm?jTbyb&-MmHcu#s{}h4u8fK~{B13&YxoNoP{lsX`)djhVjE=n5N8Zz? zY3T|%&S8q%)1s`ICHz;`q5xLCSOCy917Nv}*n2Y+tezQn!j?(9X~Wu(_nqZV8y2yR z=OfPaTVMPx7YSD+G z9HtEw1rEr(=RS`jA8~Wh*hER!!lk5Za;;FwCODf&{s=A(mw|G3U=dJ6-jaQZM zul^(zcuvc_o8cOd$5n7I08Vvc3;8vQ;~4llqB?9TR7P&=-VA-5ml``*k$HCuFpEOT zm0{rAu)RvWC#-nkKIVBV#sKibg#kt-xRy26kafZU>^jmv%Cw3fLsh8|z%l|PLT)P> zF3eUsE3*wR7AP*1`onx*$&`H69&GvqXD0Lhu93e2?gXU4@0%m2`8m1il{{WvjN6E=u^~S>;|m z^2W>KmHhVenZD1fnfF-;nc_OQ7Xb3~_td-Xj)$@m8Cn%6D$`Fl(-69~!^EY?dry>j zKbfjG^OT)N(2@5#t>C2RsXpUg4+MZzrXnn(y?PHk4+qL~`hzD69J5(ujRrxnC-q)hkQ*SG8mapXST}@00Ny*URp+6H{ymGx?OC zvJ#AOfp=%7n|^TpU~XbPL97`2bDsy!crWvzAB&DBN^}t~+%N5aHgO*}p#ZOURahhn zbt}HDRtO23szDW&qIhq?x*1GJ<1oD_Q`5x6K9ZNcY1ZnqgwF!z8Rh=!g=4Saw`YP0 z&pI=i{dbN0Rd7%LLhE$oaHB9X{8!E~=7>~e4xFxXcCJR%V#kgmmODOhrq;W(fJc-h3R) zwr+1~=Ui_h@BzuQf*I83IzAmlnFi6!X_nIpn^xk4mZiPMRrVCtAZ+5o0ZLs5M}{Tp zlbv)7upB(V+HHoq5n-^1hZo^i#Haiof&ZMu{)&6n*RmkfuVs)8BTIKr5I<4SkrFo4# ztUj#KVGMcx5N*%3hQE(AI5LR$!bz+iQS;2d4;7lV0=yRr#wAS$VK160C54MeESW6f zanAY6fq!{sN6t!*J2QU`w>`&|anE~IGEvY_np0o`?}Wmk-S+iV(`1~f;}Du{-!A~q z>*;iCw?O66TF|j$n-Td3FVls2F)A5u*D>Ob)FL`D@mtu*W)?O+IGOQY4Ul{ z3kvVh=GKC|+Nu{zje4)zg~9?}U2d2lqeoUN02| z$Q#ynPW0_WAOiJ0nVO8NCo*l|ecC$Uly}O9I@Ko)+fmn~6&%+pxAdV-D>I5oMod-pMPlukPZ}#L_s2cR#Q6(>f2rF}cv8(ElmA!n+n4wO z*AAi$C6~r6)3M1VS8{4&0lC?c>nR*5Z`{^w1MgeHa(>M@@03=wN0Mk+Ij)KKSa`s3 zjohPJHR3teMmB->`XCh6Mi`dR$hKe$FTCno3c$CMQ4jVkBiMWOWPGqBRkpq8=-1lG zTuRfNbAGv1&A`8cN%PWE-%ox$?#%oJ%*Pzp!@bCt1Y-fZV^A&*HmO{!pQ7pFKDKUa z+;+Ixx|^Y&Qps2vt2Ybt+_0V2-06|~T;1~hn89CFxp&)!wIp5pu(oqo-*8Y4>nLP7 z&Yzj_Z--c9!`zpw4YfovvM1KYTT*R2cemn471ebr9or1gaDJ)fUy$Knm z^w)UA6yk@UfBYTSjpKO-EoiG zM;<8Irgb$ebIFL}ntE7~6F#XTNa(pdte8Zi(z=zjLG9YG=$#>;(Z-Yot181qkCIfR zMk7Krijo(xx>k+A@1{k-Ji_@a0{#6-+%o1hY6Mx&H1`Q?qEfoxX%V9+O(E!TI-Y9 zVcr%x`z5w_y9|HNnb*3EebUxVAj6Wa$`u9IxL_VEeZY)48A&(1AB?VN~#<@6! zX6sx(xa~CEOr~FIf)mH-@ZfXa^HG#V!in-ggS3|E4<2{2g(VdV>)g#+)gl}|u$dFR z+Y5&^mPUePy{!OVD;K2`;czVs67e(~Vs;-{q=^~+Uo z3-9%kX@_)CI!dbrROy~`X7NG!@F)yaeG@Z0H8bh{cHe}hlU)I7RBcr@stu?+>^*F! zW4jUcwv$oUOKCwv2$9PlvtX}qcB}f*4F4s5dyKR`>&(1|^HTr#@Z-;a`{lRD_%$M` zouKod-{I2vCEpRK-5`xCXqN`ox*t$)hkzxSZP9LBA5JYZz1eQJp+++0?OY*tH%{&p4Vz30LiK+RVoLDl?JPc(FE`(o+W+jyfy%vem??iSro8rwHc;p zQd)DfAK7!GcN;ru*Nh_FV$&!Az>}QkRR4t<{w01peM-$th_~ps|Nh~ppa1^LZ@>QI z-%l}q1@hw#_c3pWE-yEAnx&Tp6tqk6SPzj=5vI zD3Dt{=u+6U$3(yEU=8Ld!v(9le(u$yfdMZbZ4DZgVEcl#0kzfCDN_rQj@g3sZo45G zb!>*AQwceK?a7KT%i1?<(G2{h0h2F~GyE61G%r&!=eavm{w5EPoYVL$Rla>>xs%a< zfcKoy!6w?0NySe+q25xI8yf>NmA#>2GL(dEN{m0^imEtavsBpvrctz&dhUl&(?lDV*Y`9-wi*XMlCxmX#GDkj~WwOrx+> zZA4H*MI)|Eiir=+1C8!ZzoE>K#F?aqEf`1 zj;9b)-PiMrvWDrYjwfx$Ib(g`-7PKHR3#izMdYcFXXH}Ii$uQ=)h5Qs#D&*V$5pz( zIlO3J&8sPkKypV#Nj_kWvR{WKb&Qax3$FY~fS2gW2jDHM`V-*e^0WuJ`fN$_rG9&6 z{3&N9z4sMi&xl8*@|F>QRPS7%PX@;+W2spiwIL!?&w1Yw+HFgH@21ea-QR5cdp$E1 ztJ8Fy4fcu_qY-pGh?|ejO;Y~3sgKN=g)@qwxUP3K0BR)K=QOU{kZW0l?imam2N)Y^ z2%vdkk-mZ#<#1`Eq_HB6<^~WTr|et@ndz<;y35mh&&TK5?dOy~T>(tEeq^C?pT*xP z;!mL;1y9iWrbTj2!c`D3FtMh9;0n~+p8BnGrtZyjZ@-6FIy@+ET+>?BCzS@dhqVNd zYu4N#L_L|qt#Tte zj{ChxDlHHTJf~ldz?aBxJsnS4!&{@t>j=f7?RkRkeQH=6?8N7Bn^B zwuExq(oh5at{px)7dEX!@Ml7XuT!T7&JFfe7BYhvBAJi{Z zeyhTB@q%6IqiW`Qu;(QHHnyAJBy!ph=H`b9MZa;*1@`-)@8cAjK6GtQ;h9qjoK}b( zh5Wqcih;$kN#Lg)Y?>0EyZZRp&Pultbh2JFtS!$5yk$AmvlDqc6!0`^>^JPS zv8pOj(>yI(ip#f9J)>zpa|9$PUtdsv*|qmYz|*}c{ym3(xykeEfB!SXA9)Xxg7a)t zJ5xhi-RjTcs>qkvl@ zLIBEMW?OM{h_At^ep2>ZH*aRC>_wHyHce-3<5j!e?shGW#7C`3#8(fimP_FC)fe%e zGxg=KO#PFa)XaBq!-J9X9q>01DfRynbAK}Vb7@!-HtB%ABqfrXUM?2!S7|J8xguT9 zoqt|ZVZ27*i~b;~GCsccDse`ES8a!$y^gkFa~t??WWAm4*2;~H^P~>pr-4TR{!-k0 z3GNTIo1Rmj*E4SwirMdF+(@n+`>P$SB*(^W+YRYiUj4^%_TstmMo(hSH9 zgQ};N;SQn=fyVvX0;JMVSvBGbygry(*Xm`xKP;N2`ZU2_JuTv&!TrIYKYsu5JKg_p z@ux4q@(rj~Xj5S^wKR&q2aqkPGL^24c1tms=+6)vhd{oq%ZgPy4}^5?5mC4EF19Tz zT}#OQ(s>ol+g4#Z(=V5~{_?%mC*ux)X0|^pZ2uPE{!aJz_|rEaeFfqVfuDZ7{}K$& zf*SEIa89GJGX%s(s8bQ%h+hiwv;1)?o}&Fe7Z}Kzb>jLv*x%#&@vrbz z2;YV9W%%ts;ip3QLd37cef)SIAMWGu;rBoOkabh_J5gp8ZT3mi{L%mZ$M5&?;hy3U yKi!jjkMcdt_cZ_VpTP5fe+@(jq`x!$()b^J0VA)ZB8f5p0000x(l literal 0 HcmV?d00001 diff --git a/static/image/person1.png b/static/image/person1.png new file mode 100644 index 0000000000000000000000000000000000000000..ecb9ac80d4a6053cac1c270f931f204f9222aa84 GIT binary patch literal 572 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-s`2jv5u0Wch;Xgy&e};M(0&*ej z+W#Oa2ph{xGSy|>zI8*Ws_FfcGic)B=-cpSfb^>|;i zfk4B}^a^5RZ*3NHwWi2ZnMCvB(ii=w+tKV_+bMNHy2O3U1yth>|?Z`q$nYf+}GyR@P z_;cSr9%1Fzap>lh8TQOPXRn@T4|sgL=%2wlCnue13;QL1qzf_+{F4cgjn4Nu{OoV83&ZJCC(iuaw1_X3!DI7&H=&55Tjq03;fiKhDYBSRKJTbXf-I{J zhqJgsSIZ*#UWtY}lUMVKIS*J~x8&?8h*xYpbt#JJOVsc5PduCq&X?yi)$qR26{wx3kaPM-t%W#$8Me1UXAiwncdD#n{ronacH+?{-kdV zNxy;^Z%nQ^JZ0t#CQaMc=DI$^h3sYwDv>G;y<8@$rCiK6E1pH_&f%!AVDNil!L(NH z=ekGNnNFPC$k?KFKiY`%+zrLEO*i&CbC*1^m@!4Gp7-pMHja!C-haWT8e3$_W3OH< zKd*M->b&^bYxkDN7W5vvyQt;CT<(gG0qR$r7B|1J;IVPhJUJ(Rr`hM?M5{o*Xxoz^ zn_V>pME*qEnlfdIe0s0bxcG{oe)3!PO>g{|rr(*8oEdV!_`>G}i}M%w;Jx9{cppxqFueMcI6rkQ^cOU@+iA7 z$@Y7-EB6zN?r-PogdT8kmt{?Q?ZNG|!Cuc}TK6}P{OcF)OV0lJU+m&`M}akVtd7-{ d51#(7W$;q0X}x#Ba0e)1dAja literal 0 HcmV?d00001 diff --git a/static/image/person3.png b/static/image/person3.png new file mode 100644 index 0000000000000000000000000000000000000000..926aaeab9d02d9b7c95b2cc9fef2ad627995725c GIT binary patch literal 557 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sQ2{<7u0Wch;Xeq~!%#Jh0TBU8 zRsLtFLQ(@!jI0H&5=qdxnLik4xNJ#~Uob;V#j6j60%>2*)j0BS1Yc{=QJ&{v{p(J9 z(gc&`xk?+pGB7Zvdb&7Bl3l`?gj$TBol2eJ!D^LZZ#A z@R;YEhFeh( xyGin1YvgMq&)Xl}YJaQYZfVO$m;4*~AJ}u$BCa3MnzPx)I7vi7RA@u(nrnzvRTRg6YerM(Lkj6Q5k0jRQIr#zAz4{rWKA0MfIu@cDv;8i zI&=2E<5(7@85TFcc#PD)zdUz%hWx(>xY|@+R1^DOB+kGI|_FI?8+QJ-z!M0i)wF z@?pgQfqsCph@7W&kiA;U$!(u<~O$AmsrBItEw+oP=;?rU1@s z<$GWOIa!((B0WH}8ie4ea5VsWynYocx2J(f2N38w;D$be)dg^-=3`|}DTvYlfxZAd z5D}_AfJ*{rU}RYmL^43L&O}%glh0_FQdimbskFGblF3mNwmlgA4EJrpq~Plcn0l9xEUiGy-%gTxlo`N0AI#LdpSn# zP7e_1jTBT}!FY*Kt_c6u#k)fYH}crg&c5R*cL|Tp20>C_+p{ zS?RH{3M+S%1_-nP*y<73%0aGRq5M--04E-(1DNWua~)RR>wP^Mfk2-F9`wAp$y29$ zK&26II?Xx}VZFzPc5>1f58(2g{p>-h3k}|emC=b$K1+aN6m|n6J=3@jBYV5A_l-b{ zj-r!Yo4#9%EAG|T6H0IOG%XG3Jr5k@dyeoyB;kVRRgm^g0n zOry!y><2KKLum>P`T;AaXXRH}I)S25?)@b%VTsl$}(9*MoR~4p7 zM^nRR9vj=Sa$)c5(QMS{T$C2i;AL2uQB}vg#RGM9p?f^G=3%AJM(YE(m^_;i2K_Hl zh3No0>ctZB211P@C_n|C_ada!fwV8eIYSnr=a0m7?y!M3q zG4i7CUUFe8(AR*Y+jbuT!JQB8#mE~KMZ@Y8^0*8jE@fYWm1t$K%V?U?;?IR@bbMRE z0G_5vzAX!+MbDaS6MV0zAGSo7LX8EL4-*f;) zh~X%0z{FCb72e;@02*l$_pzg7OAp|rie;DQ3q>dOY;+~fC3FxD18p47EFPA>(@K>G z(5>o{zJHm97OH1%dQ{Tflxw4wl{ASvLYCF~2heRI(388CS@&NlSCwU1abJDjMQF#$ zPi2km)wwc&-c}uq;L3h(**m51)52eu0=qAd#b2Hs)UdYH>XH`dKQ!n4K$bIBHvj+t M07*qoM6N<$f*RC{MgRZ+ literal 0 HcmV?d00001 diff --git a/static/image/phone.png b/static/image/phone.png new file mode 100644 index 0000000000000000000000000000000000000000..e42584156aa608dd913d36e58922abed107acfd7 GIT binary patch literal 313 zcmeAS@N?(olHy`uVBq!ia0vp^azL!Z!3-o_V}6(cDUSf35LY10Q1_pq0gUSZL)kzE zPy{FrL=ZtBqZW)HB5*+NsQul#-}kq0iZwJ!$Te&~{p+>Uk~PcP zws8x&$!af}yURkrB`(La#!jNM*=W5`w4S#=;sW4X-7vRRK5 zvYyCgJXXlKFPHU1q2NA{4HW;b<2?_kj=LntFPNdh{y>7k0)>2m2~le%DglL$db&7< zNL=;}IL+1Uz;kAu$ilcDC;h!T3%9h!>1=}dbqjS<*jFT)I*f+?1D`PP@v#s>?0$-=-JOY^RtZ=A8h`o!5En{Oz7yL`odM^Jc! U)h(@ZpobVdUHx3vIVCg!0EAEaloaenUvZ@vZv0cY!GrhotU{tt{@5hx)1_|SF*U+)(N70%OCa~Cg}wfp|& zPy3SOZ@T*KX6R0hWm&I%cbUxBOHU&B+U2}_CJ^a7EZT4Y0(0$~#s9{A4tGyBDbO-O{8$n+7boFyt=akR{0QFRJ AzyJUM literal 0 HcmV?d00001 diff --git a/static/image/tab1-1.png b/static/image/tab1-1.png new file mode 100644 index 0000000000000000000000000000000000000000..15a11f79b4774157d3f745b8e9f6527abbd75138 GIT binary patch literal 604 zcmeAS@N?(olHy`uVBq!ia0vp^W+2SL3?z5Yp7kC`wFLNtxB_X0`u_|KU<719P#u`t z2;)KofodQs;mVL1O-PD?+94`|T3W$I0ZF(BoB=Vg{(o^bQxDJ?+9g4L!3-?R^sYVs zU}&uQ_m}XL1#9HLUOv3HxvND*;=%p9PXJ37Hdd~Oy{hn&7+bjZno^AU7)YGnCLimFE{YML@Y?67@ z`YPxNLuFy)lUsGn`%7zgCxrVy6nvYU9~!)H=7O!uv!%KGFHW6)I*i|R=NWfHgQR@f zzR8}xdYv18$8d@kt7Tl;C31cDv)|YBR1Z$_+2Q+k3QP9RTahA(ht9Dm*IW5XSR}Wc zzv_7Kc1X%9Q^x)&KW&9y9nMJFu=Yb@QnmqS+{ynpujSO-SY{ZptY*fk34-z=M`Kj< zuO7H)V^^lXe0j*eJr7n)eA%@;U3|$p&x!t%4=pPA!D=<}ll8Ikd0ZE2U4Q6$U+=Hi zi#_yWMZ0qBfmN&J;#RZj@P0M$5jPNek?3G|=A6^n9wYP3vDVu!9X%zz>574MGVdnQ zkg_ng6SuyfJmy!O!vB7?AJc)K3)I_<8BVObmHed0u{MPva|wGO*MYv$hKuUu_68F3 U_lT`yiUK7QPgg&ebxsLQ0LEDn4FCWD literal 0 HcmV?d00001 diff --git a/static/image/tab1.png b/static/image/tab1.png new file mode 100644 index 0000000000000000000000000000000000000000..8fe1a19f292ae3a982136de6b39d11a1cdb79cf6 GIT binary patch literal 645 zcmeAS@N?(olHy`uVBq!ia0vp^W+2SL3?z5Yp7kC`bp`l@xB}@NJ9q5dwG)bf^zL0C zk)1#cB0*pmh`kF4b_3Oc*boHK0u+X8M;3<*0vUVu?16B10L=!P1|)%|f;EE71e^cl z#QnQK*XWi6`2{ol5n-Ossq;|o=jQ6-JF5J9KfQgjtgqurrqs9Br|V0Tym{`}S`3d3el~LHFi*afP#>!5il3o5FAKA7^|dsrx%J)m?WF+tim;ew7A-(~@q+9jgtfFmI@xvS!AZOHQvu!b)CNXnV$9U|888b zTJP3+Uf(Bg^3uc4KeDDImK1h>lwY^?W#6pDb+ILHENt@Qin+me_A8H@hc z<<^vj#cWzAsTY*i*!q9f!gFS~8(%(|ubcKmC+*MNC$SpoXS1v}PWfrgc)MK4?ftff z%wGMJE!LdzJTsqmMrc-FPpOpvCYW|M8!q?B9>2OS6%_Lbu!zbw*)XTVj$)j$lv%X&Ha(;+<+s z}6kmK)qMOr%Fll^YK5gj~eoI2{Xj> zrsMXedK zHlJnRJiA#+QU2#?M(t@II`3&tuh3|^w>%*B)#c3hPv>xVO$=ePTzh=M{!Hub?#i#Z zyw=uzh}?Z+Rs#R&Id?Zj&EA^6K|WEwL^`VfSz2M#t*~QpF~XnHH@c>6HR=79UBuA3 z#3hnbH|33c*TbwMbN5?HUV3(bnO#DD=PaW;D*d}J-BycLZ<>8h`Xu){uVdcV%^e-K sp1yX=W6_u0jw_dB?Ay5g;dI7-4E>)kXzCVkTMx=5p00i_>zopr082WKZU6uP literal 0 HcmV?d00001 diff --git a/static/image/tab2.png b/static/image/tab2.png new file mode 100644 index 0000000000000000000000000000000000000000..7b4f739d039c3995031a8ff16949cd48eafd8131 GIT binary patch literal 784 zcmeAS@N?(olHy`uVBq!ia0vp^W+2SL3?z5Yp7kC`bp`l@xB}@NJ9j|P&fPnK0Lb3C zYbS^eCU@=L1(F34FfNd>Yu7HI0+1kt1d8kii2%icf>6ak^)PNX3 zlYtB%*afompbFm+plftXg8YIR{{8yOdi_PK)EOT3Hf+qlQ?xaGll7W(l!9Cp9uFuqpUIrV_*vQy@{?BOpyF7CNJXWFMTH!{~|rm^%W z99!&DT+PiI$9Qy#QE95w*T4gU$G8ONe)r#MG;fm4i7kF2Dw+vBKTk+ZnxwL55{sZq zxt-yrq_|ez4G)W+MJ1lN<$LXInp}&8V2{z;8SC3mvrhlCKPIj5`f~2GHcSR`i{n;a z(~Z?Vw_IU{_^R#+mQQxe#MkTYe)PFk&f(;4+uv4-DqGKJF>SZ-5wpC$!S$lO^zxOj zPB3^BOMa)!sTKj!>(v9vQzm|=7wo_pss+^Bl9Jey)V9J*}hk$dIRlv%}s_dlMo{JksSYRT!G8SF`me%)kQUJ@t0==bskm91ufKF$BZ ZJUenzfXQ8hJYZsC@O1TaS?83{1OONXiuV8j literal 0 HcmV?d00001 diff --git a/static/image/tab3-1.png b/static/image/tab3-1.png new file mode 100644 index 0000000000000000000000000000000000000000..80644ff14ef33746aeeb27a5a94df37f004b6966 GIT binary patch literal 680 zcmeAS@N?(olHy`uVBq!ia0vp^W+2SL3?z5Yp7kC`O$+b|aRt&0_5T^_{)5N{Fp10n zvXK!`K`p8XToxz=L1+qqCPR#ckZ|=t23!k}jjC(^v|qtMhZ&Xx`2{olv1VqKesE;% z%2zipZR&N``1$R4-syS%<~&?;nnKx9B5D~J7$>%RQL}-7tDuC=#cJcTrtePv`+vSQ!bh#ESD@<56Pp7s9=_-cTOImO(E0tl z<0dWg3Z+3&r9Wn{9SHJ^%zrNykhVlOiOC?oyHI1HY96c5t$PhWXKh>M=(Jl-N7DDa zvgFzA6MMwk6&A1b@X~&2B6^G?IZnKP-q{b8Q)PB#m)6SF>i4j7I3* z&)*K8Jm9OQ&iQZM&r3{RkF_Tssbz8YT4CyVXrJ8WSWdp{pKV(ilV88=()hRVZ0F+% zd;Uh8mwoXsYQAd5tZgq|?*F2mruu4OsXvP~pPG7k`Hq<7&3digS+_fy7Md#`UMF2H zpM7Tzllupz$s(_^bTl<}B#ypYw_Z4T(xO7%rDtz*XFg12Ea05`$#VUf1fiPBU3Y{z zCj4J_dY#b4Gfi9n@U$Gr>E1SNM%r6R-PK1-HYb`ecV?bQGZ9#tw54}JYhTYZsiawV cwd&{jZ)7-q^)|0aCMd~yy85}Sb4q9e0H^vqKmY&$ literal 0 HcmV?d00001 diff --git a/static/image/tab3.png b/static/image/tab3.png new file mode 100644 index 0000000000000000000000000000000000000000..96461e7d7ac1cb06d5783d6a2ca66ab558046ad9 GIT binary patch literal 627 zcmeAS@N?(olHy`uVBq!ia0vp^W+2SL3?z5Yp7kC`H3s;ExB}@NJ9q5d1;jfb2*?Hk z5PR2-UAuPyxx04lf~o=1Kmb&LigxebjSxXn0MrOH0jL*9Llgkb1TrAT0vSN5(p%Fj zfR4~A3GxeO_}2UR*E^O6lhZ|Ic%Gi!x~zGP(#uOB&PF=74)2>&>ZR6Mlb>SqE?Eaxjv~`L8KuuK#=)c++t6Y*6;NP&U$S+x=UU1^_h)&rO)n$&VX$S4+E@NM<6Or&@%c)<_o#svaC)xG$lFCah?RmSOn$0SG z|6uXQjJhqS&e&FMm=fUSS#sg0{j8?$xdqGQa|+(S>brc`vBFca+%I54()17cZ*mnn z+Iqy>9Z!Ux{h%ojR?%O1?B;{bhxk0EnC}-8j%1y%%KBQoKxH*o%I?gq(Md78;wCin z-VD4KciC*Y*^lQwv(jItnqONU>6hX&J(g*|mY__z;MA$|F>NPAWL`?`vwQ0HX8FXu zHl1^_Z2s?hRONn#)zoB$Zrj?~maC2W*NX8Kzbgx83g4r3$w9DrmTmdkR?FR*ueHhIUN81 literal 0 HcmV?d00001 diff --git a/static/image/trash.png b/static/image/trash.png new file mode 100644 index 0000000000000000000000000000000000000000..e8d109be29db88260446fdf98b9836b31ac7611b GIT binary patch literal 416 zcmeAS@N?(olHy`uVBq!ia0vp^8X(NU3?z3ec*Fy#gaDrqS0KF>4A!h!1Ehf@gaKr) zTel7(1td3Z+O%ueuFab_Lj-{&MCJPR>w#<_fT)MCSFKvLVZ#Q9pySd5FM)Q*mjw9* zGo%N`v=`Z2{CM^4MhgK>)`;JAUJe?^pFG?-Ynp*-+;#Eysz9X|JY5_^EKa|@d^+#2 zf=J85LSddGX2-7Iv3~!5nyAjAq9T#Vsk1`&o!#&woa2MH`CG1F_Ryyq7R;_ol(ZJA z>xVw{s@vxpD*`~213 zC(X9Yy?=w%Gc{Q-O72r%%Is~b?ket4g1h!qZ}N+tT&=?X%l`-G_O|}?Z&o>Tc{7{K z-<}q*4UpLqP!YbPh$EoIv1XliwC55 zt*}%rhrYxofn(QF)Rtf7{Uqd^_GW_J8MlX-uh_+>7Tk5)H|dqHR^_3vFOTf1m)+TT zXqwVr?Nj=Pww|>;AGTxC-rf7YX}|rL^z!b#6JNi-zjgl4uA{C-cOPY$K9k~D@g{3V z`WZ&?@Q}OrJewru?Ra?P(!N7W(rr}!B%7TUFpRLU5;p%REpz{qD*v77D=yS+vn!nD zYH9ns+yBhB6-GRE3ujM?UOxS5+x`9P`uC-6O=7L=+4SW(n^0R>^u(0HKMlMSCLESt za9~%tI;*PA;{T2ryDFzopr0A;^2)&Kwi literal 0 HcmV?d00001 diff --git a/styles/common.scss b/styles/common.scss new file mode 100644 index 0000000..65f0dda --- /dev/null +++ b/styles/common.scss @@ -0,0 +1,221 @@ +button[type=primary] { + background-color: #007eff; +} +page { + height: 100%; + background-color: #f5f5f5; +} +ul { + padding-left: 0; + li { + list-style: none; + } +} +.block { + padding: 0 24rpx; + margin: 20rpx 24rpx; + border-radius: 16rpx; + background-color: #fff; +} +.l-title { + display: flex; + align-items: center; + padding: 28rpx 0; + font-size: 28rpx; + color: #333; + &:before { + content: ''; + width: 6rpx; + height: 28rpx; + margin-right: 12rpx; + vertical-align: middle; + background-color: #4876F9; + } +} +.filter { + display: flex; + align-items: center; + padding: 10rpx 30rpx 10rpx 10rpx; + background-color: #fff; + .search { + flex: 1; + } + .uni-searchbar__box { + height: 70rpx; + } + .sort { + margin: 0 20rpx 0 10rpx; + &:before { + content: ''; + display: block; + margin-bottom: 5rpx; + border: 15rpx solid transparent; + border-bottom-color: #B9B9B9; + } + &:after { + content: ''; + display: block; + border: 15rpx solid transparent; + border-top-color: #B9B9B9; + } + &.desc:before { + border-bottom-color: #007EFF; + } + &.asc:after { + border-top-color: #007EFF; + } + } +} +.form-list { + border-top: 1px solid #E6E8ED; + .line { + display: flex; + justify-content: space-between; + align-items: center; + padding: 28rpx 0; + border-bottom: 1px solid #E6E8ED; + &:last-child { + border-bottom: 0; + } + } + .ph { + font-size: 28rpx; + color: #999; + } + .name, .val, input { + font-size: 28rpx; + color: #333; + } + input { + flex: 1; + margin-left: 20rpx; + text-align: right; + } + .req { + .name:after { + content: '*'; + margin-left: 6rpx; + color: #F53232; + vertical-align: middle; + } + } + .err { + .name { + color: #f00; + } + } + .inline { + display: inline-flex; + align-items: center; + @extend input; + input { + margin-right: 10rpx; + } + } +} +.picker-input .input-value-border { + line-height: 1; + border: 0; +} +.tab { + display: flex; + justify-content: space-around; + margin-bottom: 20rpx; + background-color: #fff; + li { + padding: 0 20rpx; + font-size: 28rpx; + line-height: 100rpx; + border-bottom: 3px solid transparent; + } + .active { + color: $uni-primary; + border-bottom-color: $uni-primary; + } +} +.plus { + position: fixed; + bottom: 40rpx; + right: 40rpx; +} + +.popup-mask { + z-index: 9; + position: fixed; + top: 0; + left: 0; + bottom: 0; + right: 0; + background-color: rgba(0, 0, 0, .5); +} +.popup { + z-index: 10; + position: fixed; + bottom: 0%; + width: 100%; + height: 90vh; + background-color: #fff; + border-top-left-radius: 8px; + border-top-right-radius: 8px; + .top { + text-align: center; + line-height: 100rpx; + font-size: 28rpx; + color: #333; + border-bottom: 1px solid #f1f1f1; + } + .close { + position: absolute; + top: 30rpx; + right: 30rpx; + } + .list { + max-height: calc(90vh - 206rpx); + padding: 0 30rpx; + overflow: auto; + .item { + line-height: 80rpx; + font-size: 24rpx; + } + } +} +.btn-wrap { + z-index: 10; + position: fixed; + bottom: env(safe-area-inset-bottom); + bottom: 0; + display: flex; + justify-content: flex-end; + align-items: center; + width: 100%; + padding: 20rpx 24rpx 20rpx 40rpx; + background-color: #fff; + box-shadow: 0px 0px 7rpx 0px rgba(203, 203, 203, 0.55); + box-sizing: border-box; + .btn { + width: 100%; + line-height: 80rpx; + font-size: 30rpx; + text-align: center; + color: #fff; + border-radius: 10rpx; + background-color: #007EFF; + } +} +.per-mask { + z-index: 3; + position: fixed; + top: 0; + left: 0; + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + font-size: 28rpx; + color: #333; + background-color: rgba(255, 255, 255, 0.95); + -webkit-user-drag: none; + -webkit-user-select: none; + user-select: none; +} \ No newline at end of file diff --git a/uni.scss b/uni.scss new file mode 100644 index 0000000..0bbb54a --- /dev/null +++ b/uni.scss @@ -0,0 +1,3 @@ +@import '@/uni_modules/uni-scss/variables.scss'; +@import '@/styles/common.scss'; +@import '@/static/iconfont/iconfont.css'; \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/changelog.md b/uni_modules/Sansnn-uQRCode/changelog.md new file mode 100644 index 0000000..de28dde --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/changelog.md @@ -0,0 +1,44 @@ +## 3.2.2(2022-05-12) +3.2.2 + +修复vue3引入js报错问题; +增加draw可选项,可在每一阶段绘制前后扩展自定义方法,详见文档draw(options); +其他优化。 +## 3.2.1(2022-05-09) +3.2.1 + +已实现导入临时文件方法`toTempFilePath`; +已实现保存二维码到本地或相册方法`save`; +已实现生成完成回调事件`complete`; +文档补充。 +## 3.2.0(2022-05-07) +3.2.0 + +适用所有支持canvas的前端应用和Node.js服务端; +微信小程序端切换为canvas2d; +支持绘制背景图片和前景图片,也就是说可以绘制背景和logo了; +支持对定位角进行样式设置; +支持对分割图案进行样式设置; +支持对对齐图案进行样式设置; +支持对时序图案进行样式设置; +支持对暗块进行样式设置; +支持对版本信息进行样式设置; +解决小块之间出现白线问题。 +## 3.0.1(2022-01-05) +3.0.1 gcanvas引用目录调整。 +## 3.0.0(2022-01-04) +3.0.0 uQRCode 3.0 全新版本来袭。 +## 2.0.4(2021-11-19) +2.0.4 新增绘制模式;新增绘制延时、canvas导入文件延时属性。 +## 2.0.3(2021-10-18) +2.0.3 修复在部分安卓设备生成异常;移除延迟绘制;新增批量生成示例。 +## 2.0.23(2021-08-09) + +## 2.0.22(2021-08-09) + +## 2.0.21(2021-07-28) + +## 2.0.2(2021-07-28) +2.0.2 新增延迟绘制。 +## 2.0.1(2021-07-26) +2.0.1 调整为uni_modules目录规范。 diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/bridge/bridge-weex.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/bridge/bridge-weex.js new file mode 100644 index 0000000..27086ec --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/bridge/bridge-weex.js @@ -0,0 +1,241 @@ +const isWeex = typeof WXEnvironment !== 'undefined'; +const isWeexIOS = isWeex && /ios/i.test(WXEnvironment.platform); +const isWeexAndroid = isWeex && !isWeexIOS; + +import GLmethod from '../context-webgl/GLmethod'; + +const GCanvasModule = + (typeof weex !== 'undefined' && weex.requireModule) ? (weex.requireModule('gcanvas')) : + (typeof __weex_require__ !== 'undefined') ? (__weex_require__('@weex-module/gcanvas')) : {}; + +let isDebugging = false; + +let isComboDisabled = false; + +const logCommand = (function () { + const methodQuery = []; + Object.keys(GLmethod).forEach(key => { + methodQuery[GLmethod[key]] = key; + }) + const queryMethod = (id) => { + return methodQuery[parseInt(id)] || 'NotFoundMethod'; + } + const logCommand = (id, cmds) => { + const mId = cmds.split(',')[0]; + const mName = queryMethod(mId); + console.log(`=== callNative - componentId:${id}; method: ${mName}; cmds: ${cmds}`); + } + return logCommand; +})(); + +function joinArray(arr, sep) { + let res = ''; + for (let i = 0; i < arr.length; i++) { + if (i !== 0) { + res += sep; + } + res += arr[i]; + } + return res; +} + +const commandsCache = {} + +const GBridge = { + + callEnable: (ref, configArray) => { + + commandsCache[ref] = []; + + return GCanvasModule.enable({ + componentId: ref, + config: configArray + }); + }, + + callEnableDebug: () => { + isDebugging = true; + }, + + callEnableDisableCombo: () => { + isComboDisabled = true; + }, + + callSetContextType: function (componentId, context_type) { + GCanvasModule.setContextType(context_type, componentId); + }, + + callReset: function(id){ + GCanvasModule.resetComponent && canvasModule.resetComponent(componentId); + }, + + render: isWeexIOS ? function (componentId) { + return GCanvasModule.extendCallNative({ + contextId: componentId, + type: 0x60000001 + }); + } : function (componentId) { + return callGCanvasLinkNative(componentId, 0x60000001, 'render'); + }, + + render2d: isWeexIOS ? function (componentId, commands, callback) { + + if (isDebugging) { + console.log('>>> >>> render2d ==='); + console.log('>>> commands: ' + commands); + } + + GCanvasModule.render([commands, callback?true:false], componentId, callback); + + } : function (componentId, commands,callback) { + + if (isDebugging) { + console.log('>>> >>> render2d ==='); + console.log('>>> commands: ' + commands); + } + + callGCanvasLinkNative(componentId, 0x20000001, commands); + if(callback){ + callback(); + } + }, + + callExtendCallNative: isWeexIOS ? function (componentId, cmdArgs) { + + throw 'should not be here anymore ' + cmdArgs; + + } : function (componentId, cmdArgs) { + + throw 'should not be here anymore ' + cmdArgs; + + }, + + + flushNative: isWeexIOS ? function (componentId) { + + const cmdArgs = joinArray(commandsCache[componentId], ';'); + commandsCache[componentId] = []; + + if (isDebugging) { + console.log('>>> >>> flush native ==='); + console.log('>>> commands: ' + cmdArgs); + } + + const result = GCanvasModule.extendCallNative({ + "contextId": componentId, + "type": 0x60000000, + "args": cmdArgs + }); + + const res = result && result.result; + + if (isDebugging) { + console.log('>>> result: ' + res); + } + + return res; + + } : function (componentId) { + + const cmdArgs = joinArray(commandsCache[componentId], ';'); + commandsCache[componentId] = []; + + if (isDebugging) { + console.log('>>> >>> flush native ==='); + console.log('>>> commands: ' + cmdArgs); + } + + const result = callGCanvasLinkNative(componentId, 0x60000000, cmdArgs); + + if (isDebugging) { + console.log('>>> result: ' + result); + } + + return result; + }, + + callNative: function (componentId, cmdArgs, cache) { + + if (isDebugging) { + logCommand(componentId, cmdArgs); + } + + commandsCache[componentId].push(cmdArgs); + + if (!cache || isComboDisabled) { + return GBridge.flushNative(componentId); + } else { + return undefined; + } + }, + + texImage2D(componentId, ...args) { + if (isWeexIOS) { + if (args.length === 6) { + const [target, level, internalformat, format, type, image] = args; + GBridge.callNative( + componentId, + GLmethod.texImage2D + ',' + 6 + ',' + target + ',' + level + ',' + internalformat + ',' + format + ',' + type + ',' + image.src + ) + } else if (args.length === 9) { + const [target, level, internalformat, width, height, border, format, type, image] = args; + GBridge.callNative( + componentId, + GLmethod.texImage2D + ',' + 9 + ',' + target + ',' + level + ',' + internalformat + ',' + width + ',' + height + ',' + border + ',' + + + format + ',' + type + ',' + (image ? image.src : 0) + ) + } + } else if (isWeexAndroid) { + if (args.length === 6) { + const [target, level, internalformat, format, type, image] = args; + GCanvasModule.texImage2D(componentId, target, level, internalformat, format, type, image.src); + } else if (args.length === 9) { + const [target, level, internalformat, width, height, border, format, type, image] = args; + GCanvasModule.texImage2D(componentId, target, level, internalformat, width, height, border, format, type, (image ? image.src : 0)); + } + } + }, + + texSubImage2D(componentId, target, level, xoffset, yoffset, format, type, image) { + if (isWeexIOS) { + if (arguments.length === 8) { + GBridge.callNative( + componentId, + GLmethod.texSubImage2D + ',' + 6 + ',' + target + ',' + level + ',' + xoffset + ',' + yoffset, + ',' + format + ',' + type + ',' + image.src + ) + } + } else if (isWeexAndroid) { + GCanvasModule.texSubImage2D(componentId, target, level, xoffset, yoffset, format, type, image.src); + } + }, + + bindImageTexture(componentId, src, imageId) { + GCanvasModule.bindImageTexture([src, imageId], componentId); + }, + + perloadImage([url, id], callback) { + GCanvasModule.preLoadImage([url, id], function (image) { + image.url = url; + image.id = id; + callback(image); + }); + }, + + measureText(text, fontStyle, componentId) { + return GCanvasModule.measureText([text, fontStyle], componentId); + }, + + getImageData (componentId, x, y, w, h, callback) { + GCanvasModule.getImageData([x, y,w,h],componentId,callback); + }, + + putImageData (componentId, data, x, y, w, h, callback) { + GCanvasModule.putImageData([x, y,w,h,data],componentId,callback); + }, + + toTempFilePath(componentId, x, y, width, height, destWidth, destHeight, fileType, quality, callback){ + GCanvasModule.toTempFilePath([x, y, width,height, destWidth, destHeight, fileType, quality], componentId, callback); + } +} + +export default GBridge; \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/FillStyleLinearGradient.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/FillStyleLinearGradient.js new file mode 100644 index 0000000..3e7f03a --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/FillStyleLinearGradient.js @@ -0,0 +1,18 @@ +class FillStyleLinearGradient { + + constructor(x0, y0, x1, y1) { + this._start_pos = { _x: x0, _y: y0 }; + this._end_pos = { _x: x1, _y: y1 }; + this._stop_count = 0; + this._stops = [0, 0, 0, 0, 0]; + } + + addColorStop = function (pos, color) { + if (this._stop_count < 5 && 0.0 <= pos && pos <= 1.0) { + this._stops[this._stop_count] = { _pos: pos, _color: color }; + this._stop_count++; + } + } +} + +export default FillStyleLinearGradient; \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/FillStylePattern.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/FillStylePattern.js new file mode 100644 index 0000000..6e4f646 --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/FillStylePattern.js @@ -0,0 +1,8 @@ +class FillStylePattern { + constructor(img, pattern) { + this._style = pattern; + this._img = img; + } +} + +export default FillStylePattern; \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/FillStyleRadialGradient.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/FillStyleRadialGradient.js new file mode 100644 index 0000000..7790596 --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/FillStyleRadialGradient.js @@ -0,0 +1,17 @@ +class FillStyleRadialGradient { + constructor(x0, y0, r0, x1, y1, r1) { + this._start_pos = { _x: x0, _y: y0, _r: r0 }; + this._end_pos = { _x: x1, _y: y1, _r: r1 }; + this._stop_count = 0; + this._stops = [0, 0, 0, 0, 0]; + } + + addColorStop(pos, color) { + if (this._stop_count < 5 && 0.0 <= pos && pos <= 1.0) { + this._stops[this._stop_count] = { _pos: pos, _color: color }; + this._stop_count++; + } + } +} + +export default FillStyleRadialGradient; \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/RenderingContext.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/RenderingContext.js new file mode 100644 index 0000000..e6b8f48 --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/RenderingContext.js @@ -0,0 +1,666 @@ +import FillStylePattern from './FillStylePattern'; +import FillStyleLinearGradient from './FillStyleLinearGradient'; +import FillStyleRadialGradient from './FillStyleRadialGradient'; +import GImage from '../env/image.js'; +import { + ArrayBufferToBase64, + Base64ToUint8ClampedArray +} from '../env/tool.js'; + +export default class CanvasRenderingContext2D { + + _drawCommands = ''; + + _globalAlpha = 1.0; + + _fillStyle = 'rgb(0,0,0)'; + _strokeStyle = 'rgb(0,0,0)'; + + _lineWidth = 1; + _lineCap = 'butt'; + _lineJoin = 'miter'; + + _miterLimit = 10; + + _globalCompositeOperation = 'source-over'; + + _textAlign = 'start'; + _textBaseline = 'alphabetic'; + + _font = '10px sans-serif'; + + _savedGlobalAlpha = []; + + timer = null; + componentId = null; + + _notCommitDrawImageCache = []; + _needRedrawImageCache = []; + _redrawCommands = ''; + _autoSaveContext = true; + // _imageMap = new GHashMap(); + // _textureMap = new GHashMap(); + + constructor() { + this.className = 'CanvasRenderingContext2D'; + //this.save() + } + + setFillStyle(value) { + this.fillStyle = value; + } + + set fillStyle(value) { + this._fillStyle = value; + + if (typeof(value) == 'string') { + this._drawCommands = this._drawCommands.concat("F" + value + ";"); + } else if (value instanceof FillStylePattern) { + const image = value._img; + if (!image.complete) { + image.onload = () => { + var index = this._needRedrawImageCache.indexOf(image); + if (index > -1) { + this._needRedrawImageCache.splice(index, 1); + CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id); + this._redrawflush(true); + } + } + this._notCommitDrawImageCache.push(image); + } else { + CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id); + } + + //CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id); + this._drawCommands = this._drawCommands.concat("G" + image._id + "," + value._style + ";"); + } else if (value instanceof FillStyleLinearGradient) { + var command = "D" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," + + value._end_pos._x.toFixed(2) + "," + value._end_pos._y.toFixed(2) + "," + + value._stop_count; + for (var i = 0; i < value._stop_count; ++i) { + command += ("," + value._stops[i]._pos + "," + value._stops[i]._color); + } + this._drawCommands = this._drawCommands.concat(command + ";"); + } else if (value instanceof FillStyleRadialGradient) { + var command = "H" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," + value._start_pos._r + .toFixed(2) + "," + + value._end_pos._x.toFixed(2) + "," + value._end_pos._y.toFixed(2) + "," + value._end_pos._r.toFixed(2) + "," + + value._stop_count; + for (var i = 0; i < value._stop_count; ++i) { + command += ("," + value._stops[i]._pos + "," + value._stops[i]._color); + } + this._drawCommands = this._drawCommands.concat(command + ";"); + } + } + + get fillStyle() { + return this._fillStyle; + } + + get globalAlpha() { + return this._globalAlpha; + } + + setGlobalAlpha(value) { + this.globalAlpha = value; + } + + set globalAlpha(value) { + this._globalAlpha = value; + this._drawCommands = this._drawCommands.concat("a" + value.toFixed(2) + ";"); + } + + + get strokeStyle() { + return this._strokeStyle; + } + + setStrokeStyle(value) { + this.strokeStyle = value; + } + + set strokeStyle(value) { + + this._strokeStyle = value; + + if (typeof(value) == 'string') { + this._drawCommands = this._drawCommands.concat("S" + value + ";"); + } else if (value instanceof FillStylePattern) { + CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id); + this._drawCommands = this._drawCommands.concat("G" + image._id + "," + value._style + ";"); + } else if (value instanceof FillStyleLinearGradient) { + var command = "D" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," + + value._end_pos._x.toFixed(2) + "," + value._end_pos._y.toFixed(2) + "," + + value._stop_count; + + for (var i = 0; i < value._stop_count; ++i) { + command += ("," + value._stops[i]._pos + "," + value._stops[i]._color); + } + this._drawCommands = this._drawCommands.concat(command + ";"); + } else if (value instanceof FillStyleRadialGradient) { + var command = "H" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," + value._start_pos._r + .toFixed(2) + "," + + value._end_pos._x.toFixed(2) + "," + value._end_pos._y + ",".toFixed(2) + value._end_pos._r.toFixed(2) + "," + + value._stop_count; + + for (var i = 0; i < value._stop_count; ++i) { + command += ("," + value._stops[i]._pos + "," + value._stops[i]._color); + } + this._drawCommands = this._drawCommands.concat(command + ";"); + } + } + + get lineWidth() { + return this._lineWidth; + } + + setLineWidth(value) { + this.lineWidth = value; + } + + set lineWidth(value) { + this._lineWidth = value; + this._drawCommands = this._drawCommands.concat("W" + value + ";"); + } + + get lineCap() { + return this._lineCap; + } + + setLineCap(value) { + this.lineCap = value; + } + + set lineCap(value) { + this._lineCap = value; + this._drawCommands = this._drawCommands.concat("C" + value + ";"); + } + + get lineJoin() { + return this._lineJoin; + } + + setLineJoin(value) { + this.lineJoin = value + } + + set lineJoin(value) { + this._lineJoin = value; + this._drawCommands = this._drawCommands.concat("J" + value + ";"); + } + + get miterLimit() { + return this._miterLimit; + } + + setMiterLimit(value) { + this.miterLimit = value + } + + set miterLimit(value) { + this._miterLimit = value; + this._drawCommands = this._drawCommands.concat("M" + value + ";"); + } + + get globalCompositeOperation() { + return this._globalCompositeOperation; + } + + set globalCompositeOperation(value) { + + this._globalCompositeOperation = value; + let mode = 0; + switch (value) { + case "source-over": + mode = 0; + break; + case "source-atop": + mode = 5; + break; + case "source-in": + mode = 0; + break; + case "source-out": + mode = 2; + break; + case "destination-over": + mode = 4; + break; + case "destination-atop": + mode = 4; + break; + case "destination-in": + mode = 4; + break; + case "destination-out": + mode = 3; + break; + case "lighter": + mode = 1; + break; + case "copy": + mode = 2; + break; + case "xor": + mode = 6; + break; + default: + mode = 0; + } + + this._drawCommands = this._drawCommands.concat("B" + mode + ";"); + } + + get textAlign() { + return this._textAlign; + } + + setTextAlign(value) { + this.textAlign = value + } + + set textAlign(value) { + + this._textAlign = value; + let Align = 0; + switch (value) { + case "start": + Align = 0; + break; + case "end": + Align = 1; + break; + case "left": + Align = 2; + break; + case "center": + Align = 3; + break; + case "right": + Align = 4; + break; + default: + Align = 0; + } + + this._drawCommands = this._drawCommands.concat("A" + Align + ";"); + } + + get textBaseline() { + return this._textBaseline; + } + + setTextBaseline(value) { + this.textBaseline = value + } + + set textBaseline(value) { + this._textBaseline = value; + let baseline = 0; + switch (value) { + case "alphabetic": + baseline = 0; + break; + case "middle": + baseline = 1; + break; + case "top": + baseline = 2; + break; + case "hanging": + baseline = 3; + break; + case "bottom": + baseline = 4; + break; + case "ideographic": + baseline = 5; + break; + default: + baseline = 0; + break; + } + + this._drawCommands = this._drawCommands.concat("E" + baseline + ";"); + } + + get font() { + return this._font; + } + + setFontSize(size) { + var str = this._font; + var strs = str.trim().split(/\s+/); + for (var i = 0; i < strs.length; i++) { + var values = ["normal", "italic", "oblique", "normal", "small-caps", "normal", "bold", + "bolder", "lighter", "100", "200", "300", "400", "500", "600", "700", "800", "900", + "normal", "ultra-condensed", "extra-condensed", "condensed", "semi-condensed", + "semi-expanded", "expanded", "extra-expanded", "ultra-expanded" + ]; + + if (-1 == values.indexOf(strs[i].trim())) { + if (typeof size === 'string') { + strs[i] = size; + } else if (typeof size === 'number') { + strs[i] = String(size) + 'px'; + } + break; + } + } + this.font = strs.join(" "); + } + + set font(value) { + this._font = value; + this._drawCommands = this._drawCommands.concat("j" + value + ";"); + } + + setTransform(a, b, c, d, tx, ty) { + this._drawCommands = this._drawCommands.concat("t" + + (a === 1 ? "1" : a.toFixed(2)) + "," + + (b === 0 ? "0" : b.toFixed(2)) + "," + + (c === 0 ? "0" : c.toFixed(2)) + "," + + (d === 1 ? "1" : d.toFixed(2)) + "," + tx.toFixed(2) + "," + ty.toFixed(2) + ";"); + } + + transform(a, b, c, d, tx, ty) { + this._drawCommands = this._drawCommands.concat("f" + + (a === 1 ? "1" : a.toFixed(2)) + "," + + (b === 0 ? "0" : b.toFixed(2)) + "," + + (c === 0 ? "0" : c.toFixed(2)) + "," + + (d === 1 ? "1" : d.toFixed(2)) + "," + tx + "," + ty + ";"); + } + + resetTransform() { + this._drawCommands = this._drawCommands.concat("m;"); + } + + scale(a, d) { + this._drawCommands = this._drawCommands.concat("k" + a.toFixed(2) + "," + + d.toFixed(2) + ";"); + } + + rotate(angle) { + this._drawCommands = this._drawCommands + .concat("r" + angle.toFixed(6) + ";"); + } + + translate(tx, ty) { + this._drawCommands = this._drawCommands.concat("l" + tx.toFixed(2) + "," + ty.toFixed(2) + ";"); + } + + save() { + this._savedGlobalAlpha.push(this._globalAlpha); + this._drawCommands = this._drawCommands.concat("v;"); + } + + restore() { + this._drawCommands = this._drawCommands.concat("e;"); + this._globalAlpha = this._savedGlobalAlpha.pop(); + } + + createPattern(img, pattern) { + if (typeof img === 'string') { + var imgObj = new GImage(); + imgObj.src = img; + img = imgObj; + } + return new FillStylePattern(img, pattern); + } + + createLinearGradient(x0, y0, x1, y1) { + return new FillStyleLinearGradient(x0, y0, x1, y1); + } + + createRadialGradient = function(x0, y0, r0, x1, y1, r1) { + return new FillStyleRadialGradient(x0, y0, r0, x1, y1, r1); + }; + + createCircularGradient = function(x0, y0, r0) { + return new FillStyleRadialGradient(x0, y0, 0, x0, y0, r0); + }; + + strokeRect(x, y, w, h) { + this._drawCommands = this._drawCommands.concat("s" + x + "," + y + "," + w + "," + h + ";"); + } + + + clearRect(x, y, w, h) { + this._drawCommands = this._drawCommands.concat("c" + x + "," + y + "," + w + + "," + h + ";"); + } + + clip() { + this._drawCommands = this._drawCommands.concat("p;"); + } + + resetClip() { + this._drawCommands = this._drawCommands.concat("q;"); + } + + closePath() { + this._drawCommands = this._drawCommands.concat("o;"); + } + + moveTo(x, y) { + this._drawCommands = this._drawCommands.concat("g" + x.toFixed(2) + "," + y.toFixed(2) + ";"); + } + + lineTo(x, y) { + this._drawCommands = this._drawCommands.concat("i" + x.toFixed(2) + "," + y.toFixed(2) + ";"); + } + + quadraticCurveTo = function(cpx, cpy, x, y) { + this._drawCommands = this._drawCommands.concat("u" + cpx + "," + cpy + "," + x + "," + y + ";"); + } + + bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y, ) { + this._drawCommands = this._drawCommands.concat( + "z" + cp1x.toFixed(2) + "," + cp1y.toFixed(2) + "," + cp2x.toFixed(2) + "," + cp2y.toFixed(2) + "," + + x.toFixed(2) + "," + y.toFixed(2) + ";"); + } + + arcTo(x1, y1, x2, y2, radius) { + this._drawCommands = this._drawCommands.concat("h" + x1 + "," + y1 + "," + x2 + "," + y2 + "," + radius + ";"); + } + + beginPath() { + this._drawCommands = this._drawCommands.concat("b;"); + } + + + fillRect(x, y, w, h) { + this._drawCommands = this._drawCommands.concat("n" + x + "," + y + "," + w + + "," + h + ";"); + } + + rect(x, y, w, h) { + this._drawCommands = this._drawCommands.concat("w" + x + "," + y + "," + w + "," + h + ";"); + } + + fill() { + this._drawCommands = this._drawCommands.concat("L;"); + } + + stroke(path) { + this._drawCommands = this._drawCommands.concat("x;"); + } + + arc(x, y, radius, startAngle, endAngle, anticlockwise) { + + let ianticlockwise = 0; + if (anticlockwise) { + ianticlockwise = 1; + } + + this._drawCommands = this._drawCommands.concat( + "y" + x.toFixed(2) + "," + y.toFixed(2) + "," + + radius.toFixed(2) + "," + startAngle + "," + endAngle + "," + ianticlockwise + + ";" + ); + } + + fillText(text, x, y) { + let tmptext = text.replace(/!/g, "!!"); + tmptext = tmptext.replace(/,/g, "!,"); + tmptext = tmptext.replace(/;/g, "!;"); + this._drawCommands = this._drawCommands.concat("T" + tmptext + "," + x + "," + y + ",0.0;"); + } + + strokeText = function(text, x, y) { + let tmptext = text.replace(/!/g, "!!"); + tmptext = tmptext.replace(/,/g, "!,"); + tmptext = tmptext.replace(/;/g, "!;"); + this._drawCommands = this._drawCommands.concat("U" + tmptext + "," + x + "," + y + ",0.0;"); + } + + measureText(text) { + return CanvasRenderingContext2D.GBridge.measureText(text, this.font, this.componentId); + } + + isPointInPath = function(x, y) { + throw new Error('GCanvas not supported yet'); + } + + drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) { + if (typeof image === 'string') { + var imgObj = new GImage(); + imgObj.src = image; + image = imgObj; + } + if (image instanceof GImage) { + if (!image.complete) { + imgObj.onload = () => { + var index = this._needRedrawImageCache.indexOf(image); + if (index > -1) { + this._needRedrawImageCache.splice(index, 1); + CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id); + this._redrawflush(true); + } + } + this._notCommitDrawImageCache.push(image); + } else { + CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id); + } + var srcArgs = [image, sx, sy, sw, sh, dx, dy, dw, dh]; + var args = []; + for (var arg in srcArgs) { + if (typeof(srcArgs[arg]) != 'undefined') { + args.push(srcArgs[arg]); + } + } + this.__drawImage.apply(this, args); + //this.__drawImage(image,sx, sy, sw, sh, dx, dy, dw, dh); + } + } + + __drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) { + const numArgs = arguments.length; + + function drawImageCommands() { + + if (numArgs === 3) { + const x = parseFloat(sx) || 0.0; + const y = parseFloat(sy) || 0.0; + + return ("d" + image._id + ",0,0," + + image.width + "," + image.height + "," + + x + "," + y + "," + image.width + "," + image.height + ";"); + } else if (numArgs === 5) { + const x = parseFloat(sx) || 0.0; + const y = parseFloat(sy) || 0.0; + const width = parseInt(sw) || image.width; + const height = parseInt(sh) || image.height; + + return ("d" + image._id + ",0,0," + + image.width + "," + image.height + "," + + x + "," + y + "," + width + "," + height + ";"); + } else if (numArgs === 9) { + sx = parseFloat(sx) || 0.0; + sy = parseFloat(sy) || 0.0; + sw = parseInt(sw) || image.width; + sh = parseInt(sh) || image.height; + dx = parseFloat(dx) || 0.0; + dy = parseFloat(dy) || 0.0; + dw = parseInt(dw) || image.width; + dh = parseInt(dh) || image.height; + + return ("d" + image._id + "," + + sx + "," + sy + "," + sw + "," + sh + "," + + dx + "," + dy + "," + dw + "," + dh + ";"); + } + } + this._drawCommands += drawImageCommands(); + } + + _flush(reserve, callback) { + const commands = this._drawCommands; + this._drawCommands = ''; + CanvasRenderingContext2D.GBridge.render2d(this.componentId, commands, callback); + this._needRender = false; + } + + _redrawflush(reserve, callback) { + const commands = this._redrawCommands; + CanvasRenderingContext2D.GBridge.render2d(this.componentId, commands, callback); + if (this._needRedrawImageCache.length == 0) { + this._redrawCommands = ''; + } + } + + draw(reserve, callback) { + if (!reserve) { + this._globalAlpha = this._savedGlobalAlpha.pop(); + this._savedGlobalAlpha.push(this._globalAlpha); + this._redrawCommands = this._drawCommands; + this._needRedrawImageCache = this._notCommitDrawImageCache; + if (this._autoSaveContext) { + this._drawCommands = ("v;" + this._drawCommands); + this._autoSaveContext = false; + } else { + this._drawCommands = ("e;X;v;" + this._drawCommands); + } + } else { + this._needRedrawImageCache = this._needRedrawImageCache.concat(this._notCommitDrawImageCache); + this._redrawCommands += this._drawCommands; + if (this._autoSaveContext) { + this._drawCommands = ("v;" + this._drawCommands); + this._autoSaveContext = false; + } + } + this._notCommitDrawImageCache = []; + if (this._flush) { + this._flush(reserve, callback); + } + } + + getImageData(x, y, w, h, callback) { + CanvasRenderingContext2D.GBridge.getImageData(this.componentId, x, y, w, h, function(res) { + res.data = Base64ToUint8ClampedArray(res.data); + if (typeof(callback) == 'function') { + callback(res); + } + }); + } + + putImageData(data, x, y, w, h, callback) { + if (data instanceof Uint8ClampedArray) { + data = ArrayBufferToBase64(data); + CanvasRenderingContext2D.GBridge.putImageData(this.componentId, data, x, y, w, h, function(res) { + if (typeof(callback) == 'function') { + callback(res); + } + }); + } + } + + toTempFilePath(x, y, width, height, destWidth, destHeight, fileType, quality, callback) { + CanvasRenderingContext2D.GBridge.toTempFilePath(this.componentId, x, y, width, height, destWidth, destHeight, + fileType, quality, + function(res) { + if (typeof(callback) == 'function') { + callback(res); + } + }); + } +} diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/ActiveInfo.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/ActiveInfo.js new file mode 100644 index 0000000..b495129 --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/ActiveInfo.js @@ -0,0 +1,11 @@ +export default class WebGLActiveInfo { + className = 'WebGLActiveInfo'; + + constructor({ + type, name, size + }) { + this.type = type; + this.name = name; + this.size = size; + } +} \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Buffer.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Buffer.js new file mode 100644 index 0000000..4800f67 --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Buffer.js @@ -0,0 +1,21 @@ +import {getTransferedObjectUUID} from './classUtils'; + +const name = 'WebGLBuffer'; + +function uuid(id) { + return getTransferedObjectUUID(name, id); +} + +export default class WebGLBuffer { + className = name; + + constructor(id) { + this.id = id; + } + + static uuid = uuid; + + uuid() { + return uuid(this.id); + } +} \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Framebuffer.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Framebuffer.js new file mode 100644 index 0000000..28b46d3 --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Framebuffer.js @@ -0,0 +1,21 @@ +import {getTransferedObjectUUID} from './classUtils'; + +const name = 'WebGLFrameBuffer'; + +function uuid(id) { + return getTransferedObjectUUID(name, id); +} + +export default class WebGLFramebuffer { + className = name; + + constructor(id) { + this.id = id; + } + + static uuid = uuid; + + uuid() { + return uuid(this.id); + } +} \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/GLenum.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/GLenum.js new file mode 100644 index 0000000..ac5544d --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/GLenum.js @@ -0,0 +1,298 @@ +export default { + "DEPTH_BUFFER_BIT": 256, + "STENCIL_BUFFER_BIT": 1024, + "COLOR_BUFFER_BIT": 16384, + "POINTS": 0, + "LINES": 1, + "LINE_LOOP": 2, + "LINE_STRIP": 3, + "TRIANGLES": 4, + "TRIANGLE_STRIP": 5, + "TRIANGLE_FAN": 6, + "ZERO": 0, + "ONE": 1, + "SRC_COLOR": 768, + "ONE_MINUS_SRC_COLOR": 769, + "SRC_ALPHA": 770, + "ONE_MINUS_SRC_ALPHA": 771, + "DST_ALPHA": 772, + "ONE_MINUS_DST_ALPHA": 773, + "DST_COLOR": 774, + "ONE_MINUS_DST_COLOR": 775, + "SRC_ALPHA_SATURATE": 776, + "FUNC_ADD": 32774, + "BLEND_EQUATION": 32777, + "BLEND_EQUATION_RGB": 32777, + "BLEND_EQUATION_ALPHA": 34877, + "FUNC_SUBTRACT": 32778, + "FUNC_REVERSE_SUBTRACT": 32779, + "BLEND_DST_RGB": 32968, + "BLEND_SRC_RGB": 32969, + "BLEND_DST_ALPHA": 32970, + "BLEND_SRC_ALPHA": 32971, + "CONSTANT_COLOR": 32769, + "ONE_MINUS_CONSTANT_COLOR": 32770, + "CONSTANT_ALPHA": 32771, + "ONE_MINUS_CONSTANT_ALPHA": 32772, + "BLEND_COLOR": 32773, + "ARRAY_BUFFER": 34962, + "ELEMENT_ARRAY_BUFFER": 34963, + "ARRAY_BUFFER_BINDING": 34964, + "ELEMENT_ARRAY_BUFFER_BINDING": 34965, + "STREAM_DRAW": 35040, + "STATIC_DRAW": 35044, + "DYNAMIC_DRAW": 35048, + "BUFFER_SIZE": 34660, + "BUFFER_USAGE": 34661, + "CURRENT_VERTEX_ATTRIB": 34342, + "FRONT": 1028, + "BACK": 1029, + "FRONT_AND_BACK": 1032, + "TEXTURE_2D": 3553, + "CULL_FACE": 2884, + "BLEND": 3042, + "DITHER": 3024, + "STENCIL_TEST": 2960, + "DEPTH_TEST": 2929, + "SCISSOR_TEST": 3089, + "POLYGON_OFFSET_FILL": 32823, + "SAMPLE_ALPHA_TO_COVERAGE": 32926, + "SAMPLE_COVERAGE": 32928, + "NO_ERROR": 0, + "INVALID_ENUM": 1280, + "INVALID_VALUE": 1281, + "INVALID_OPERATION": 1282, + "OUT_OF_MEMORY": 1285, + "CW": 2304, + "CCW": 2305, + "LINE_WIDTH": 2849, + "ALIASED_POINT_SIZE_RANGE": 33901, + "ALIASED_LINE_WIDTH_RANGE": 33902, + "CULL_FACE_MODE": 2885, + "FRONT_FACE": 2886, + "DEPTH_RANGE": 2928, + "DEPTH_WRITEMASK": 2930, + "DEPTH_CLEAR_VALUE": 2931, + "DEPTH_FUNC": 2932, + "STENCIL_CLEAR_VALUE": 2961, + "STENCIL_FUNC": 2962, + "STENCIL_FAIL": 2964, + "STENCIL_PASS_DEPTH_FAIL": 2965, + "STENCIL_PASS_DEPTH_PASS": 2966, + "STENCIL_REF": 2967, + "STENCIL_VALUE_MASK": 2963, + "STENCIL_WRITEMASK": 2968, + "STENCIL_BACK_FUNC": 34816, + "STENCIL_BACK_FAIL": 34817, + "STENCIL_BACK_PASS_DEPTH_FAIL": 34818, + "STENCIL_BACK_PASS_DEPTH_PASS": 34819, + "STENCIL_BACK_REF": 36003, + "STENCIL_BACK_VALUE_MASK": 36004, + "STENCIL_BACK_WRITEMASK": 36005, + "VIEWPORT": 2978, + "SCISSOR_BOX": 3088, + "COLOR_CLEAR_VALUE": 3106, + "COLOR_WRITEMASK": 3107, + "UNPACK_ALIGNMENT": 3317, + "PACK_ALIGNMENT": 3333, + "MAX_TEXTURE_SIZE": 3379, + "MAX_VIEWPORT_DIMS": 3386, + "SUBPIXEL_BITS": 3408, + "RED_BITS": 3410, + "GREEN_BITS": 3411, + "BLUE_BITS": 3412, + "ALPHA_BITS": 3413, + "DEPTH_BITS": 3414, + "STENCIL_BITS": 3415, + "POLYGON_OFFSET_UNITS": 10752, + "POLYGON_OFFSET_FACTOR": 32824, + "TEXTURE_BINDING_2D": 32873, + "SAMPLE_BUFFERS": 32936, + "SAMPLES": 32937, + "SAMPLE_COVERAGE_VALUE": 32938, + "SAMPLE_COVERAGE_INVERT": 32939, + "COMPRESSED_TEXTURE_FORMATS": 34467, + "DONT_CARE": 4352, + "FASTEST": 4353, + "NICEST": 4354, + "GENERATE_MIPMAP_HINT": 33170, + "BYTE": 5120, + "UNSIGNED_BYTE": 5121, + "SHORT": 5122, + "UNSIGNED_SHORT": 5123, + "INT": 5124, + "UNSIGNED_INT": 5125, + "FLOAT": 5126, + "DEPTH_COMPONENT": 6402, + "ALPHA": 6406, + "RGB": 6407, + "RGBA": 6408, + "LUMINANCE": 6409, + "LUMINANCE_ALPHA": 6410, + "UNSIGNED_SHORT_4_4_4_4": 32819, + "UNSIGNED_SHORT_5_5_5_1": 32820, + "UNSIGNED_SHORT_5_6_5": 33635, + "FRAGMENT_SHADER": 35632, + "VERTEX_SHADER": 35633, + "MAX_VERTEX_ATTRIBS": 34921, + "MAX_VERTEX_UNIFORM_VECTORS": 36347, + "MAX_VARYING_VECTORS": 36348, + "MAX_COMBINED_TEXTURE_IMAGE_UNITS": 35661, + "MAX_VERTEX_TEXTURE_IMAGE_UNITS": 35660, + "MAX_TEXTURE_IMAGE_UNITS": 34930, + "MAX_FRAGMENT_UNIFORM_VECTORS": 36349, + "SHADER_TYPE": 35663, + "DELETE_STATUS": 35712, + "LINK_STATUS": 35714, + "VALIDATE_STATUS": 35715, + "ATTACHED_SHADERS": 35717, + "ACTIVE_UNIFORMS": 35718, + "ACTIVE_ATTRIBUTES": 35721, + "SHADING_LANGUAGE_VERSION": 35724, + "CURRENT_PROGRAM": 35725, + "NEVER": 512, + "LESS": 513, + "EQUAL": 514, + "LEQUAL": 515, + "GREATER": 516, + "NOTEQUAL": 517, + "GEQUAL": 518, + "ALWAYS": 519, + "KEEP": 7680, + "REPLACE": 7681, + "INCR": 7682, + "DECR": 7683, + "INVERT": 5386, + "INCR_WRAP": 34055, + "DECR_WRAP": 34056, + "VENDOR": 7936, + "RENDERER": 7937, + "VERSION": 7938, + "NEAREST": 9728, + "LINEAR": 9729, + "NEAREST_MIPMAP_NEAREST": 9984, + "LINEAR_MIPMAP_NEAREST": 9985, + "NEAREST_MIPMAP_LINEAR": 9986, + "LINEAR_MIPMAP_LINEAR": 9987, + "TEXTURE_MAG_FILTER": 10240, + "TEXTURE_MIN_FILTER": 10241, + "TEXTURE_WRAP_S": 10242, + "TEXTURE_WRAP_T": 10243, + "TEXTURE": 5890, + "TEXTURE_CUBE_MAP": 34067, + "TEXTURE_BINDING_CUBE_MAP": 34068, + "TEXTURE_CUBE_MAP_POSITIVE_X": 34069, + "TEXTURE_CUBE_MAP_NEGATIVE_X": 34070, + "TEXTURE_CUBE_MAP_POSITIVE_Y": 34071, + "TEXTURE_CUBE_MAP_NEGATIVE_Y": 34072, + "TEXTURE_CUBE_MAP_POSITIVE_Z": 34073, + "TEXTURE_CUBE_MAP_NEGATIVE_Z": 34074, + "MAX_CUBE_MAP_TEXTURE_SIZE": 34076, + "TEXTURE0": 33984, + "TEXTURE1": 33985, + "TEXTURE2": 33986, + "TEXTURE3": 33987, + "TEXTURE4": 33988, + "TEXTURE5": 33989, + "TEXTURE6": 33990, + "TEXTURE7": 33991, + "TEXTURE8": 33992, + "TEXTURE9": 33993, + "TEXTURE10": 33994, + "TEXTURE11": 33995, + "TEXTURE12": 33996, + "TEXTURE13": 33997, + "TEXTURE14": 33998, + "TEXTURE15": 33999, + "TEXTURE16": 34000, + "TEXTURE17": 34001, + "TEXTURE18": 34002, + "TEXTURE19": 34003, + "TEXTURE20": 34004, + "TEXTURE21": 34005, + "TEXTURE22": 34006, + "TEXTURE23": 34007, + "TEXTURE24": 34008, + "TEXTURE25": 34009, + "TEXTURE26": 34010, + "TEXTURE27": 34011, + "TEXTURE28": 34012, + "TEXTURE29": 34013, + "TEXTURE30": 34014, + "TEXTURE31": 34015, + "ACTIVE_TEXTURE": 34016, + "REPEAT": 10497, + "CLAMP_TO_EDGE": 33071, + "MIRRORED_REPEAT": 33648, + "FLOAT_VEC2": 35664, + "FLOAT_VEC3": 35665, + "FLOAT_VEC4": 35666, + "INT_VEC2": 35667, + "INT_VEC3": 35668, + "INT_VEC4": 35669, + "BOOL": 35670, + "BOOL_VEC2": 35671, + "BOOL_VEC3": 35672, + "BOOL_VEC4": 35673, + "FLOAT_MAT2": 35674, + "FLOAT_MAT3": 35675, + "FLOAT_MAT4": 35676, + "SAMPLER_2D": 35678, + "SAMPLER_CUBE": 35680, + "VERTEX_ATTRIB_ARRAY_ENABLED": 34338, + "VERTEX_ATTRIB_ARRAY_SIZE": 34339, + "VERTEX_ATTRIB_ARRAY_STRIDE": 34340, + "VERTEX_ATTRIB_ARRAY_TYPE": 34341, + "VERTEX_ATTRIB_ARRAY_NORMALIZED": 34922, + "VERTEX_ATTRIB_ARRAY_POINTER": 34373, + "VERTEX_ATTRIB_ARRAY_BUFFER_BINDING": 34975, + "IMPLEMENTATION_COLOR_READ_TYPE": 35738, + "IMPLEMENTATION_COLOR_READ_FORMAT": 35739, + "COMPILE_STATUS": 35713, + "LOW_FLOAT": 36336, + "MEDIUM_FLOAT": 36337, + "HIGH_FLOAT": 36338, + "LOW_INT": 36339, + "MEDIUM_INT": 36340, + "HIGH_INT": 36341, + "FRAMEBUFFER": 36160, + "RENDERBUFFER": 36161, + "RGBA4": 32854, + "RGB5_A1": 32855, + "RGB565": 36194, + "DEPTH_COMPONENT16": 33189, + "STENCIL_INDEX8": 36168, + "DEPTH_STENCIL": 34041, + "RENDERBUFFER_WIDTH": 36162, + "RENDERBUFFER_HEIGHT": 36163, + "RENDERBUFFER_INTERNAL_FORMAT": 36164, + "RENDERBUFFER_RED_SIZE": 36176, + "RENDERBUFFER_GREEN_SIZE": 36177, + "RENDERBUFFER_BLUE_SIZE": 36178, + "RENDERBUFFER_ALPHA_SIZE": 36179, + "RENDERBUFFER_DEPTH_SIZE": 36180, + "RENDERBUFFER_STENCIL_SIZE": 36181, + "FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE": 36048, + "FRAMEBUFFER_ATTACHMENT_OBJECT_NAME": 36049, + "FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL": 36050, + "FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE": 36051, + "COLOR_ATTACHMENT0": 36064, + "DEPTH_ATTACHMENT": 36096, + "STENCIL_ATTACHMENT": 36128, + "DEPTH_STENCIL_ATTACHMENT": 33306, + "NONE": 0, + "FRAMEBUFFER_COMPLETE": 36053, + "FRAMEBUFFER_INCOMPLETE_ATTACHMENT": 36054, + "FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT": 36055, + "FRAMEBUFFER_INCOMPLETE_DIMENSIONS": 36057, + "FRAMEBUFFER_UNSUPPORTED": 36061, + "FRAMEBUFFER_BINDING": 36006, + "RENDERBUFFER_BINDING": 36007, + "MAX_RENDERBUFFER_SIZE": 34024, + "INVALID_FRAMEBUFFER_OPERATION": 1286, + "UNPACK_FLIP_Y_WEBGL": 37440, + "UNPACK_PREMULTIPLY_ALPHA_WEBGL": 37441, + "CONTEXT_LOST_WEBGL": 37442, + "UNPACK_COLORSPACE_CONVERSION_WEBGL": 37443, + "BROWSER_DEFAULT_WEBGL": 37444 +}; \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/GLmethod.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/GLmethod.js new file mode 100644 index 0000000..f2659be --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/GLmethod.js @@ -0,0 +1,142 @@ +let i = 1; + +const GLmethod = {}; + +GLmethod.activeTexture = i++; //1 +GLmethod.attachShader = i++; +GLmethod.bindAttribLocation = i++; +GLmethod.bindBuffer = i++; +GLmethod.bindFramebuffer = i++; +GLmethod.bindRenderbuffer = i++; +GLmethod.bindTexture = i++; +GLmethod.blendColor = i++; +GLmethod.blendEquation = i++; +GLmethod.blendEquationSeparate = i++; //10 +GLmethod.blendFunc = i++; +GLmethod.blendFuncSeparate = i++; +GLmethod.bufferData = i++; +GLmethod.bufferSubData = i++; +GLmethod.checkFramebufferStatus = i++; +GLmethod.clear = i++; +GLmethod.clearColor = i++; +GLmethod.clearDepth = i++; +GLmethod.clearStencil = i++; +GLmethod.colorMask = i++; //20 +GLmethod.compileShader = i++; +GLmethod.compressedTexImage2D = i++; +GLmethod.compressedTexSubImage2D = i++; +GLmethod.copyTexImage2D = i++; +GLmethod.copyTexSubImage2D = i++; +GLmethod.createBuffer = i++; +GLmethod.createFramebuffer = i++; +GLmethod.createProgram = i++; +GLmethod.createRenderbuffer = i++; +GLmethod.createShader = i++; //30 +GLmethod.createTexture = i++; +GLmethod.cullFace = i++; +GLmethod.deleteBuffer = i++; +GLmethod.deleteFramebuffer = i++; +GLmethod.deleteProgram = i++; +GLmethod.deleteRenderbuffer = i++; +GLmethod.deleteShader = i++; +GLmethod.deleteTexture = i++; +GLmethod.depthFunc = i++; +GLmethod.depthMask = i++; //40 +GLmethod.depthRange = i++; +GLmethod.detachShader = i++; +GLmethod.disable = i++; +GLmethod.disableVertexAttribArray = i++; +GLmethod.drawArrays = i++; +GLmethod.drawArraysInstancedANGLE = i++; +GLmethod.drawElements = i++; +GLmethod.drawElementsInstancedANGLE = i++; +GLmethod.enable = i++; +GLmethod.enableVertexAttribArray = i++; //50 +GLmethod.flush = i++; +GLmethod.framebufferRenderbuffer = i++; +GLmethod.framebufferTexture2D = i++; +GLmethod.frontFace = i++; +GLmethod.generateMipmap = i++; +GLmethod.getActiveAttrib = i++; +GLmethod.getActiveUniform = i++; +GLmethod.getAttachedShaders = i++; +GLmethod.getAttribLocation = i++; +GLmethod.getBufferParameter = i++; //60 +GLmethod.getContextAttributes = i++; +GLmethod.getError = i++; +GLmethod.getExtension = i++; +GLmethod.getFramebufferAttachmentParameter = i++; +GLmethod.getParameter = i++; +GLmethod.getProgramInfoLog = i++; +GLmethod.getProgramParameter = i++; +GLmethod.getRenderbufferParameter = i++; +GLmethod.getShaderInfoLog = i++; +GLmethod.getShaderParameter = i++; //70 +GLmethod.getShaderPrecisionFormat = i++; +GLmethod.getShaderSource = i++; +GLmethod.getSupportedExtensions = i++; +GLmethod.getTexParameter = i++; +GLmethod.getUniform = i++; +GLmethod.getUniformLocation = i++; +GLmethod.getVertexAttrib = i++; +GLmethod.getVertexAttribOffset = i++; +GLmethod.isBuffer = i++; +GLmethod.isContextLost = i++; //80 +GLmethod.isEnabled = i++; +GLmethod.isFramebuffer = i++; +GLmethod.isProgram = i++; +GLmethod.isRenderbuffer = i++; +GLmethod.isShader = i++; +GLmethod.isTexture = i++; +GLmethod.lineWidth = i++; +GLmethod.linkProgram = i++; +GLmethod.pixelStorei = i++; +GLmethod.polygonOffset = i++; //90 +GLmethod.readPixels = i++; +GLmethod.renderbufferStorage = i++; +GLmethod.sampleCoverage = i++; +GLmethod.scissor = i++; +GLmethod.shaderSource = i++; +GLmethod.stencilFunc = i++; +GLmethod.stencilFuncSeparate = i++; +GLmethod.stencilMask = i++; +GLmethod.stencilMaskSeparate = i++; +GLmethod.stencilOp = i++; //100 +GLmethod.stencilOpSeparate = i++; +GLmethod.texImage2D = i++; +GLmethod.texParameterf = i++; +GLmethod.texParameteri = i++; +GLmethod.texSubImage2D = i++; +GLmethod.uniform1f = i++; +GLmethod.uniform1fv = i++; +GLmethod.uniform1i = i++; +GLmethod.uniform1iv = i++; +GLmethod.uniform2f = i++; //110 +GLmethod.uniform2fv = i++; +GLmethod.uniform2i = i++; +GLmethod.uniform2iv = i++; +GLmethod.uniform3f = i++; +GLmethod.uniform3fv = i++; +GLmethod.uniform3i = i++; +GLmethod.uniform3iv = i++; +GLmethod.uniform4f = i++; +GLmethod.uniform4fv = i++; +GLmethod.uniform4i = i++; //120 +GLmethod.uniform4iv = i++; +GLmethod.uniformMatrix2fv = i++; +GLmethod.uniformMatrix3fv = i++; +GLmethod.uniformMatrix4fv = i++; +GLmethod.useProgram = i++; +GLmethod.validateProgram = i++; +GLmethod.vertexAttrib1f = i++; //new +GLmethod.vertexAttrib2f = i++; //new +GLmethod.vertexAttrib3f = i++; //new +GLmethod.vertexAttrib4f = i++; //new //130 +GLmethod.vertexAttrib1fv = i++; //new +GLmethod.vertexAttrib2fv = i++; //new +GLmethod.vertexAttrib3fv = i++; //new +GLmethod.vertexAttrib4fv = i++; //new +GLmethod.vertexAttribPointer = i++; +GLmethod.viewport = i++; + +export default GLmethod; \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/GLtype.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/GLtype.js new file mode 100644 index 0000000..695abcb --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/GLtype.js @@ -0,0 +1,23 @@ +const GLtype = {}; + +[ + "GLbitfield", + "GLboolean", + "GLbyte", + "GLclampf", + "GLenum", + "GLfloat", + "GLint", + "GLintptr", + "GLsizei", + "GLsizeiptr", + "GLshort", + "GLubyte", + "GLuint", + "GLushort" +].sort().map((typeName, i) => GLtype[typeName] = 1 >> (i + 1)); + +export default GLtype; + + + diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Program.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Program.js new file mode 100644 index 0000000..6f5691c --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Program.js @@ -0,0 +1,21 @@ +import {getTransferedObjectUUID} from './classUtils'; + +const name = 'WebGLProgram'; + +function uuid(id) { + return getTransferedObjectUUID(name, id); +} + +export default class WebGLProgram { + className = name; + + constructor(id) { + this.id = id; + } + + static uuid = uuid; + + uuid() { + return uuid(this.id); + } +} \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Renderbuffer.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Renderbuffer.js new file mode 100644 index 0000000..d3182ae --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Renderbuffer.js @@ -0,0 +1,21 @@ +import {getTransferedObjectUUID} from './classUtils'; + +const name = 'WebGLRenderBuffer'; + +function uuid(id) { + return getTransferedObjectUUID(name, id); +} + +export default class WebGLRenderbuffer { + className = name; + + constructor(id) { + this.id = id; + } + + static uuid = uuid; + + uuid() { + return uuid(this.id); + } +} \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/RenderingContext.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/RenderingContext.js new file mode 100644 index 0000000..5f9608f --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/RenderingContext.js @@ -0,0 +1,1191 @@ +import GLenum from './GLenum'; +import ActiveInfo from './ActiveInfo'; +import Buffer from './Buffer'; +import Framebuffer from './Framebuffer'; +import Renderbuffer from './Renderbuffer'; +import Texture from './Texture'; +import Program from './Program'; +import Shader from './Shader'; +import ShaderPrecisionFormat from './ShaderPrecisionFormat'; +import UniformLocation from './UniformLocation'; +import GLmethod from './GLmethod'; + +const processArray = (array, checkArrayType = false) => { + + function joinArray(arr, sep) { + let res = ''; + for (let i = 0; i < arr.length; i++) { + if (i !== 0) { + res += sep; + } + res += arr[i]; + } + return res; + } + + let type = 'Float32Array'; + if (checkArrayType) { + if (array instanceof Uint8Array) { + type = 'Uint8Array' + } else if (array instanceof Uint16Array) { + type = 'Uint16Array'; + } else if (array instanceof Uint32Array) { + type = 'Uint32Array'; + } else if (array instanceof Float32Array) { + type = 'Float32Array'; + } else { + throw new Error('Check array type failed. Array type is ' + typeof array); + } + } + + const ArrayTypes = { + Uint8Array: 1, + Uint16Array: 2, + Uint32Array: 4, + Float32Array: 14 + }; + return ArrayTypes[type] + ',' + btoa(joinArray(array, ',')) +} + +export default class WebGLRenderingContext { + + // static GBridge = null; + + className = 'WebGLRenderingContext'; + + constructor(canvas, type, attrs) { + this._canvas = canvas; + this._type = type; + this._version = 'WebGL 1.0'; + this._attrs = attrs; + this._map = new Map(); + + Object.keys(GLenum) + .forEach(name => Object.defineProperty(this, name, { + value: GLenum[name] + })); + } + + get canvas() { + return this._canvas; + } + + activeTexture = function (textureUnit) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.activeTexture + ',' + textureUnit, + true + ); + } + + attachShader = function (progarm, shader) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.attachShader + ',' + progarm.id + ',' + shader.id, + true + ); + } + + bindAttribLocation = function (program, index, name) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.bindAttribLocation + ',' + program.id + ',' + index + ',' + name, + true + ) + } + + bindBuffer = function (target, buffer) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.bindBuffer + ',' + target + ',' + (buffer ? buffer.id : 0), + true + ); + } + + bindFramebuffer = function (target, framebuffer) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.bindFramebuffer + ',' + target + ',' + (framebuffer ? framebuffer.id : 0), + true + ) + } + + bindRenderbuffer = function (target, renderBuffer) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.bindRenderbuffer + ',' + target + ',' + (renderBuffer ? renderBuffer.id : 0), + true + ) + } + + bindTexture = function (target, texture) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.bindTexture + ',' + target + ',' + (texture ? texture.id : 0), + true + ) + } + + blendColor = function (r, g, b, a) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.blendColor + ',' + target + ',' + r + ',' + g + ',' + b + ',' + a, + true + ) + } + + blendEquation = function (mode) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.blendEquation + ',' + mode, + true + ) + } + + blendEquationSeparate = function (modeRGB, modeAlpha) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.blendEquationSeparate + ',' + modeRGB + ',' + modeAlpha, + true + ) + } + + + blendFunc = function (sfactor, dfactor) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.blendFunc + ',' + sfactor + ',' + dfactor, + true + ); + } + + blendFuncSeparate = function (srcRGB, dstRGB, srcAlpha, dstAlpha) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.blendFuncSeparate + ',' + srcRGB + ',' + dstRGB + ',' + srcAlpha + ',' + dstAlpha, + true + ); + } + + bufferData = function (target, data, usage) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.bufferData + ',' + target + ',' + processArray(data, true) + ',' + usage, + true + ) + } + + bufferSubData = function (target, offset, data) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.bufferSubData + ',' + target + ',' + offset + ',' + processArray(data, true), + true + ) + } + + checkFramebufferStatus = function (target) { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.checkFramebufferStatus + ',' + target + ); + return Number(result); + } + + clear = function (mask) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.clear + ',' + mask + ); + this._canvas._needRender = true; + } + + clearColor = function (r, g, b, a) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.clearColor + ',' + r + ',' + g + ',' + b, + true + ) + } + + clearDepth = function (depth) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.clearDepth + ',' + depth, + true + ) + } + + clearStencil = function (s) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.clearStencil + ',' + s + ); + } + + colorMask = function (r, g, b, a) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.colorMask + ',' + r + ',' + g + ',' + b + ',' + a + ) + } + + compileShader = function (shader) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.compileShader + ',' + shader.id, + true + ) + } + + compressedTexImage2D = function (target, level, internalformat, width, height, border, pixels) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.compressedTexImage2D + ',' + target + ',' + level + ',' + internalformat + ',' + + width + ',' + height + ',' + border + ',' + processArray(pixels), + true + ) + } + + compressedTexSubImage2D = function (target, level, xoffset, yoffset, width, height, format, pixels) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.compressedTexSubImage2D + ',' + target + ',' + level + ',' + xoffset + ',' + yoffset + ',' + + width + ',' + height + ',' + format + ',' + processArray(pixels), + true + ) + } + + + copyTexImage2D = function (target, level, internalformat, x, y, width, height, border) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.copyTexImage2D + ',' + target + ',' + level + ',' + internalformat + ',' + x + ',' + y + ',' + + width + ',' + height + ',' + border, + true + ); + } + + copyTexSubImage2D = function (target, level, xoffset, yoffset, x, y, width, height) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.copyTexSubImage2D + ',' + target + ',' + level + ',' + xoffset + ',' + yoffset + ',' + x + ',' + y + ',' + + width + ',' + height + ); + } + + createBuffer = function () { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.createBuffer + '' + ); + const buffer = new Buffer(result); + this._map.set(buffer.uuid(), buffer); + return buffer; + } + + createFramebuffer = function () { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.createFramebuffer + '' + ); + const framebuffer = new Framebuffer(result); + this._map.set(framebuffer.uuid(), framebuffer); + return framebuffer; + } + + + createProgram = function () { + const id = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.createProgram + '' + ); + const program = new Program(id); + this._map.set(program.uuid(), program); + return program; + } + + createRenderbuffer = function () { + const id = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.createRenderbuffer + '' + ) + const renderBuffer = new Renderbuffer(id); + this._map.set(renderBuffer.uuid(), renderBuffer); + return renderBuffer; + } + + createShader = function (type) { + const id = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.createShader + ',' + type + ) + const shader = new Shader(id, type); + this._map.set(shader.uuid(), shader); + return shader; + } + + createTexture = function () { + const id = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.createTexture + '' + ); + const texture = new Texture(id); + this._map.set(texture.uuid(), texture); + return texture; + } + + cullFace = function (mode) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.cullFace + ',' + mode, + true + ) + } + + + deleteBuffer = function (buffer) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.deleteBuffer + ',' + buffer.id, + true + ) + } + + deleteFramebuffer = function (framebuffer) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.deleteFramebuffer + ',' + framebuffer.id, + true + ) + } + + deleteProgram = function (program) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.deleteProgram + ',' + program.id, + true + ) + } + + deleteRenderbuffer = function (renderbuffer) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.deleteRenderbuffer + ',' + renderbuffer.id, + true + ) + } + + deleteShader = function (shader) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.deleteShader + ',' + shader.id, + true + ) + } + + deleteTexture = function (texture) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.deleteTexture + ',' + texture.id, + true + ) + } + + depthFunc = function (func) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.depthFunc + ',' + func + ) + } + + depthMask = function (flag) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.depthMask + ',' + Number(flag), + true + ) + } + + depthRange = function (zNear, zFar) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.depthRange + ',' + zNear + ',' + zFar, + true + ) + } + + detachShader = function (program, shader) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.detachShader + ',' + program.id + ',' + shader.id, + true + ) + } + + disable = function (cap) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.disable + ',' + cap, + true + ) + } + + disableVertexAttribArray = function (index) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.disableVertexAttribArray + ',' + index, + true + ); + } + + drawArrays = function (mode, first, count) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.drawArrays + ',' + mode + ',' + first + ',' + count + ) + this._canvas._needRender = true; + } + + drawElements = function (mode, count, type, offset) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.drawElements + ',' + mode + ',' + count + ',' + type + ',' + offset + ';' + ); + this._canvas._needRender = true; + } + + enable = function (cap) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.enable + ',' + cap, + true + ); + } + + enableVertexAttribArray = function (index) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.enableVertexAttribArray + ',' + index, + true + ) + } + + + flush = function () { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.flush + '' + ) + } + + framebufferRenderbuffer = function (target, attachment, textarget, texture, level) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.framebufferRenderbuffer + ',' + target + ',' + attachment + ',' + textarget + ',' + (texture ? texture.id : 0) + ',' + level, + true + ) + } + + framebufferTexture2D = function (target, attachment, textarget, texture, level) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.framebufferTexture2D + ',' + target + ',' + attachment + ',' + textarget + ',' + (texture ? texture.id : 0) + ',' + level, + true + ) + } + + frontFace = function (mode) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.frontFace + ',' + mode, + true + ) + } + + generateMipmap = function (target) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.generateMipmap + ',' + target, + true + ) + } + + getActiveAttrib = function (progarm, index) { + const resultString = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.getActiveAttrib + ',' + progarm.id + ',' + index + ) + const [type, size, name] = resultString.split(','); + return new ActiveInfo({ + type: Number(type), + size: Number(size), + name + }); + } + + getActiveUniform = function (progarm, index) { + const resultString = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.getActiveUniform + ',' + progarm.id + ',' + index + ); + const [type, size, name] = resultString.split(','); + return new ActiveInfo({ + type: Number(type), + size: Number(size), + name + }) + } + + getAttachedShaders = function (progarm) { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.getAttachedShaders + ',' + progarm.id + ); + const [type, ...ids] = result; + return ids.map(id => this._map.get(Shader.uuid(id))); + } + + getAttribLocation = function (progarm, name) { + return WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.getAttribLocation + ',' + progarm.id + ',' + name + ) + } + + getBufferParameter = function (target, pname) { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.getBufferParameter + ',' + target + ',' + pname + ); + const [type, res] = getBufferParameter; + return res; + } + + getError = function () { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.getError + '' + ) + return result; + } + + getExtension = function (name) { + return null; + } + + getFramebufferAttachmentParameter = function (target, attachment, pname) { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.getFramebufferAttachmentParameter + ',' + target + ',' + attachment + ',' + pname + ) + switch (pname) { + case GLenum.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + return this._map.get(Renderbuffer.uuid(result)) || this._map.get(Texture.uuid(result)) || null; + default: + return result; + } + } + + getParameter = function (pname) { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.getParameter + ',' + pname + ) + switch (pname) { + case GLenum.VERSION: + return this._version; + case GLenum.ARRAY_BUFFER_BINDING: // buffer + case GLenum.ELEMENT_ARRAY_BUFFER_BINDING: // buffer + return this._map.get(Buffer.uuid(result)) || null; + case GLenum.CURRENT_PROGRAM: // program + return this._map.get(Program.uuid(result)) || null; + case GLenum.FRAMEBUFFER_BINDING: // framebuffer + return this._map.get(Framebuffer.uuid(result)) || null; + case GLenum.RENDERBUFFER_BINDING: // renderbuffer + return this._map.get(Renderbuffer.uuid(result)) || null; + case GLenum.TEXTURE_BINDING_2D: // texture + case GLenum.TEXTURE_BINDING_CUBE_MAP: // texture + return this._map.get(Texture.uuid(result)) || null; + case GLenum.ALIASED_LINE_WIDTH_RANGE: // Float32Array + case GLenum.ALIASED_POINT_SIZE_RANGE: // Float32Array + case GLenum.BLEND_COLOR: // Float32Array + case GLenum.COLOR_CLEAR_VALUE: // Float32Array + case GLenum.DEPTH_RANGE: // Float32Array + case GLenum.MAX_VIEWPORT_DIMS: // Int32Array + case GLenum.SCISSOR_BOX: // Int32Array + case GLenum.VIEWPORT: // Int32Array + case GLenum.COMPRESSED_TEXTURE_FORMATS: // Uint32Array + default: + const [type, ...res] = result.split(','); + if (res.length === 1) { + return Number(res[0]); + } else { + return res.map(Number); + } + } + } + + getProgramInfoLog = function (progarm) { + return WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.getProgramInfoLog + ',' + progarm.id + ) + } + + getProgramParameter = function (program, pname) { + const res = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.getProgramParameter + ',' + program.id + ',' + pname + ); + + const [type, result] = res.split(',').map(i => parseInt(i)); + + if (type === 1) { + return Boolean(result); + } else if (type === 2) { + return result; + } else { + throw new Error('Unrecongized program paramater ' + res + ', type: ' + typeof res); + } + } + + + getRenderbufferParameter = function (target, pname) { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.getRenderbufferParameter + ',' + target + ',' + pname + ) + return result; + } + + + getShaderInfoLog = function (shader) { + return WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.getShaderInfoLog + ',' + shader.id + ); + } + + getShaderParameter = function (shader, pname) { + return WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.getShaderParameter + ',' + shader.id + ',' + pname + ) + } + + getShaderPrecisionFormat = function (shaderType, precisionType) { + const [rangeMin, rangeMax, precision] = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.getShaderPrecisionFormat + ',' + shaderType + ',' + precisionType + ); + const shaderPrecisionFormat = new ShaderPrecisionFormat({ + rangeMin: Number(rangeMin), + rangeMax: Number(rangeMax), + precision: Number(precision) + }); + return shaderPrecisionFormat; + } + + getShaderSource = function (shader) { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.getShaderSource + ',' + shader.id + ); + return result; + } + + getSupportedExtensions = function () { + return Object.keys({}); + } + + getTexParameter = function (target, pname) { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.getTexParameter + ',' + target + ',' + pname + ) + return result; + } + + getUniformLocation = function (program, name) { + const id = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.getUniformLocation + ',' + program.id + ',' + name + ); + if (id === -1) { + return null; + } else { + return new UniformLocation(Number(id)); + } + } + + getVertexAttrib = function (index, pname) { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.getVertexAttrib + ',' + index + ',' + pname + ); + switch (pname) { + case GLenum.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: + return this._map.get(Buffer.uuid(result)) || null; + case GLenum.CURRENT_VERTEX_ATTRIB: // Float32Array + default: + return result; + } + } + + getVertexAttribOffset = function (index, pname) { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.getVertexAttribOffset + ',' + index + ',' + pname + ) + return Number(result); + } + + isBuffer = function (buffer) { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.isBuffer + ',' + buffer.id + ) + return Boolean(result); + } + + isContextLost = function () { + return false; + } + + isEnabled = function (cap) { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.isEnabled + ',' + cap + ) + return Boolean(result); + } + + isFramebuffer = function (framebuffer) { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.isFramebuffer + ',' + framebuffer.id + ) + return Boolean(result); + } + + isProgram = function (program) { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.isProgram + ',' + program.id + ) + return Boolean(result); + } + + isRenderbuffer = function (renderBuffer) { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.isRenderbuffer + ',' + renderbuffer.id + ) + return Boolean(result); + } + + isShader = function (shader) { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.isShader + ',' + shader.id + ) + return Boolean(result); + } + + isTexture = function (texture) { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.isTexture + ',' + texture.id + ); + return Boolean(result); + } + + lineWidth = function (width) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.lineWidth + ',' + width, + true + ) + } + + linkProgram = function (program) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.linkProgram + ',' + program.id, + true + ); + } + + + pixelStorei = function (pname, param) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.pixelStorei + ',' + pname + ',' + Number(param) + ) + } + + polygonOffset = function (factor, units) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.polygonOffset + ',' + factor + ',' + units + ) + } + + readPixels = function (x, y, width, height, format, type, pixels) { + const result = WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.readPixels + ',' + x + ',' + y + ',' + width + ',' + height + ',' + format + ',' + type + ) + return result; + } + + renderbufferStorage = function (target, internalFormat, width, height) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.renderbufferStorage + ',' + target + ',' + internalFormat + ',' + width + ',' + height, + true + ) + } + + sampleCoverage = function (value, invert) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.sampleCoverage + ',' + value + ',' + Number(invert), + true + ) + } + + scissor = function (x, y, width, height) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.scissor + ',' + x + ',' + y + ',' + width + ',' + height, + true + ) + } + + shaderSource = function (shader, source) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.shaderSource + ',' + shader.id + ',' + source + ) + } + + stencilFunc = function (func, ref, mask) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.stencilFunc + ',' + func + ',' + ref + ',' + mask, + true + ) + } + + stencilFuncSeparate = function (face, func, ref, mask) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.stencilFuncSeparate + ',' + face + ',' + func + ',' + ref + ',' + mask, + true + ) + } + + stencilMask = function (mask) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.stencilMask + ',' + mask, + true + ) + } + + stencilMaskSeparate = function (face, mask) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.stencilMaskSeparate + ',' + face + ',' + mask, + true + ) + } + + stencilOp = function (fail, zfail, zpass) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.stencilOp + ',' + fail + ',' + zfail + ',' + zpass + ) + } + + stencilOpSeparate = function (face, fail, zfail, zpass) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.stencilOp + ',' + face + ',' + fail + ',' + zfail + ',' + zpass, + true + ) + } + + texImage2D = function (...args) { + WebGLRenderingContext.GBridge.texImage2D(this._canvas.id, ...args); + } + + + texParameterf = function (target, pname, param) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.texParameterf + ',' + target + ',' + pname + ',' + param, + true + ) + } + + texParameteri = function (target, pname, param) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.texParameteri + ',' + target + ',' + pname + ',' + param + ) + } + + texSubImage2D = function (...args) { + WebGLRenderingContext.GBridge.texSubImage2D(this._canvas.id, ...args); + } + + uniform1f = function (location, v0) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.uniform1f + ',' + location.id + ',' + v0 + ) + } + + uniform1fv = function (location, value) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.uniform1fv + ',' + location.id + ',' + processArray(value), + true + ) + } + + uniform1i = function (location, v0) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.uniform1i + ',' + location.id + ',' + v0, + // true + ) + } + + uniform1iv = function (location, value) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.uniform1iv + ',' + location.id + ',' + processArray(value), + true + ) + } + + uniform2f = function (location, v0, v1) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.uniform2f + ',' + location.id + ',' + v0 + ',' + v1, + true + ) + } + + uniform2fv = function (location, value) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.uniform2fv + ',' + location.id + ',' + processArray(value), + true + ) + } + + uniform2i = function (location, v0, v1) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.uniform2i + ',' + location.id + ',' + v0 + ',' + v1, + true + ) + } + + uniform2iv = function (location, value) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.uniform2iv + ',' + location.id + ',' + processArray(value), + true + ) + } + + uniform3f = function (location, v0, v1, v2) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.uniform3f + ',' + location.id + ',' + v0 + ',' + v1 + ',' + v2, + true + ) + } + + uniform3fv = function (location, value) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.uniform3fv + ',' + location.id + ',' + processArray(value), + true + ) + } + + uniform3i = function (location, v0, v1, v2) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.uniform3i + ',' + location.id + ',' + v0 + ',' + v1 + ',' + v2, + true + ) + } + + uniform3iv = function (location, value) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.uniform3iv + ',' + location.id + ',' + processArray(value), + true + ) + } + + uniform4f = function (location, v0, v1, v2, v3) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.uniform4f + ',' + location.id + ',' + v0 + ',' + v1 + ',' + v2 + ',' + v3, + true + ) + } + + uniform4fv = function (location, value) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.uniform4fv + ',' + location.id + ',' + processArray(value), + true + ) + } + + uniform4i = function (location, v0, v1, v2, v3) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.uniform4i + ',' + location.id + ',' + v0 + ',' + v1 + ',' + v2 + ',' + v3, + true + ) + } + + uniform4iv = function (location, value) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.uniform4iv + ',' + location.id + ',' + processArray(value, true), + true + ) + } + + uniformMatrix2fv = function (location, transpose, value) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.uniformMatrix2fv + ',' + location.id + ',' + Number(transpose) + ',' + processArray(value), + true + ) + } + + uniformMatrix3fv = function (location, transpose, value) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.uniformMatrix3fv + ',' + location.id + ',' + Number(transpose) + ',' + processArray(value), + true + ) + } + + uniformMatrix4fv = function (location, transpose, value) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.uniformMatrix4fv + ',' + location.id + ',' + Number(transpose) + ',' + processArray(value), + true + ); + } + + useProgram = function (progarm) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.useProgram + ',' + progarm.id + '', + true + ) + } + + + validateProgram = function (program) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.validateProgram + ',' + program.id, + true + ) + } + + vertexAttrib1f = function (index, v0) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.vertexAttrib1f + ',' + index + ',' + v0, + true + ) + } + + vertexAttrib2f = function (index, v0, v1) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.vertexAttrib2f + ',' + index + ',' + v0 + ',' + v1, + true + ) + } + + vertexAttrib3f = function (index, v0, v1, v2) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.vertexAttrib3f + ',' + index + ',' + v0 + ',' + v1 + ',' + v2, + true + ) + } + + vertexAttrib4f = function (index, v0, v1, v2, v3) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.vertexAttrib4f + ',' + index + ',' + v0 + ',' + v1 + ',' + v2 + ',' + v3, + true + ) + } + + vertexAttrib1fv = function (index, value) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.vertexAttrib1fv + ',' + index + ',' + processArray(value), + true + ) + } + + vertexAttrib2fv = function (index, value) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.vertexAttrib2fv + ',' + index + ',' + processArray(value), + true + ) + } + + vertexAttrib3fv = function (index, value) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.vertexAttrib3fv + ',' + index + ',' + processArray(value), + true + ) + } + + vertexAttrib4fv = function (index, value) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.vertexAttrib4fv + ',' + index + ',' + processArray(value), + true + ) + } + + vertexAttribPointer = function (index, size, type, normalized, stride, offset) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.vertexAttribPointer + ',' + index + ',' + size + ',' + type + ',' + Number(normalized) + ',' + stride + ',' + offset, + true + ) + } + + viewport = function (x, y, width, height) { + WebGLRenderingContext.GBridge.callNative( + this._canvas.id, + GLmethod.viewport + ',' + x + ',' + y + ',' + width + ',' + height, + true + ) + } +} \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Shader.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Shader.js new file mode 100644 index 0000000..a763886 --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Shader.js @@ -0,0 +1,22 @@ +import {getTransferedObjectUUID} from './classUtils'; + +const name = 'WebGLShader'; + +function uuid(id) { + return getTransferedObjectUUID(name, id); +} + +export default class WebGLShader { + className = name; + + constructor(id, type) { + this.id = id; + this.type = type; + } + + static uuid = uuid; + + uuid() { + return uuid(this.id); + } +} \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/ShaderPrecisionFormat.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/ShaderPrecisionFormat.js new file mode 100644 index 0000000..208d6c1 --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/ShaderPrecisionFormat.js @@ -0,0 +1,11 @@ +export default class WebGLShaderPrecisionFormat { + className = 'WebGLShaderPrecisionFormat'; + + constructor({ + rangeMin, rangeMax, precision + }) { + this.rangeMin = rangeMin; + this.rangeMax = rangeMax; + this.precision = precision; + } +} \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Texture.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Texture.js new file mode 100644 index 0000000..de4d806 --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Texture.js @@ -0,0 +1,22 @@ +import {getTransferedObjectUUID} from './classUtils'; + +const name = 'WebGLTexture'; + +function uuid(id) { + return getTransferedObjectUUID(name, id); +} + +export default class WebGLTexture { + className = name; + + constructor(id, type) { + this.id = id; + this.type = type; + } + + static uuid = uuid; + + uuid() { + return uuid(this.id); + } +} \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/UniformLocation.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/UniformLocation.js new file mode 100644 index 0000000..f5e99dc --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/UniformLocation.js @@ -0,0 +1,22 @@ +import {getTransferedObjectUUID} from './classUtils'; + +const name = 'WebGLUniformLocation'; + +function uuid(id) { + return getTransferedObjectUUID(name, id); +} + +export default class WebGLUniformLocation { + className = name; + + constructor(id, type) { + this.id = id; + this.type = type; + } + + static uuid = uuid; + + uuid() { + return uuid(this.id); + } +} \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/classUtils.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/classUtils.js new file mode 100644 index 0000000..88716be --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/classUtils.js @@ -0,0 +1,3 @@ +export function getTransferedObjectUUID(name, id) { + return `${name.toLowerCase()}-${id}`; +} \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/env/canvas.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/env/canvas.js new file mode 100644 index 0000000..a8d9bb9 --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/env/canvas.js @@ -0,0 +1,74 @@ +import GContext2D from '../context-2d/RenderingContext'; +import GContextWebGL from '../context-webgl/RenderingContext'; + +export default class GCanvas { + + // static GBridge = null; + + id = null; + + _needRender = true; + + constructor(id, { disableAutoSwap }) { + this.id = id; + + this._disableAutoSwap = disableAutoSwap; + if (disableAutoSwap) { + this._swapBuffers = () => { + GCanvas.GBridge.render(this.id); + } + } + } + + getContext(type) { + + let context = null; + + if (type.match(/webgl/i)) { + context = new GContextWebGL(this); + + context.componentId = this.id; + + if (!this._disableAutoSwap) { + const render = () => { + if (this._needRender) { + GCanvas.GBridge.render(this.id); + this._needRender = false; + } + } + setInterval(render, 16); + } + + GCanvas.GBridge.callSetContextType(this.id, 1); // 0 for 2d; 1 for webgl + } else if (type.match(/2d/i)) { + context = new GContext2D(this); + + context.componentId = this.id; + +// const render = ( callback ) => { +// +// const commands = context._drawCommands; +// context._drawCommands = ''; +// +// GCanvas.GBridge.render2d(this.id, commands, callback); +// this._needRender = false; +// } +// //draw方法触发 +// context._flush = render; +// //setInterval(render, 16); + + GCanvas.GBridge.callSetContextType(this.id, 0); + } else { + throw new Error('not supported context ' + type); + } + + return context; + + } + + reset() { + GCanvas.GBridge.callReset(this.id); + } + + +} \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/env/image.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/env/image.js new file mode 100644 index 0000000..9499a51 --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/env/image.js @@ -0,0 +1,96 @@ +let incId = 1; + +const noop = function () { }; + +class GImage { + + static GBridge = null; + + constructor() { + this._id = incId++; + this._width = 0; + this._height = 0; + this._src = undefined; + this._onload = noop; + this._onerror = noop; + this.complete = false; + } + + get width() { + return this._width; + } + set width(v) { + this._width = v; + } + + get height() { + return this._height; + } + + set height(v) { + this._height = v; + } + + get src() { + return this._src; + } + + set src(v) { + + if (v.startsWith('//')) { + v = 'http:' + v; + } + + this._src = v; + + GImage.GBridge.perloadImage([this._src, this._id], (data) => { + if (typeof data === 'string') { + data = JSON.parse(data); + } + if (data.error) { + var evt = { type: 'error', target: this }; + this.onerror(evt); + } else { + this.complete = true; + this.width = typeof data.width === 'number' ? data.width : 0; + this.height = typeof data.height === 'number' ? data.height : 0; + var evt = { type: 'load', target: this }; + this.onload(evt); + } + }); + } + + addEventListener(name, listener) { + if (name === 'load') { + this.onload = listener; + } else if (name === 'error') { + this.onerror = listener; + } + } + + removeEventListener(name, listener) { + if (name === 'load') { + this.onload = noop; + } else if (name === 'error') { + this.onerror = noop; + } + } + + get onload() { + return this._onload; + } + + set onload(v) { + this._onload = v; + } + + get onerror() { + return this._onerror; + } + + set onerror(v) { + this._onerror = v; + } +} + +export default GImage; \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/env/tool.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/env/tool.js new file mode 100644 index 0000000..d3fb398 --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/env/tool.js @@ -0,0 +1,24 @@ + +export function ArrayBufferToBase64 (buffer) { + var binary = ''; + var bytes = new Uint8ClampedArray(buffer); + for (var len = bytes.byteLength, i = 0; i < len; i++) { + binary += String.fromCharCode(bytes[i]); + } + return btoa(binary); +} + +export function Base64ToUint8ClampedArray(base64String) { + const padding = '='.repeat((4 - base64String.length % 4) % 4); + const base64 = (base64String + padding) + .replace(/\-/g, '+') + .replace(/_/g, '/'); + + const rawData = atob(base64); + const outputArray = new Uint8ClampedArray(rawData.length); + + for (let i = 0; i < rawData.length; ++i) { + outputArray[i] = rawData.charCodeAt(i); + } + return outputArray; +} \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/index.js b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/index.js new file mode 100644 index 0000000..a34ad58 --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/index.js @@ -0,0 +1,39 @@ +import GCanvas from './env/canvas'; +import GImage from './env/image'; + +import GWebGLRenderingContext from './context-webgl/RenderingContext'; +import GContext2D from './context-2d/RenderingContext'; + +import GBridgeWeex from './bridge/bridge-weex'; + +export let Image = GImage; + +export let WeexBridge = GBridgeWeex; + +export function enable(el, { bridge, debug, disableAutoSwap, disableComboCommands } = {}) { + + const GBridge = GImage.GBridge = GCanvas.GBridge = GWebGLRenderingContext.GBridge = GContext2D.GBridge = bridge; + + GBridge.callEnable(el.ref, [ + 0, // renderMode: 0--RENDERMODE_WHEN_DIRTY, 1--RENDERMODE_CONTINUOUSLY + -1, // hybridLayerType: 0--LAYER_TYPE_NONE 1--LAYER_TYPE_SOFTWARE 2--LAYER_TYPE_HARDWARE + false, // supportScroll + false, // newCanvasMode + 1, // compatible + 'white',// clearColor + false // sameLevel: newCanvasMode = true && true => GCanvasView and Webview is same level + ]); + + if (debug === true) { + GBridge.callEnableDebug(); + } + if (disableComboCommands) { + GBridge.callEnableDisableCombo(); + } + + var canvas = new GCanvas(el.ref, { disableAutoSwap }); + canvas.width = el.style.width; + canvas.height = el.style.height; + + return canvas; +}; \ No newline at end of file diff --git a/uni_modules/Sansnn-uQRCode/components/u-qrcode/u-qrcode.vue b/uni_modules/Sansnn-uQRCode/components/u-qrcode/u-qrcode.vue new file mode 100644 index 0000000..d9e7ad2 --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/components/u-qrcode/u-qrcode.vue @@ -0,0 +1,684 @@ + + + + + + diff --git a/uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/license.md b/uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/license.md new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/license.md @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/module.js b/uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/module.js new file mode 100644 index 0000000..a3cbfca --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/module.js @@ -0,0 +1,2285 @@ +//--------------------------------------------------------------------- +// uQRCode 二维码生成插件 v3.2.2 +// +// uQRCode 是一款使用方式简单,高扩展的二维码生成插件。支持全端生成,支持canvas的地方就可以使用uQRCode。 +// +// Copyright (c) Sansnn uQRCode All rights reserved. +// Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) +// 复制使用请保留本段注释,感谢支持开源! +// +// 开源地址: +// https://github.com/Sansnn/uQRCode +// +// uni-app插件市场地址: +// https://ext.dcloud.net.cn/plugin?id=1287 +//--------------------------------------------------------------------- + +"use strict"; + +function uQRCode(options, canvasContext, loadImage) { + this.options = uQRCode.getOptions(options); + this.canvasContext = uQRCode.getCanvasContext(canvasContext); + this.loadImage = uQRCode.getLoadImage(loadImage); +} + +(function() { + //--------------------------------------------------------------------- + // QRCode for JavaScript + // + // Copyright (c) 2009 Kazuhiko Arase + // + // URL: http://www.d-project.com/ + // + // Licensed under the MIT license: + // http://www.opensource.org/licenses/mit-license.php + // + // The word "QR Code" is registered trademark of + // DENSO WAVE INCORPORATED + // http://www.denso-wave.com/qrcode/faqpatent-e.html + // + //--------------------------------------------------------------------- + + //--------------------------------------------------------------------- + // QR8bitByte + //--------------------------------------------------------------------- + + function QR8bitByte(data) { + this.mode = QRMode.MODE_8BIT_BYTE; + this.data = data; + } + + QR8bitByte.prototype = { + + getLength: function(buffer) { + return this.data.length; + }, + + write: function(buffer) { + for (var i = 0; i < this.data.length; i++) { + // not JIS ... + buffer.put(this.data.charCodeAt(i), 8); + } + } + }; + + //--------------------------------------------------------------------- + // QRCode + //--------------------------------------------------------------------- + + function QRCode(typeNumber, errorCorrectLevel) { + this.typeNumber = typeNumber; + this.errorCorrectLevel = errorCorrectLevel; + this.modules = null; + this.moduleCount = 0; + this.dataCache = null; + this.dataList = new Array(); + } + + QRCode.prototype = { + + addData: function(data) { + var newData = new QR8bitByte(data); + this.dataList.push(newData); + this.dataCache = null; + }, + + isDark: function(row, col) { + if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) { + throw new Error(row + "," + col); + } + return this.modules[row][col]; + }, + + getModuleCount: function() { + return this.moduleCount; + }, + + make: function() { + // Calculate automatically typeNumber if provided is < 1 + if (this.typeNumber < 1) { + var typeNumber = 1; + for (typeNumber = 1; typeNumber < 40; typeNumber++) { + var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, this.errorCorrectLevel); + + var buffer = new QRBitBuffer(); + var totalDataCount = 0; + for (var i = 0; i < rsBlocks.length; i++) { + totalDataCount += rsBlocks[i].dataCount; + } + + for (var i = 0; i < this.dataList.length; i++) { + var data = this.dataList[i]; + buffer.put(data.mode, 4); + buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber)); + data.write(buffer); + } + if (buffer.getLengthInBits() <= totalDataCount * 8) + break; + } + this.typeNumber = typeNumber; + } + this.makeImpl(false, this.getBestMaskPattern()); + }, + + makeImpl: function(test, maskPattern) { + + this.moduleCount = this.typeNumber * 4 + 17; + this.modules = new Array(this.moduleCount); + + for (var row = 0; row < this.moduleCount; row++) { + + this.modules[row] = new Array(this.moduleCount); + + for (var col = 0; col < this.moduleCount; col++) { + this.modules[row][col] = null; //(col + row) % 3; + } + } + + this.setupPositionProbePattern(0, 0); + this.setupPositionProbePattern(this.moduleCount - 7, 0); + this.setupPositionProbePattern(0, this.moduleCount - 7); + this.setupPositionAdjustPattern(); + this.setupTimingPattern(); + this.setupTypeInfo(test, maskPattern); + + if (this.typeNumber >= 7) { + this.setupTypeNumber(test); + } + + if (this.dataCache == null) { + this.dataCache = QRCode.createData(this.typeNumber, this.errorCorrectLevel, this.dataList); + } + + this.mapData(this.dataCache, maskPattern); + }, + + setupPositionProbePattern: function(row, col) { + + for (var r = -1; r <= 7; r++) { + + if (row + r <= -1 || this.moduleCount <= row + r) continue; + + for (var c = -1; c <= 7; c++) { + + if (col + c <= -1 || this.moduleCount <= col + c) continue; + + if ((0 <= r && r <= 6 && (c == 0 || c == 6)) || + (0 <= c && c <= 6 && (r == 0 || r == 6)) || + (2 <= r && r <= 4 && 2 <= c && c <= 4)) { + this.modules[row + r][col + c] = true; + } else { + this.modules[row + r][col + c] = false; + } + } + } + }, + + getBestMaskPattern: function() { + + var minLostPoint = 0; + var pattern = 0; + + for (var i = 0; i < 8; i++) { + + this.makeImpl(true, i); + + var lostPoint = QRUtil.getLostPoint(this); + + if (i == 0 || minLostPoint > lostPoint) { + minLostPoint = lostPoint; + pattern = i; + } + } + + return pattern; + }, + + createMovieClip: function(target_mc, instance_name, depth) { + + var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth); + var cs = 1; + + this.make(); + + for (var row = 0; row < this.modules.length; row++) { + + var y = row * cs; + + for (var col = 0; col < this.modules[row].length; col++) { + + var x = col * cs; + var dark = this.modules[row][col]; + + if (dark) { + qr_mc.beginFill(0, 100); + qr_mc.moveTo(x, y); + qr_mc.lineTo(x + cs, y); + qr_mc.lineTo(x + cs, y + cs); + qr_mc.lineTo(x, y + cs); + qr_mc.endFill(); + } + } + } + + return qr_mc; + }, + + setupTimingPattern: function() { + + for (var r = 8; r < this.moduleCount - 8; r++) { + if (this.modules[r][6] != null) { + continue; + } + this.modules[r][6] = (r % 2 == 0); + } + + for (var c = 8; c < this.moduleCount - 8; c++) { + if (this.modules[6][c] != null) { + continue; + } + this.modules[6][c] = (c % 2 == 0); + } + }, + + setupPositionAdjustPattern: function() { + + var pos = QRUtil.getPatternPosition(this.typeNumber); + + for (var i = 0; i < pos.length; i++) { + + for (var j = 0; j < pos.length; j++) { + + var row = pos[i]; + var col = pos[j]; + + if (this.modules[row][col] != null) { + continue; + } + + for (var r = -2; r <= 2; r++) { + + for (var c = -2; c <= 2; c++) { + + if (r == -2 || r == 2 || c == -2 || c == 2 || + (r == 0 && c == 0)) { + this.modules[row + r][col + c] = true; + } else { + this.modules[row + r][col + c] = false; + } + } + } + } + } + }, + + setupTypeNumber: function(test) { + + var bits = QRUtil.getBCHTypeNumber(this.typeNumber); + + for (var i = 0; i < 18; i++) { + var mod = (!test && ((bits >> i) & 1) == 1); + this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod; + } + + for (var i = 0; i < 18; i++) { + var mod = (!test && ((bits >> i) & 1) == 1); + this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod; + } + }, + + setupTypeInfo: function(test, maskPattern) { + + var data = (this.errorCorrectLevel << 3) | maskPattern; + var bits = QRUtil.getBCHTypeInfo(data); + + // vertical + for (var i = 0; i < 15; i++) { + + var mod = (!test && ((bits >> i) & 1) == 1); + + if (i < 6) { + this.modules[i][8] = mod; + } else if (i < 8) { + this.modules[i + 1][8] = mod; + } else { + this.modules[this.moduleCount - 15 + i][8] = mod; + } + } + + // horizontal + for (var i = 0; i < 15; i++) { + + var mod = (!test && ((bits >> i) & 1) == 1); + + if (i < 8) { + this.modules[8][this.moduleCount - i - 1] = mod; + } else if (i < 9) { + this.modules[8][15 - i - 1 + 1] = mod; + } else { + this.modules[8][15 - i - 1] = mod; + } + } + + // fixed module + this.modules[this.moduleCount - 8][8] = (!test); + + }, + + mapData: function(data, maskPattern) { + + var inc = -1; + var row = this.moduleCount - 1; + var bitIndex = 7; + var byteIndex = 0; + + for (var col = this.moduleCount - 1; col > 0; col -= 2) { + + if (col == 6) col--; + + while (true) { + + for (var c = 0; c < 2; c++) { + + if (this.modules[row][col - c] == null) { + + var dark = false; + + if (byteIndex < data.length) { + dark = (((data[byteIndex] >>> bitIndex) & 1) == 1); + } + + var mask = QRUtil.getMask(maskPattern, row, col - c); + + if (mask) { + dark = !dark; + } + + this.modules[row][col - c] = dark; + bitIndex--; + + if (bitIndex == -1) { + byteIndex++; + bitIndex = 7; + } + } + } + + row += inc; + + if (row < 0 || this.moduleCount <= row) { + row -= inc; + inc = -inc; + break; + } + } + } + + } + + }; + + QRCode.PAD0 = 0xEC; + QRCode.PAD1 = 0x11; + + QRCode.createData = function(typeNumber, errorCorrectLevel, dataList) { + + var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel); + + var buffer = new QRBitBuffer(); + + for (var i = 0; i < dataList.length; i++) { + var data = dataList[i]; + buffer.put(data.mode, 4); + buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber)); + data.write(buffer); + } + + // calc num max data. + var totalDataCount = 0; + for (var i = 0; i < rsBlocks.length; i++) { + totalDataCount += rsBlocks[i].dataCount; + } + + if (buffer.getLengthInBits() > totalDataCount * 8) { + throw new Error("code length overflow. (" + + buffer.getLengthInBits() + + ">" + + totalDataCount * 8 + + ")"); + } + + // end code + if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) { + buffer.put(0, 4); + } + + // padding + while (buffer.getLengthInBits() % 8 != 0) { + buffer.putBit(false); + } + + // padding + while (true) { + + if (buffer.getLengthInBits() >= totalDataCount * 8) { + break; + } + buffer.put(QRCode.PAD0, 8); + + if (buffer.getLengthInBits() >= totalDataCount * 8) { + break; + } + buffer.put(QRCode.PAD1, 8); + } + + return QRCode.createBytes(buffer, rsBlocks); + } + + QRCode.createBytes = function(buffer, rsBlocks) { + + var offset = 0; + + var maxDcCount = 0; + var maxEcCount = 0; + + var dcdata = new Array(rsBlocks.length); + var ecdata = new Array(rsBlocks.length); + + for (var r = 0; r < rsBlocks.length; r++) { + + var dcCount = rsBlocks[r].dataCount; + var ecCount = rsBlocks[r].totalCount - dcCount; + + maxDcCount = Math.max(maxDcCount, dcCount); + maxEcCount = Math.max(maxEcCount, ecCount); + + dcdata[r] = new Array(dcCount); + + for (var i = 0; i < dcdata[r].length; i++) { + dcdata[r][i] = 0xff & buffer.buffer[i + offset]; + } + offset += dcCount; + + var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount); + var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1); + + var modPoly = rawPoly.mod(rsPoly); + ecdata[r] = new Array(rsPoly.getLength() - 1); + for (var i = 0; i < ecdata[r].length; i++) { + var modIndex = i + modPoly.getLength() - ecdata[r].length; + ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0; + } + + } + + var totalCodeCount = 0; + for (var i = 0; i < rsBlocks.length; i++) { + totalCodeCount += rsBlocks[i].totalCount; + } + + var data = new Array(totalCodeCount); + var index = 0; + + for (var i = 0; i < maxDcCount; i++) { + for (var r = 0; r < rsBlocks.length; r++) { + if (i < dcdata[r].length) { + data[index++] = dcdata[r][i]; + } + } + } + + for (var i = 0; i < maxEcCount; i++) { + for (var r = 0; r < rsBlocks.length; r++) { + if (i < ecdata[r].length) { + data[index++] = ecdata[r][i]; + } + } + } + + return data; + + } + + //--------------------------------------------------------------------- + // QRMode + //--------------------------------------------------------------------- + + var QRMode = { + MODE_NUMBER: 1 << 0, + MODE_ALPHA_NUM: 1 << 1, + MODE_8BIT_BYTE: 1 << 2, + MODE_KANJI: 1 << 3 + }; + + //--------------------------------------------------------------------- + // QRErrorCorrectLevel + //--------------------------------------------------------------------- + + var QRErrorCorrectLevel = { + L: 1, + M: 0, + Q: 3, + H: 2 + }; + + //--------------------------------------------------------------------- + // QRMaskPattern + //--------------------------------------------------------------------- + + var QRMaskPattern = { + PATTERN000: 0, + PATTERN001: 1, + PATTERN010: 2, + PATTERN011: 3, + PATTERN100: 4, + PATTERN101: 5, + PATTERN110: 6, + PATTERN111: 7 + }; + + //--------------------------------------------------------------------- + // QRUtil + //--------------------------------------------------------------------- + + var QRUtil = { + + PATTERN_POSITION_TABLE: [ + [], + [6, 18], + [6, 22], + [6, 26], + [6, 30], + [6, 34], + [6, 22, 38], + [6, 24, 42], + [6, 26, 46], + [6, 28, 50], + [6, 30, 54], + [6, 32, 58], + [6, 34, 62], + [6, 26, 46, 66], + [6, 26, 48, 70], + [6, 26, 50, 74], + [6, 30, 54, 78], + [6, 30, 56, 82], + [6, 30, 58, 86], + [6, 34, 62, 90], + [6, 28, 50, 72, 94], + [6, 26, 50, 74, 98], + [6, 30, 54, 78, 102], + [6, 28, 54, 80, 106], + [6, 32, 58, 84, 110], + [6, 30, 58, 86, 114], + [6, 34, 62, 90, 118], + [6, 26, 50, 74, 98, 122], + [6, 30, 54, 78, 102, 126], + [6, 26, 52, 78, 104, 130], + [6, 30, 56, 82, 108, 134], + [6, 34, 60, 86, 112, 138], + [6, 30, 58, 86, 114, 142], + [6, 34, 62, 90, 118, 146], + [6, 30, 54, 78, 102, 126, 150], + [6, 24, 50, 76, 102, 128, 154], + [6, 28, 54, 80, 106, 132, 158], + [6, 32, 58, 84, 110, 136, 162], + [6, 26, 54, 82, 110, 138, 166], + [6, 30, 58, 86, 114, 142, 170] + ], + + G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0), + G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0), + G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1), + + getBCHTypeInfo: function(data) { + var d = data << 10; + while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) { + d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15))); + } + return ((data << 10) | d) ^ QRUtil.G15_MASK; + }, + + getBCHTypeNumber: function(data) { + var d = data << 12; + while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) { + d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18))); + } + return (data << 12) | d; + }, + + getBCHDigit: function(data) { + + var digit = 0; + + while (data != 0) { + digit++; + data >>>= 1; + } + + return digit; + }, + + getPatternPosition: function(typeNumber) { + return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1]; + }, + + getMask: function(maskPattern, i, j) { + + switch (maskPattern) { + + case QRMaskPattern.PATTERN000: + return (i + j) % 2 == 0; + case QRMaskPattern.PATTERN001: + return i % 2 == 0; + case QRMaskPattern.PATTERN010: + return j % 3 == 0; + case QRMaskPattern.PATTERN011: + return (i + j) % 3 == 0; + case QRMaskPattern.PATTERN100: + return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0; + case QRMaskPattern.PATTERN101: + return (i * j) % 2 + (i * j) % 3 == 0; + case QRMaskPattern.PATTERN110: + return ((i * j) % 2 + (i * j) % 3) % 2 == 0; + case QRMaskPattern.PATTERN111: + return ((i * j) % 3 + (i + j) % 2) % 2 == 0; + + default: + throw new Error("bad maskPattern:" + maskPattern); + } + }, + + getErrorCorrectPolynomial: function(errorCorrectLength) { + + var a = new QRPolynomial([1], 0); + + for (var i = 0; i < errorCorrectLength; i++) { + a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0)); + } + + return a; + }, + + getLengthInBits: function(mode, type) { + + if (1 <= type && type < 10) { + + // 1 - 9 + + switch (mode) { + case QRMode.MODE_NUMBER: + return 10; + case QRMode.MODE_ALPHA_NUM: + return 9; + case QRMode.MODE_8BIT_BYTE: + return 8; + case QRMode.MODE_KANJI: + return 8; + default: + throw new Error("mode:" + mode); + } + + } else if (type < 27) { + + // 10 - 26 + + switch (mode) { + case QRMode.MODE_NUMBER: + return 12; + case QRMode.MODE_ALPHA_NUM: + return 11; + case QRMode.MODE_8BIT_BYTE: + return 16; + case QRMode.MODE_KANJI: + return 10; + default: + throw new Error("mode:" + mode); + } + + } else if (type < 41) { + + // 27 - 40 + + switch (mode) { + case QRMode.MODE_NUMBER: + return 14; + case QRMode.MODE_ALPHA_NUM: + return 13; + case QRMode.MODE_8BIT_BYTE: + return 16; + case QRMode.MODE_KANJI: + return 12; + default: + throw new Error("mode:" + mode); + } + + } else { + throw new Error("type:" + type); + } + }, + + getLostPoint: function(qrCode) { + + var moduleCount = qrCode.getModuleCount(); + + var lostPoint = 0; + + // LEVEL1 + + for (var row = 0; row < moduleCount; row++) { + + for (var col = 0; col < moduleCount; col++) { + + var sameCount = 0; + var dark = qrCode.isDark(row, col); + + for (var r = -1; r <= 1; r++) { + + if (row + r < 0 || moduleCount <= row + r) { + continue; + } + + for (var c = -1; c <= 1; c++) { + + if (col + c < 0 || moduleCount <= col + c) { + continue; + } + + if (r == 0 && c == 0) { + continue; + } + + if (dark == qrCode.isDark(row + r, col + c)) { + sameCount++; + } + } + } + + if (sameCount > 5) { + lostPoint += (3 + sameCount - 5); + } + } + } + + // LEVEL2 + + for (var row = 0; row < moduleCount - 1; row++) { + for (var col = 0; col < moduleCount - 1; col++) { + var count = 0; + if (qrCode.isDark(row, col)) count++; + if (qrCode.isDark(row + 1, col)) count++; + if (qrCode.isDark(row, col + 1)) count++; + if (qrCode.isDark(row + 1, col + 1)) count++; + if (count == 0 || count == 4) { + lostPoint += 3; + } + } + } + + // LEVEL3 + + for (var row = 0; row < moduleCount; row++) { + for (var col = 0; col < moduleCount - 6; col++) { + if (qrCode.isDark(row, col) && + !qrCode.isDark(row, col + 1) && + qrCode.isDark(row, col + 2) && + qrCode.isDark(row, col + 3) && + qrCode.isDark(row, col + 4) && + !qrCode.isDark(row, col + 5) && + qrCode.isDark(row, col + 6)) { + lostPoint += 40; + } + } + } + + for (var col = 0; col < moduleCount; col++) { + for (var row = 0; row < moduleCount - 6; row++) { + if (qrCode.isDark(row, col) && + !qrCode.isDark(row + 1, col) && + qrCode.isDark(row + 2, col) && + qrCode.isDark(row + 3, col) && + qrCode.isDark(row + 4, col) && + !qrCode.isDark(row + 5, col) && + qrCode.isDark(row + 6, col)) { + lostPoint += 40; + } + } + } + + // LEVEL4 + + var darkCount = 0; + + for (var col = 0; col < moduleCount; col++) { + for (var row = 0; row < moduleCount; row++) { + if (qrCode.isDark(row, col)) { + darkCount++; + } + } + } + + var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5; + lostPoint += ratio * 10; + + return lostPoint; + } + + }; + + + //--------------------------------------------------------------------- + // QRMath + //--------------------------------------------------------------------- + + var QRMath = { + + glog: function(n) { + + if (n < 1) { + throw new Error("glog(" + n + ")"); + } + + return QRMath.LOG_TABLE[n]; + }, + + gexp: function(n) { + + while (n < 0) { + n += 255; + } + + while (n >= 256) { + n -= 255; + } + + return QRMath.EXP_TABLE[n]; + }, + + EXP_TABLE: new Array(256), + + LOG_TABLE: new Array(256) + + }; + + for (var i = 0; i < 8; i++) { + QRMath.EXP_TABLE[i] = 1 << i; + } + for (var i = 8; i < 256; i++) { + QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ + QRMath.EXP_TABLE[i - 5] ^ + QRMath.EXP_TABLE[i - 6] ^ + QRMath.EXP_TABLE[i - 8]; + } + for (var i = 0; i < 255; i++) { + QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i; + } + + //--------------------------------------------------------------------- + // QRPolynomial + //--------------------------------------------------------------------- + + function QRPolynomial(num, shift) { + + if (num.length == undefined) { + throw new Error(num.length + "/" + shift); + } + + var offset = 0; + + while (offset < num.length && num[offset] == 0) { + offset++; + } + + this.num = new Array(num.length - offset + shift); + for (var i = 0; i < num.length - offset; i++) { + this.num[i] = num[i + offset]; + } + } + + QRPolynomial.prototype = { + + get: function(index) { + return this.num[index]; + }, + + getLength: function() { + return this.num.length; + }, + + multiply: function(e) { + + var num = new Array(this.getLength() + e.getLength() - 1); + + for (var i = 0; i < this.getLength(); i++) { + for (var j = 0; j < e.getLength(); j++) { + num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j))); + } + } + + return new QRPolynomial(num, 0); + }, + + mod: function(e) { + + if (this.getLength() - e.getLength() < 0) { + return this; + } + + var ratio = QRMath.glog(this.get(0)) - QRMath.glog(e.get(0)); + + var num = new Array(this.getLength()); + + for (var i = 0; i < this.getLength(); i++) { + num[i] = this.get(i); + } + + for (var i = 0; i < e.getLength(); i++) { + num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio); + } + + // recursive call + return new QRPolynomial(num, 0).mod(e); + } + }; + + //--------------------------------------------------------------------- + // QRRSBlock + //--------------------------------------------------------------------- + + function QRRSBlock(totalCount, dataCount) { + this.totalCount = totalCount; + this.dataCount = dataCount; + } + + QRRSBlock.RS_BLOCK_TABLE = [ + + // L + // M + // Q + // H + + // 1 + [1, 26, 19], + [1, 26, 16], + [1, 26, 13], + [1, 26, 9], + + // 2 + [1, 44, 34], + [1, 44, 28], + [1, 44, 22], + [1, 44, 16], + + // 3 + [1, 70, 55], + [1, 70, 44], + [2, 35, 17], + [2, 35, 13], + + // 4 + [1, 100, 80], + [2, 50, 32], + [2, 50, 24], + [4, 25, 9], + + // 5 + [1, 134, 108], + [2, 67, 43], + [2, 33, 15, 2, 34, 16], + [2, 33, 11, 2, 34, 12], + + // 6 + [2, 86, 68], + [4, 43, 27], + [4, 43, 19], + [4, 43, 15], + + // 7 + [2, 98, 78], + [4, 49, 31], + [2, 32, 14, 4, 33, 15], + [4, 39, 13, 1, 40, 14], + + // 8 + [2, 121, 97], + [2, 60, 38, 2, 61, 39], + [4, 40, 18, 2, 41, 19], + [4, 40, 14, 2, 41, 15], + + // 9 + [2, 146, 116], + [3, 58, 36, 2, 59, 37], + [4, 36, 16, 4, 37, 17], + [4, 36, 12, 4, 37, 13], + + // 10 + [2, 86, 68, 2, 87, 69], + [4, 69, 43, 1, 70, 44], + [6, 43, 19, 2, 44, 20], + [6, 43, 15, 2, 44, 16], + + // 11 + [4, 101, 81], + [1, 80, 50, 4, 81, 51], + [4, 50, 22, 4, 51, 23], + [3, 36, 12, 8, 37, 13], + + // 12 + [2, 116, 92, 2, 117, 93], + [6, 58, 36, 2, 59, 37], + [4, 46, 20, 6, 47, 21], + [7, 42, 14, 4, 43, 15], + + // 13 + [4, 133, 107], + [8, 59, 37, 1, 60, 38], + [8, 44, 20, 4, 45, 21], + [12, 33, 11, 4, 34, 12], + + // 14 + [3, 145, 115, 1, 146, 116], + [4, 64, 40, 5, 65, 41], + [11, 36, 16, 5, 37, 17], + [11, 36, 12, 5, 37, 13], + + // 15 + [5, 109, 87, 1, 110, 88], + [5, 65, 41, 5, 66, 42], + [5, 54, 24, 7, 55, 25], + [11, 36, 12], + + // 16 + [5, 122, 98, 1, 123, 99], + [7, 73, 45, 3, 74, 46], + [15, 43, 19, 2, 44, 20], + [3, 45, 15, 13, 46, 16], + + // 17 + [1, 135, 107, 5, 136, 108], + [10, 74, 46, 1, 75, 47], + [1, 50, 22, 15, 51, 23], + [2, 42, 14, 17, 43, 15], + + // 18 + [5, 150, 120, 1, 151, 121], + [9, 69, 43, 4, 70, 44], + [17, 50, 22, 1, 51, 23], + [2, 42, 14, 19, 43, 15], + + // 19 + [3, 141, 113, 4, 142, 114], + [3, 70, 44, 11, 71, 45], + [17, 47, 21, 4, 48, 22], + [9, 39, 13, 16, 40, 14], + + // 20 + [3, 135, 107, 5, 136, 108], + [3, 67, 41, 13, 68, 42], + [15, 54, 24, 5, 55, 25], + [15, 43, 15, 10, 44, 16], + + // 21 + [4, 144, 116, 4, 145, 117], + [17, 68, 42], + [17, 50, 22, 6, 51, 23], + [19, 46, 16, 6, 47, 17], + + // 22 + [2, 139, 111, 7, 140, 112], + [17, 74, 46], + [7, 54, 24, 16, 55, 25], + [34, 37, 13], + + // 23 + [4, 151, 121, 5, 152, 122], + [4, 75, 47, 14, 76, 48], + [11, 54, 24, 14, 55, 25], + [16, 45, 15, 14, 46, 16], + + // 24 + [6, 147, 117, 4, 148, 118], + [6, 73, 45, 14, 74, 46], + [11, 54, 24, 16, 55, 25], + [30, 46, 16, 2, 47, 17], + + // 25 + [8, 132, 106, 4, 133, 107], + [8, 75, 47, 13, 76, 48], + [7, 54, 24, 22, 55, 25], + [22, 45, 15, 13, 46, 16], + + // 26 + [10, 142, 114, 2, 143, 115], + [19, 74, 46, 4, 75, 47], + [28, 50, 22, 6, 51, 23], + [33, 46, 16, 4, 47, 17], + + // 27 + [8, 152, 122, 4, 153, 123], + [22, 73, 45, 3, 74, 46], + [8, 53, 23, 26, 54, 24], + [12, 45, 15, 28, 46, 16], + + // 28 + [3, 147, 117, 10, 148, 118], + [3, 73, 45, 23, 74, 46], + [4, 54, 24, 31, 55, 25], + [11, 45, 15, 31, 46, 16], + + // 29 + [7, 146, 116, 7, 147, 117], + [21, 73, 45, 7, 74, 46], + [1, 53, 23, 37, 54, 24], + [19, 45, 15, 26, 46, 16], + + // 30 + [5, 145, 115, 10, 146, 116], + [19, 75, 47, 10, 76, 48], + [15, 54, 24, 25, 55, 25], + [23, 45, 15, 25, 46, 16], + + // 31 + [13, 145, 115, 3, 146, 116], + [2, 74, 46, 29, 75, 47], + [42, 54, 24, 1, 55, 25], + [23, 45, 15, 28, 46, 16], + + // 32 + [17, 145, 115], + [10, 74, 46, 23, 75, 47], + [10, 54, 24, 35, 55, 25], + [19, 45, 15, 35, 46, 16], + + // 33 + [17, 145, 115, 1, 146, 116], + [14, 74, 46, 21, 75, 47], + [29, 54, 24, 19, 55, 25], + [11, 45, 15, 46, 46, 16], + + // 34 + [13, 145, 115, 6, 146, 116], + [14, 74, 46, 23, 75, 47], + [44, 54, 24, 7, 55, 25], + [59, 46, 16, 1, 47, 17], + + // 35 + [12, 151, 121, 7, 152, 122], + [12, 75, 47, 26, 76, 48], + [39, 54, 24, 14, 55, 25], + [22, 45, 15, 41, 46, 16], + + // 36 + [6, 151, 121, 14, 152, 122], + [6, 75, 47, 34, 76, 48], + [46, 54, 24, 10, 55, 25], + [2, 45, 15, 64, 46, 16], + + // 37 + [17, 152, 122, 4, 153, 123], + [29, 74, 46, 14, 75, 47], + [49, 54, 24, 10, 55, 25], + [24, 45, 15, 46, 46, 16], + + // 38 + [4, 152, 122, 18, 153, 123], + [13, 74, 46, 32, 75, 47], + [48, 54, 24, 14, 55, 25], + [42, 45, 15, 32, 46, 16], + + // 39 + [20, 147, 117, 4, 148, 118], + [40, 75, 47, 7, 76, 48], + [43, 54, 24, 22, 55, 25], + [10, 45, 15, 67, 46, 16], + + // 40 + [19, 148, 118, 6, 149, 119], + [18, 75, 47, 31, 76, 48], + [34, 54, 24, 34, 55, 25], + [20, 45, 15, 61, 46, 16] + ]; + + QRRSBlock.getRSBlocks = function(typeNumber, errorCorrectLevel) { + + var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel); + + if (rsBlock == undefined) { + throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + + errorCorrectLevel); + } + + var length = rsBlock.length / 3; + + var list = new Array(); + + for (var i = 0; i < length; i++) { + + var count = rsBlock[i * 3 + 0]; + var totalCount = rsBlock[i * 3 + 1]; + var dataCount = rsBlock[i * 3 + 2]; + + for (var j = 0; j < count; j++) { + list.push(new QRRSBlock(totalCount, dataCount)); + } + } + + return list; + } + + QRRSBlock.getRsBlockTable = function(typeNumber, errorCorrectLevel) { + + switch (errorCorrectLevel) { + case QRErrorCorrectLevel.L: + return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0]; + case QRErrorCorrectLevel.M: + return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1]; + case QRErrorCorrectLevel.Q: + return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2]; + case QRErrorCorrectLevel.H: + return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3]; + default: + return undefined; + } + } + + //--------------------------------------------------------------------- + // QRBitBuffer + //--------------------------------------------------------------------- + + function QRBitBuffer() { + this.buffer = new Array(); + this.length = 0; + } + + QRBitBuffer.prototype = { + + get: function(index) { + var bufIndex = Math.floor(index / 8); + return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) == 1; + }, + + put: function(num, length) { + for (var i = 0; i < length; i++) { + this.putBit(((num >>> (length - i - 1)) & 1) == 1); + } + }, + + getLengthInBits: function() { + return this.length; + }, + + putBit: function(bit) { + + var bufIndex = Math.floor(this.length / 8); + if (this.buffer.length <= bufIndex) { + this.buffer.push(0); + } + + if (bit) { + this.buffer[bufIndex] |= (0x80 >>> (this.length % 8)); + } + + this.length++; + } + }; + + //--------------------------------------------------------------------- + // Support Chinese 字符编码支持中文 + // 使用mode 4 8bit + //--------------------------------------------------------------------- + function utf16To8(text) { + var result = ''; + var c; + for (var i = 0; i < text.length; i++) { + c = text.charCodeAt(i); + if (c >= 0x0001 && c <= 0x007F) { + result += text.charAt(i); + } else if (c > 0x07FF) { + result += String.fromCharCode(0xE0 | c >> 12 & 0x0F); + result += String.fromCharCode(0x80 | c >> 6 & 0x3F); + result += String.fromCharCode(0x80 | c >> 0 & 0x3F); + } else { + result += String.fromCharCode(0xC0 | c >> 6 & 0x1F); + result += String.fromCharCode(0x80 | c >> 0 & 0x3F); + } + } + return result; + } + + /** + * 队列 + */ + class Queue { + constructor() { + let waitingQueue = []; + let isRunning = false; //记录是否有未完成的任务 + function execute(task, resolve, reject) { + task() + .then((data) => { + resolve(data); + }) + .catch((e) => { + reject(e); + }) + .finally(() => { + //等待任务队列中如果有任务,则触发它;否则设置isRunning = false,表示无任务状态 + if (waitingQueue.length) { + const next = waitingQueue.shift(); + execute(next.task, next.resolve, next.reject); + } else { + isRunning = false; + } + }); + } + return function(task) { + return new Promise((resolve, reject) => { + if (isRunning) { + waitingQueue.push({ + task, + resolve, + reject + }); + } else { + isRunning = true; + execute(task, resolve, reject); + } + }); + }; + } + } + // const queue = new Queue(); + // queue(() => new Promise((resolve, reject) => { + // setTimeout(() => { + // resolve('task1'); + // }, 1000); + // })).then(data => console.log(data)); + // queue(() => new Promise((resolve, reject) => { + // setTimeout(() => { + // resolve('task2'); + // }, 100); + // })).then(data => console.log(data)); + // queue(() => new Promise((resolve, reject) => { + // setTimeout(() => { + // resolve('task3'); + // }, 300); + // })).then(data => console.log(data)); + + /** + * 纠错等级 + */ + uQRCode.errorCorrectLevel = QRErrorCorrectLevel; + + /** + * 预设默认值(基本,不包含各部分和艺术码参数) + */ + uQRCode.defaults = { + typeNumber: -1, // 版本,-1为自动计算,字符越多,版本越高 + errorCorrectLevel: QRErrorCorrectLevel.H, // 纠错等级 + text: '', // 二维码内容 + size: 354, // 大小 + useDynamicSize: false, // 使用动态尺寸,可以去掉方块小数点,绘制出来后没有白色细线 + margin: 0, // 边距 + background: { + color: '#FFFFFF' // 背景色 + }, + foreground: { + color: '#000000' // 前景色 + } + } + + /** + * 对象属性深度替换 + * @param {Object} o 原始对象/默认对象/被替换的对象 + * @param {Object} r 从这个对象里取值替换到o对象里 + * @return {Object} 替换后的新对象 + */ + uQRCode.deepReplace = function(o = {}, r = {}) { + let obj = { + ...o + } + for (let k in r) { + var vr = r[k]; + if (vr.constructor == Object) { + obj[k] = this.deepReplace(obj[k], vr); + } else if (vr.constructor == String && !vr) { + obj[k] = obj[k]; + } else { + obj[k] = vr; + } + } + return obj; + } + + /** + * 获取选项值 + */ + uQRCode.getOptions = function(options) { + options = uQRCode.deepReplace(uQRCode.defaults, options); + + /* 背景 */ + options.background = uQRCode.deepReplace({ + color: options.background.color, // 背景色 + image: { + src: '', + width: 1, // 图片宽 + height: 1, // 图片高 + align: ['center', 'center'], // 图片对齐方式水平,垂直 + anchor: [0, 0], // 图片位置,X坐标,Y坐标 + alpha: 1 // 透明度 + } + }, options.background); + /* 前景 */ + options.foreground = uQRCode.deepReplace({ + color: options.foreground.color, // 前景色 + image: { + src: '', + width: 1 / 4, // 图片宽 + height: 1 / 4, // 图片高 + align: ['center', 'center'], // 图片对齐方式水平,垂直 + anchor: [0, 0] // 图片位置,X坐标,Y坐标 + } + }, options.foreground); + /* 定位角 */ + options.positionDetection = uQRCode.deepReplace({ + backgroundColor: options.background.color, // 定位角区域背景色,默认值跟随背景色 + foregroundColor: options.foreground.color // 定位角小块颜色,默认值跟随前景色 + }, options.positionDetection); + /* 分割图案 */ + options.separator = uQRCode.deepReplace({ + color: options.background.color // 分割区域颜色,默认值跟随背景色 + }, options.separator); + /* 对齐图案 */ + options.alignment = uQRCode.deepReplace({ + backgroundColor: options.background.color, // 对齐区域背景色,默认值跟随背景色 + foregroundColor: options.foreground.color // 对齐小块颜色,默认值跟随前景色 + }, options.alignment); + /* 时序图案 */ + options.timing = uQRCode.deepReplace({ + backgroundColor: options.background.color, // 时序区域背景色,默认值跟随背景色 + foregroundColor: options.foreground.color // 时序小块颜色,默认值跟随前景色 + }, options.timing); + /* 暗块 */ + options.darkBlock = uQRCode.deepReplace({ + color: options.foreground.color // 暗块颜色 + }, options.darkBlock); + /* 版本信息 */ + options.versionInformation = uQRCode.deepReplace({ + backgroundColor: options.background.color, // 版本信息区域背景色,默认值跟随背景色 + foregroundColor: options.foreground.color // 版本信息小块颜色,默认值跟随前景色 + }, options.versionInformation); + + return options; + } + + /** + * 获取canvas实例 + */ + uQRCode.getCanvasContext = function(ctx) { + /* 兼容setFillStyle写法,主要在uni-app nvue gcanvas */ + ctx.setFillStyle = ctx.setFillStyle || function(color) { + ctx.fillStyle = color; + } + /* 兼容setFontSize写法,主要在微信小程序canvas2d */ + ctx.setFontSize = ctx.setFontSize || function(fontSize) { + ctx.font = `${fontSize}px`; + } + /* 兼容setTextAlign写法,主要在微信小程序canvas2d */ + ctx.setTextAlign = ctx.setTextAlign || function(align) { + ctx.textAlign = align; + } + /* 兼容setTextBaseline写法,主要在微信小程序canvas2d */ + ctx.setTextBaseline = ctx.setTextBaseline || function(textBaseline) { + ctx.textBaseline = textBaseline; + } + /* 若实例不包含draw方法则创建一个 */ + ctx.draw = ctx.draw || function(reserve, callback) { + callback && callback(); + } + return ctx; + } + + /* 队列实例,某些平台一起使用多个组件时需要通过队列逐一绘制,否则部分绘制方法异常,nvue端的iOS gcanvas尤其明显,在不通过队列绘制时会出现图片丢失的情况 */ + uQRCode.Queue = new Queue(); + uQRCode.QueueLoadImage = new Queue(); + + /* 缓存loadImage图片 */ + uQRCode.loadImageCache = []; + + /** + * 获取加载图片方法 + */ + uQRCode.getLoadImage = function(loadImage) { + if (typeof loadImage == 'function') { + return function(src) { + /* 解决iOS APP||NVUE同时绘制多个二维码导致图片丢失需使用队列 */ + return uQRCode.QueueLoadImage(() => new Promise((resolve, reject) => { + setTimeout(() => { + const cache = uQRCode.loadImageCache.find(x => x.src == src); + if (cache) { + resolve(cache.img); + } else { + loadImage(src).then(img => { + uQRCode.loadImageCache.push({ + src, + img + }); + resolve(img); + }); + } + }, 150); + })); + } + } else { + return function(src) { + return Promise.resolve(src); + } + } + } + + uQRCode.prototype = { + /** + * 实例化传入的选项值 + */ + options: {}, + + /** + * 画布实例 + */ + canvasContext: {}, + + /** + * 制作二维码全部数据 + */ + makeData: {}, + + /** + * 制作二维码主要模块数据,基于makeData的modules但数据格式不一致,这里的modules是定制过的 + */ + modules: [], + + /** + * 模块数量 + */ + moduleCount: 0, + + /** + * 获取制作二维码数据 + */ + getMakeData() { + let { + typeNumber, + errorCorrectLevel, + text + } = this.options; + var qrcode = new QRCode(typeNumber, errorCorrectLevel); + qrcode.addData(utf16To8(text.toString())); + qrcode.make(); + return qrcode; + }, + + /** + * 制作二维码方法 + */ + make() { + let makeData = this.makeData = this.getMakeData(); + this.modules = JSON.parse(JSON.stringify(makeData.modules)); + this.moduleCount = makeData.moduleCount; + this.options.typeNumber = makeData.typeNumber; + + /* 数据码 data */ + this.paintData(); + /* 定位图案 position detection */ + this.paintPositionDetection(); + /* 分隔图案 separator */ + this.paintSeparator(); + /* 对齐图案 alignment */ + this.paintAlignment(); + /* 时序图案 timing */ + this.paintTiming(); + /* 暗块 darkBlock */ + this.paintDarkBlock(); + /* 预留版本信息 version information */ + this.paintVersionInformation(); + }, + + paintData() { + let modules = this.modules; + let moduleCount = this.moduleCount; + let { + size, + margin, + background, + foreground, + useDynamicSize + } = this.options; + + /* dynamicSize自动计算出最适合绘制的尺寸,并按这个尺寸去绘制,可以解决canvas绘制小块间产生白线的问题(其实就是小数点精度问题),useDynamicSize=false可以取消这个设定 */ + // let dynamicSize = this.options.dynamicSize = Math.floor((size - margin * 2) / moduleCount) * moduleCount + margin * 2; // Math.floor向下取整缩放会模糊 + let dynamicSize = this.options.dynamicSize = Math.ceil((size - margin * 2) / moduleCount) * moduleCount + margin * 2; // Math.ceil向上取整缩放效果比floor清晰 + if (!useDynamicSize) { + dynamicSize = this.options.dynamicSize = size; + } + let tileSize = (dynamicSize - margin * 2) / moduleCount; + + for (var rowI = 0; rowI < modules.length; rowI++) { + for (var colI = 0; colI < modules.length; colI++) { + var tile = modules[rowI][colI]; + if (tile) { + modules[rowI][colI] = { + size: tileSize, + x: colI * tileSize + margin, + y: rowI * tileSize + margin, + type: ['foreground'], + color: foreground.color, + isBlack: true, + isDrawn: false + }; + } else { + modules[rowI][colI] = { + size: tileSize, + x: colI * tileSize + margin, + y: rowI * tileSize + margin, + type: ['background'], + color: background.color, + isBlack: false, + isDrawn: false + }; + } + } + } + }, + + paintPositionDetection() { + let modules = this.modules; + let size = this.moduleCount; + let { + positionDetection + } = this.options; + + //1) 定义基础图形索引(左上角)x ,y,v + let basePart = [ + [0, 0, 1], + [1, 0, 1], + [2, 0, 1], + [3, 0, 1], + [4, 0, 1], + [5, 0, 1], + [6, 0, 1], + [0, 1, 1], + [1, 1, 0], + [2, 1, 0], + [3, 1, 0], + [4, 1, 0], + [5, 1, 0], + [6, 1, 1], + [0, 2, 1], + [1, 2, 0], + [2, 2, 1], + [3, 2, 1], + [4, 2, 1], + [5, 2, 0], + [6, 2, 1], + [0, 3, 1], + [1, 3, 0], + [2, 3, 1], + [3, 3, 1], + [4, 3, 1], + [5, 3, 0], + [6, 3, 1], + [0, 4, 1], + [1, 4, 0], + [2, 4, 1], + [3, 4, 1], + [4, 4, 1], + [5, 4, 0], + [6, 4, 1], + [0, 5, 1], + [1, 5, 0], + [2, 5, 0], + [3, 5, 0], + [4, 5, 0], + [5, 5, 0], + [6, 5, 1], + [0, 6, 1], + [1, 6, 1], + [2, 6, 1], + [3, 6, 1], + [4, 6, 1], + [5, 6, 1], + [6, 6, 1] + ]; + let disc = size - 7; //size -7 + basePart.forEach(d => { + var ltItem = modules[d[0]][d[1]]; + var rtItem = modules[d[0] + disc][d[1]]; + var lbItem = modules[d[0]][d[1] + disc]; + lbItem.type.push('positionDetection'); + rtItem.type.push('positionDetection'); + ltItem.type.push('positionDetection'); + //绘制左上角 + ltItem.color = d[2] == 1 ? positionDetection.foregroundColor : positionDetection.backgroundColor; + //绘制右 + rtItem.color = d[2] == 1 ? positionDetection.foregroundColor : positionDetection.backgroundColor; + //绘制左 + lbItem.color = d[2] == 1 ? positionDetection.foregroundColor : positionDetection.backgroundColor; + }); + }, + + paintSeparator() { + let modules = this.modules; + let size = this.moduleCount; + let { + separator + } = this.options; + + //1) 定义基础图形索引(左上角) + [ + [7, 0], + [7, 1], + [7, 2], + [7, 3], + [7, 4], + [7, 5], + [7, 6], + [7, 7], + [0, 7], + [1, 7], + [2, 7], + [3, 7], + [4, 7], + [5, 7], + [6, 7] + ].forEach(d => { + var ltItem = modules[d[0]][d[1]]; + var rtItem = modules[size - d[0] - 1][d[1]]; + var lbItem = modules[d[0]][size - d[1] - 1]; + lbItem.type.push('separator'); + rtItem.type.push('separator'); + ltItem.type.push('separator'); + //绘制左上 + ltItem.color = separator.color; + //绘制右 + rtItem.color = separator.color; + //绘制左 + lbItem.color = separator.color; + }); + }, + + paintAlignment() { + let modules = this.modules; + let size = this.moduleCount; + let { + alignment, + typeNumber + } = this.options; + + //不同版本的对齐图案组合位置 + const ALIGNMENT_OF_VERSION = [ + [], + [6, 18], + [6, 22], + [6, 26], + [6, 30], + [6, 34], + [6, 22, 38], + [6, 24, 42], + [6, 26, 46], + [6, 28, 50], + [6, 30, 54], + [6, 32, 58], + [6, 34, 62], + [6, 26, 46, 66], + [6, 26, 48, 70], + [6, 26, 50, 74], + [6, 30, 54, 78], + [6, 30, 56, 82], + [6, 30, 58, 86], + [6, 34, 62, 90], + [6, 28, 50, 72, 94], + [6, 26, 50, 74, 98], + [6, 30, 54, 78, 102], + [6, 28, 54, 80, 106], + [6, 32, 58, 84, 110], + [6, 30, 58, 86, 114], + [6, 34, 62, 90, 118], + [6, 26, 50, 74, 98, 122], + [6, 30, 54, 78, 102, 126], + [6, 26, 52, 78, 104, 130], + [6, 30, 56, 82, 108, 134], + [6, 34, 60, 86, 112, 138], + [6, 30, 58, 86, 114, 142], + [6, 34, 62, 90, 118, 146], + [6, 30, 54, 78, 102, 126, 150], + [6, 24, 50, 76, 102, 128, 154], + [6, 28, 54, 80, 106, 132, 158], + [6, 32, 58, 84, 110, 136, 162], + [6, 26, 54, 82, 110, 138, 166], + [6, 30, 58, 86, 114, 142, 170] + ]; + // 对齐图案数量和中心位置根据版本定义 + const alignments = ALIGNMENT_OF_VERSION[typeNumber - 1]; + if (alignments) { + const calcMatrix = [ + [-2, -2, 1], + [-1, -2, 1], + [0, -2, 1], + [1, -2, 1], + [2, -2, 1], + [-2, -1, 1], + [-1, -1, 0], + [0, -1, 0], + [1, -1, 0], + [2, -1, 1], + [-2, 0, 1], + [-1, 0, 0], + [0, 0, 1], + [1, 0, 0], + [2, 0, 1], + [-2, 1, 1], + [-1, 1, 0], + [0, 1, 0], + [1, 1, 0], + [2, 1, 1], + [-2, 2, 1], + [-1, 2, 1], + [0, 2, 1], + [1, 2, 1], + [2, 2, 1] + ]; + const group_len = alignments.length; + for (let i = 0; i < group_len; i++) { + for (let j = 0; j < group_len; j++) { + //对齐图案不能污染 定位器和分隔器 + let { + x, + y + } = { + x: alignments[i], + y: alignments[j] + }; + if (!((x < 9 && y < 9) || (x > size - 9 - 1 && y < 9) || (y > size - 9 - 1 && x < 9))) { + calcMatrix.forEach(d => { + var alignmentItem = modules[x + d[0]][y + d[1]]; + alignmentItem.type.push('alignment'); + alignmentItem.color = d[2] == 1 ? alignment.foregroundColor : alignment.backgroundColor; + }); + } + } + } + } + }, + + paintTiming() { + let modules = this.modules; + let { + timing + } = this.options; + + let timingPartLen = modules.length - 16; + for (let i = 0; i < timingPartLen; i++) { + var xItem = modules[6][8 + i]; + var yItem = modules[8 + i][6]; + xItem.type.push('timing'); + yItem.type.push('timing'); + xItem.color = (1 & i) ^ 1 ? timing.foregroundColor : timing.backgroundColor; + yItem.color = (1 & i) ^ 1 ? timing.foregroundColor : timing.backgroundColor; + } + }, + + paintDarkBlock() { + let modules = this.modules; + let size = this.moduleCount; + let { + darkBlock + } = this.options; + + //创建暗模块 + var darkBlockItem = modules[size - 7 - 1][8]; + darkBlockItem.type.push('darkBlock'); + darkBlockItem.color = darkBlock.color; + }, + + paintVersionInformation() { + let modules = this.modules; + let size = this.moduleCount; + let { + versionInformation, + typeNumber: version + } = this.options; + + if (version < 7) { + return modules; + } + //预留版本信息 0 为补位,预留版本信息 是从索引7开始 + const VERSIONS = [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + '000111110010010100', + '001000010110111100', + '001001101010011001', + '001010010011010011', + '001011101111110110', + '001100011101100010', + '001101100001000111', + '001110011000001101', + '001111100100101000', + '010000101101111000', + '010001010001011101', + '010010101000010111', + '010011010100110010', + '010100100110100110', + '010101011010000011', + '010110100011001001', + '010111011111101100', + '011000111011000100', + '011001000111100001', + '011010111110101011', + '011011000010001110', + '011100110000011010', + '011101001100111111', + '011110110101110101', + '011111001001010000', + '100000100111010101', + '100001011011110000', + '100010100010111010', + '100011011110011111', + '100100101100001011', + '100101010000101110', + '100110101001100100', + '100111010101000001', + '101000110001101001' + ]; + + //两种方式获取预留格式信息,临时计算或者查字典 + //let version_codes = _v.correctVersionData(_v.version); + let version_codes = VERSIONS[version] + VERSIONS[version]; + //创建预留版本信息 + let disc = [size - 11, size - 10, size - 9]; + // 左+右 + let version_cells = [ + //左 + [5, disc[2]], + [5, disc[1]], + [5, disc[0]], + [4, disc[2]], + [4, disc[1]], + [4, disc[0]], + [3, disc[2]], + [3, disc[1]], + [3, disc[0]], + [2, disc[2]], + [2, disc[1]], + [2, disc[0]], + [1, disc[2]], + [1, disc[1]], + [1, disc[0]], + [0, disc[2]], + [0, disc[1]], + [0, disc[0]], + //右 + [disc[2], 5], + [disc[1], 5], + [disc[0], 5], + [disc[2], 4], + [disc[1], 4], + [disc[0], 4], + [disc[2], 3], + [disc[1], 3], + [disc[0], 3], + [disc[2], 2], + [disc[1], 2], + [disc[0], 2], + [disc[2], 1], + [disc[1], 1], + [disc[0], 1], + [disc[2], 0], + [disc[1], 0], + [disc[0], 0] + ]; + version_cells.forEach((d, index) => { + var versionInformationItem = modules[d[0]][d[1]]; + versionInformationItem.type.push('versionInformation'); + versionInformationItem.color = version_codes[index] == '1' ? versionInformation.foregroundColor : versionInformation.backgroundColor; + }); + }, + + /** + * 绘制二维码方法 + */ + draw(options) { + options = uQRCode.deepReplace({ + drawBackground: { + before: () => {}, + after: () => {} + }, + drawBackgroundImage: { + before: () => {}, + after: () => {} + }, + drawForeground: { + before: () => {}, + after: () => {} + }, + drawForegroundImage: { + before: () => {}, + after: () => {} + } + }, options); + + /* 绘制层级关系,最底层背景 -> 背景图片 -> 前景 -> 最顶层前景图片 */ + return new Promise((resolve, reject) => { + let ctx = this.canvasContext; + + const startup = () => { + /* 同时绘制多个二维码时使用队列绘制,防止内部方法冲突导致绘制失败 */ + return uQRCode.Queue(() => new Promise((queueResolve, queueReject) => { + setTimeout(() => { + ctx.draw(false); // 第一个draw false可以清空画布 + queueResolve(); + }, 150); + })); + } + startup() + .then(() => { + /* 绘制背景 */ + return this.drawBackground({ + before: options.drawBackground.before, + after: options.drawBackground.after + }); + }) + .then(() => { + /* 绘制背景图片 */ + return this.drawBackgroundImage({ + before: options.drawBackgroundImage.before, + after: options.drawBackgroundImage.after + }); + }) + .then(() => { + /* 绘制前景 */ + return this.drawForeground({ + before: options.drawForeground.before, + after: options.drawForeground.after + }); + }) + .then(() => { + /* 绘制前景图片 */ + return this.drawForegroundImage({ + before: options.drawForegroundImage.before, + after: options.drawForegroundImage.after + }); + }) + .then(() => { + /* 完成绘制 */ + resolve(); + }); + }); + }, + + drawBackground({ + before, + after + }) { + let { + dynamicSize: size, + background + } = this.options; + let ctx = this.canvasContext; + + return new Promise((resolve, reject) => { + (async () => { + await before(this); + + ctx.save(); + /* 填充背景色 */ + ctx.setFillStyle(background.color); + ctx.fillRect(0, 0, size, size); + ctx.restore(); + ctx.draw(true); // gcanvas需要每一阶段都draw一下,否则重绘有问题,例如uni-app nvue绘制图片会失败 + + await after(this); + resolve(); + })(); + }); + }, + + drawBackgroundImage({ + before, + after + }) { + let { + dynamicSize: size, + background + } = this.options; + let ctx = this.canvasContext; + + return new Promise((resolve, reject) => { + (async () => { + await before(this); + + if (background.image.src) { + ctx.save(); + + let x = 0; + let y = 0; + + let w = background.image.width * size; + let h = background.image.height * size; + let align = background.image.align; + let anchor = background.image.anchor; + let alpha = background.image.alpha; + + switch (align[0]) { + case 'left': + x = 0; + break; + case 'center': + x = size / 2 - w / 2; + break; + case 'right': + x = size - w; + break; + } + x += Number(anchor[0]); + + switch (align[1]) { + case 'top': + y = 0; + break; + case 'center': + y = size / 2 - h / 2; + break; + case 'bottom': + y = size - h; + break; + } + y += Number(anchor[1]); + + /* 设置透明度 */ + ctx.globalAlpha = alpha; + + /* 绘制图片 */ + const img = await this.loadImage(background.image.src); + ctx.drawImage(img, x, y, w, h); + ctx.restore(); + ctx.draw(true); // gcanvas需要每一阶段都draw一下,否则重绘有问题,例如uni-app nvue绘制图片会失败 + } + + await after(this); + resolve(); + })(); + }); + }, + + drawForeground({ + before, + after + }) { + let { + background + } = this.options; + let modules = this.modules; + let moduleCount = this.moduleCount; + let ctx = this.canvasContext; + + return new Promise((resolve, reject) => { + (async () => { + await before(this); + + ctx.save(); + for (var rowI = 0; rowI < moduleCount; rowI++) { + for (var colI = 0; colI < moduleCount; colI++) { + var tile = modules[rowI][colI]; + if (!tile.isDrawn && tile.color != background.color) { // 颜色不能与背景色一致,否则可能发生颜色重叠 + var color = tile.color; + ctx.setFillStyle(color); + ctx.fillRect(tile.x, tile.y, tile.size, tile.size); + tile.isDrawn = true; + } + } + } + ctx.restore(); + ctx.draw(true); // gcanvas需要每一阶段都draw一下,否则重绘有问题,例如uni-app nvue绘制图片会失败 + + await after(this); + resolve(); + })(); + }); + }, + + drawForegroundImage({ + before, + after + }) { + let { + dynamicSize: size, + foreground + } = this.options; + let ctx = this.canvasContext; + + return new Promise((resolve, reject) => { + (async () => { + await before(this); + + if (foreground.image.src) { + ctx.save(); + + // 绘制前景图 + let x = 0; + let y = 0; + + let w = foreground.image.width * size; + let h = foreground.image.height * size; + let align = foreground.image.align; + let anchor = foreground.image.anchor; + let alpha = foreground.image.alpha; + let shadow = foreground.image.shadow; + let border = foreground.image.border; + + switch (align[0]) { + case 'left': + x = 0; + break; + case 'center': + x = size / 2 - w / 2; + break; + case 'right': + x = size - w; + break; + } + x += Number(anchor[0]); + + switch (align[1]) { + case 'top': + y = 0; + break; + case 'center': + y = size / 2 - h / 2; + break; + case 'bottom': + y = size - h; + break; + } + y += Number(anchor[1]); + + /* 绘制图片 */ + const img = await this.loadImage(foreground.image.src); + ctx.drawImage(img, x, y, w, h); + ctx.restore(); + ctx.draw(true); // gcanvas需要每一阶段都draw一下,否则重绘有问题,例如uni-app nvue绘制图片会失败 + } + + await after(this); + resolve(); + })(); + }); + } + + } + +})(); + +module.exports = uQRCode; diff --git a/uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/package.json b/uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/package.json new file mode 100644 index 0000000..86328da --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/package.json @@ -0,0 +1,24 @@ +{ + "name": "u-qrcode", + "version": "3.2.2", + "description": "uQRCode 二维码生成插件", + "main": "u-qrcode.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Sansnn/uQRCode.git" + }, + "keywords": [ + "QR", + "QRCode", + "uQRCode" + ], + "author": "Sansnn", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/Sansnn/uQRCode/issues" + }, + "homepage": "https://github.com/Sansnn/uQRCode#readme" +} diff --git a/uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/readme.md b/uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/readme.md new file mode 100644 index 0000000..e5935be --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/readme.md @@ -0,0 +1,274 @@ +# uQRCode + +**点击群号加入群聊【uQRCode交流群】:[695070434](https://jq.qq.com/?_wv=1027&k=JRjzDqiw)** + +uQRCode 生成方式简单,可扩展性高,适用所有前端应用和Node.js服务端,可运行到所有支持canvas的平台。支持NVUE(NVUE中使用GCanvas)。 + +支持自定义二维码渲染规则,可通过uQRCode API得到矩阵信息后,自行实现canvas或view+css渲染二维码,如随机颜色、圆点、方块、块与块之间的间距等,详情参考示例项目。 + +### 插件市场 +[https://ext.dcloud.net.cn/plugin?id=1287](https://ext.dcloud.net.cn/plugin?id=1287) + +### github +[https://github.com/Sansnn/uQRCode](https://github.com/Sansnn/uQRCode) + +### npm +[https://www.npmjs.com/package/u-qrcode](https://www.npmjs.com/package/u-qrcode) + +### 示例预览 +[https://static-c15f4b57-ef97-4d2b-b939-f580f910d7e2.bspapp.com](https://static-c15f4b57-ef97-4d2b-b939-f580f910d7e2.bspapp.com) + +### 二维码 +**什么是QR码** + +QR码属于矩阵式二维码中的一个种类,由DENSO(日本电装)公司开发,由JIS和ISO将其标准化。 + +**QR码的特点** + +一是高速读取(QR就是取自“Quick Response”的首字母),通过摄像头从拍摄到解码到显示内容也就三秒左右,对摄像的角度也没有什么要求; + +二是高容量、高密度,理论上内容经过压缩处理后可以存7089个数字,4296个字母和数字混合字符,2953个8位字节数据,1817个汉字; + +三是支持纠错处理,按照QR码的标准文档说明,QR码的纠错分为4个级别,分别是: +- level L : 最大 7% 的错误能够被纠正; +- level M : 最大 15% 的错误能够被纠正; +- level Q : 最大 25% 的错误能够被纠正; +- level H : 最大 30% 的错误能够被纠正; + +四是结构化,看似无规则的图形,其实对区域有严格的定义。 + +更多二维码介绍及原理:[https://blog.csdn.net/jason_ldh/article/details/11801355](https://blog.csdn.net/jason_ldh/article/details/11801355) + +### 组件使用 + +导入`u-qrcode`组件后,在 `template` 中创建 `` 组件 + +```html + +``` + +### 属性说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|canvasId |String |- |- |是 |组件标识/canvasId | +|value |String |- |- |是 |二维码内容 | +|size |Number |- |354 |否 |二维码大小,默认单位px,rpx需要使用uni.upx2px()转换| +|options |Object |- |- |否 |参数可选项,详见下方options说明 | + +### 事件说明 +|事件名 |参数 |返回值 |说明 | +|--- |--- |--- |:--- | +|click |- |void |点击事件 | +|complete |- |Object |生成完成事件,返回值success: true表示生成成功,false生成失败 | + +### 方法说明 +|方法名 |参数 |返回值 |说明 | +|--- |--- |--- |:--- | +|remake |- |void |重新生成 | +|toTempFilePath |Object:callback|void |导出临时路径 | +|save |Object:callback|void |保存 | + +#### options说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|typeNumber |Number |- |-1 |否 |二维码版本 | +|errorCorrectLevel |String/Number|L/M/Q/H/1/0/3/2|H |否 |纠错等级L/M/Q/H分别对应1/0/3/2 | +|useDynamicSize |Boolean |- |false |否 |是否使用动态尺寸,可以去除二维码小块白色细线 | +|margin |Number |- |0 |否 |填充边距,默认单位px | +|background |Object |- |- |否 |背景设置,详见下方options.background说明 | +|foreground |Object |- |- |否 |前景设置,详见下方options.foreground说明 | +|positionDetection |Object |- |- |否 |定位角设置,详见下方options.positionDetection说明 | +|separator |Object |- |- |否 |分割图案设置,详见下方options.separator说明 | +|alignment |Object |- |- |否 |对齐图案设置,详见下方options.alignment说明 | +|timing |Object |- |- |否 |时序图案设置,详见下方options.timing说明 | +|darkBlock |Object |- |- |否 |暗块设置,详见下方options.darkBlock说明 | +|versionInformation |Object |- |- |否 |版本信息设置,详见下方options.versionInformation说明 | + +#### options.background说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|color |String |- |#FFFFFF|否 |背景色,若需要透明背景可设置为rgba(0,0,0,0)| +|image |Object |- |- |否 |背景图片设置,详见下方options.background.image说明| + +#### options.background.image说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|src |String |- |- |否 |背景图片路径 | +|width |Number |- |1 |否 |指定背景图片宽度,1为二维码size的100% | +|height |Number |- |1 |否 |指定背景图片高度,1为二维码size的100% | +|align |Array|['left'/'center'/'right', 'top'/'center'/'bottom'] |['center', 'center'] |否 |指定背景图片对齐方式,[0]为水平方位,[1]为垂直方位 | +|anchor |Array|- |[0, 0] |否 |指定背景图片锚点,[0]为X轴偏移量,[1]为Y轴偏移量 | +|alpha |Number |0-1 |1 |否 |指定背景图片透明度 | + +#### options.foreground说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|color |String |- |#FFFFFF|否 |前景色 | +|image |Object |- |- |否 |前景图片设置,详见下方options.foreground.image说明 | + +#### options.foreground.image说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|src |String |- |- |否 |前景图片路径 | +|width |Number |- |1/4 |否 |指定前景图片宽度,1为二维码size的100% | +|height |Number |- |1/4 |否 |指定前景图片高度,1为二维码size的100% | +|align |Array|['left'/'center'/'right', 'top'/'center'/'bottom'] |['center', 'center'] |否 |指定前景图片对齐方式,[0]为水平方位,[1]为垂直方位 | +|anchor |Array|- |[0, 0] |否 |指定前景图片锚点,[0]为X轴偏移量,[1]为Y轴偏移量 | + +#### options.positionDetection说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|backgroundColor|String |- |options.background.color |否 |定位角区域背景色,默认值跟随背景色 | +|foregroundColor|String |- |options.foreground.color |否 |定位角小块颜色,默认值跟随前景色 | + +#### options.separator说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|color |String |- |options.background.color |否 |分割区域颜色,默认值跟随背景色 | + +#### options.alignment说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|backgroundColor|String |- |options.background.color |否 |对齐区域背景色,默认值跟随背景色 | +|foregroundColor|String |- |options.foreground.color |否 |对齐小块颜色,默认值跟随前景色 | + +#### options.timing说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|backgroundColor|String |- |options.background.color |否 |时序区域背景色,默认值跟随背景色 | +|foregroundColor|String |- |options.foreground.color |否 |时序小块颜色,默认值跟随前景色 | + +#### options.darkBlock说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|color |String |- |options.foreground.color |否 |暗块颜色,默认值跟随前景色 | + +#### options.versionInformation说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|backgroundColor|String |- |options.background.color |否 |版本信息区域背景色,默认值跟随背景色 | +|foregroundColor|String |- |options.foreground.color |否 |版本信息小块颜色,默认值跟随前景色 | + +### u-qrcode.js使用 + +引入u-qrcode.js + +``` javascript +import uQRCode from '../../uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode'; +``` + +或者使用npm安装 + +> npm i u-qrcode + +``` javascript +import uQRCode from 'u-qrcode'; +``` + +nodejs引入 + +``` javascript +import uQRCode from 'u-qrcode/module'; +``` + +在 `template` 中创建 `` 组件并设置 `id`,画布宽高 + +```html + +``` + +在 `script` 中调用生成方法 + +```javascript +import uQRCode from '../../uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode'; + +export default { + data() { + return { + text: 'uQRCode', + size: 256 + } + }, + onReady() { + const ctx = uni.createCanvasContext('qrcode'); + const uqrcode = new uQRCode( + { + text: this.text, + size: this.size + }, + ctx + ); + uqrcode.make(); + uqrcode.draw(); + } +} +``` + +### new uQRCode(options, canvasContext, loadImage)说明 + +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|options |Object |- |- |是 |包含组件属性中的options的所有属性,详见下方options说明 | +|canvasContext|Object |- |- |是 |canvas绘画上下文 | +|loadImage |Promise|- |- |否 |绘制图片时,某些平台必传,例如微信小程序2d绘图需要创建Image对象,不能直接使用路径,这时就需要传入canvas.createImage给loadImage方法,否则无法绘制图片 | + +#### options说明,包含组件属性中的options的所有属性,下方仅列举未包含的属性,其余属性请移步到组件属性options说明查看 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|text |String |- |- |是 |二维码内容 | +|size |Number |- |354 |否 |二维码大小 | + +### uQRCode实例属性 +|属性名 |类型 |说明 | +|--- |--- |:--- | +|options |Object |实例化传入的选项值 | +|canvasContext|Object |画布实例 | +|makeData |Object |制作二维码全部数据 | +|modules |Array |制作二维码主要模块数据 | +|moduleCount |Number |模块数量 | + +### uQRCode实例方法 +|方法名 |参数 |返回值 |说明 | +|--- |--- |--- |:--- | +|make |- |void |制作二维码方法 | +|draw |options|Promise|绘制二维码方法,绘制层级关系,最底层背景 -> 背景图片 -> 前景 -> 最顶层前景图片,options见下方说明 | + +#### draw(options)说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|drawBackground |Object: {before, after}|- |- |否 |绘制背景前后可执行自定义方法before,after | +|drawBackgroundImage|Object: {before, after}|- |- |否 |绘制背景图前后可执行自定义方法before,after| +|drawForeground |Object: {before, after}|- |- |否 |绘制前景前后可执行自定义方法before,after | +|drawForegroundImage|Object: {before, after}|- |- |否 |绘制前景图前后可执行自定义方法before,after| + +### uQRCode静态属性 +|属性名 |类型 |说明 | +|--- |--- |:--- | +|errorCorrectLevel|Object |纠错等级 | +|defaults |Object |预设默认值 | + +### uQRCode静态方法 +|方法名 |参数 |返回值 |说明 | +|--- |--- |--- |:--- | +|deepReplace|o, r |替换后的新对象 |对象属性深度替换 | + +### 常见问题 + +**如何扫码跳转指定网页** + +二维码内容直接放入完整的网页地址即可,例如:`https://ext.dcloud.net.cn/plugin?id=1287`。微信客户端不能是ip地址。 + +**nvue打包后生成失败** + +Canvas是作为独立的模块,打包时需要选择使用Canvas模块才能正常使用相关的功能。 需要在manifest.json的代码视图中配置如下(暂时还不支持可视化界面操作): +```javascript +"app-plus" : { + /* 模块配置 */ + "modules" : { + "Canvas" : "nvue canvas" //使用Canvas模块 + }, + //... +}, +//... +``` +保存好提交云端打包。 diff --git a/uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/u-qrcode.js b/uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/u-qrcode.js new file mode 100644 index 0000000..fa67ceb --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/u-qrcode.js @@ -0,0 +1,2285 @@ +//--------------------------------------------------------------------- +// uQRCode 二维码生成插件 v3.2.2 +// +// uQRCode 是一款使用方式简单,高扩展的二维码生成插件。支持全端生成,支持canvas的地方就可以使用uQRCode。 +// +// Copyright (c) Sansnn uQRCode All rights reserved. +// Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) +// 复制使用请保留本段注释,感谢支持开源! +// +// 开源地址: +// https://github.com/Sansnn/uQRCode +// +// uni-app插件市场地址: +// https://ext.dcloud.net.cn/plugin?id=1287 +//--------------------------------------------------------------------- + +"use strict"; + +function uQRCode(options, canvasContext, loadImage) { + this.options = uQRCode.getOptions(options); + this.canvasContext = uQRCode.getCanvasContext(canvasContext); + this.loadImage = uQRCode.getLoadImage(loadImage); +} + +(function() { + //--------------------------------------------------------------------- + // QRCode for JavaScript + // + // Copyright (c) 2009 Kazuhiko Arase + // + // URL: http://www.d-project.com/ + // + // Licensed under the MIT license: + // http://www.opensource.org/licenses/mit-license.php + // + // The word "QR Code" is registered trademark of + // DENSO WAVE INCORPORATED + // http://www.denso-wave.com/qrcode/faqpatent-e.html + // + //--------------------------------------------------------------------- + + //--------------------------------------------------------------------- + // QR8bitByte + //--------------------------------------------------------------------- + + function QR8bitByte(data) { + this.mode = QRMode.MODE_8BIT_BYTE; + this.data = data; + } + + QR8bitByte.prototype = { + + getLength: function(buffer) { + return this.data.length; + }, + + write: function(buffer) { + for (var i = 0; i < this.data.length; i++) { + // not JIS ... + buffer.put(this.data.charCodeAt(i), 8); + } + } + }; + + //--------------------------------------------------------------------- + // QRCode + //--------------------------------------------------------------------- + + function QRCode(typeNumber, errorCorrectLevel) { + this.typeNumber = typeNumber; + this.errorCorrectLevel = errorCorrectLevel; + this.modules = null; + this.moduleCount = 0; + this.dataCache = null; + this.dataList = new Array(); + } + + QRCode.prototype = { + + addData: function(data) { + var newData = new QR8bitByte(data); + this.dataList.push(newData); + this.dataCache = null; + }, + + isDark: function(row, col) { + if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) { + throw new Error(row + "," + col); + } + return this.modules[row][col]; + }, + + getModuleCount: function() { + return this.moduleCount; + }, + + make: function() { + // Calculate automatically typeNumber if provided is < 1 + if (this.typeNumber < 1) { + var typeNumber = 1; + for (typeNumber = 1; typeNumber < 40; typeNumber++) { + var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, this.errorCorrectLevel); + + var buffer = new QRBitBuffer(); + var totalDataCount = 0; + for (var i = 0; i < rsBlocks.length; i++) { + totalDataCount += rsBlocks[i].dataCount; + } + + for (var i = 0; i < this.dataList.length; i++) { + var data = this.dataList[i]; + buffer.put(data.mode, 4); + buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber)); + data.write(buffer); + } + if (buffer.getLengthInBits() <= totalDataCount * 8) + break; + } + this.typeNumber = typeNumber; + } + this.makeImpl(false, this.getBestMaskPattern()); + }, + + makeImpl: function(test, maskPattern) { + + this.moduleCount = this.typeNumber * 4 + 17; + this.modules = new Array(this.moduleCount); + + for (var row = 0; row < this.moduleCount; row++) { + + this.modules[row] = new Array(this.moduleCount); + + for (var col = 0; col < this.moduleCount; col++) { + this.modules[row][col] = null; //(col + row) % 3; + } + } + + this.setupPositionProbePattern(0, 0); + this.setupPositionProbePattern(this.moduleCount - 7, 0); + this.setupPositionProbePattern(0, this.moduleCount - 7); + this.setupPositionAdjustPattern(); + this.setupTimingPattern(); + this.setupTypeInfo(test, maskPattern); + + if (this.typeNumber >= 7) { + this.setupTypeNumber(test); + } + + if (this.dataCache == null) { + this.dataCache = QRCode.createData(this.typeNumber, this.errorCorrectLevel, this.dataList); + } + + this.mapData(this.dataCache, maskPattern); + }, + + setupPositionProbePattern: function(row, col) { + + for (var r = -1; r <= 7; r++) { + + if (row + r <= -1 || this.moduleCount <= row + r) continue; + + for (var c = -1; c <= 7; c++) { + + if (col + c <= -1 || this.moduleCount <= col + c) continue; + + if ((0 <= r && r <= 6 && (c == 0 || c == 6)) || + (0 <= c && c <= 6 && (r == 0 || r == 6)) || + (2 <= r && r <= 4 && 2 <= c && c <= 4)) { + this.modules[row + r][col + c] = true; + } else { + this.modules[row + r][col + c] = false; + } + } + } + }, + + getBestMaskPattern: function() { + + var minLostPoint = 0; + var pattern = 0; + + for (var i = 0; i < 8; i++) { + + this.makeImpl(true, i); + + var lostPoint = QRUtil.getLostPoint(this); + + if (i == 0 || minLostPoint > lostPoint) { + minLostPoint = lostPoint; + pattern = i; + } + } + + return pattern; + }, + + createMovieClip: function(target_mc, instance_name, depth) { + + var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth); + var cs = 1; + + this.make(); + + for (var row = 0; row < this.modules.length; row++) { + + var y = row * cs; + + for (var col = 0; col < this.modules[row].length; col++) { + + var x = col * cs; + var dark = this.modules[row][col]; + + if (dark) { + qr_mc.beginFill(0, 100); + qr_mc.moveTo(x, y); + qr_mc.lineTo(x + cs, y); + qr_mc.lineTo(x + cs, y + cs); + qr_mc.lineTo(x, y + cs); + qr_mc.endFill(); + } + } + } + + return qr_mc; + }, + + setupTimingPattern: function() { + + for (var r = 8; r < this.moduleCount - 8; r++) { + if (this.modules[r][6] != null) { + continue; + } + this.modules[r][6] = (r % 2 == 0); + } + + for (var c = 8; c < this.moduleCount - 8; c++) { + if (this.modules[6][c] != null) { + continue; + } + this.modules[6][c] = (c % 2 == 0); + } + }, + + setupPositionAdjustPattern: function() { + + var pos = QRUtil.getPatternPosition(this.typeNumber); + + for (var i = 0; i < pos.length; i++) { + + for (var j = 0; j < pos.length; j++) { + + var row = pos[i]; + var col = pos[j]; + + if (this.modules[row][col] != null) { + continue; + } + + for (var r = -2; r <= 2; r++) { + + for (var c = -2; c <= 2; c++) { + + if (r == -2 || r == 2 || c == -2 || c == 2 || + (r == 0 && c == 0)) { + this.modules[row + r][col + c] = true; + } else { + this.modules[row + r][col + c] = false; + } + } + } + } + } + }, + + setupTypeNumber: function(test) { + + var bits = QRUtil.getBCHTypeNumber(this.typeNumber); + + for (var i = 0; i < 18; i++) { + var mod = (!test && ((bits >> i) & 1) == 1); + this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod; + } + + for (var i = 0; i < 18; i++) { + var mod = (!test && ((bits >> i) & 1) == 1); + this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod; + } + }, + + setupTypeInfo: function(test, maskPattern) { + + var data = (this.errorCorrectLevel << 3) | maskPattern; + var bits = QRUtil.getBCHTypeInfo(data); + + // vertical + for (var i = 0; i < 15; i++) { + + var mod = (!test && ((bits >> i) & 1) == 1); + + if (i < 6) { + this.modules[i][8] = mod; + } else if (i < 8) { + this.modules[i + 1][8] = mod; + } else { + this.modules[this.moduleCount - 15 + i][8] = mod; + } + } + + // horizontal + for (var i = 0; i < 15; i++) { + + var mod = (!test && ((bits >> i) & 1) == 1); + + if (i < 8) { + this.modules[8][this.moduleCount - i - 1] = mod; + } else if (i < 9) { + this.modules[8][15 - i - 1 + 1] = mod; + } else { + this.modules[8][15 - i - 1] = mod; + } + } + + // fixed module + this.modules[this.moduleCount - 8][8] = (!test); + + }, + + mapData: function(data, maskPattern) { + + var inc = -1; + var row = this.moduleCount - 1; + var bitIndex = 7; + var byteIndex = 0; + + for (var col = this.moduleCount - 1; col > 0; col -= 2) { + + if (col == 6) col--; + + while (true) { + + for (var c = 0; c < 2; c++) { + + if (this.modules[row][col - c] == null) { + + var dark = false; + + if (byteIndex < data.length) { + dark = (((data[byteIndex] >>> bitIndex) & 1) == 1); + } + + var mask = QRUtil.getMask(maskPattern, row, col - c); + + if (mask) { + dark = !dark; + } + + this.modules[row][col - c] = dark; + bitIndex--; + + if (bitIndex == -1) { + byteIndex++; + bitIndex = 7; + } + } + } + + row += inc; + + if (row < 0 || this.moduleCount <= row) { + row -= inc; + inc = -inc; + break; + } + } + } + + } + + }; + + QRCode.PAD0 = 0xEC; + QRCode.PAD1 = 0x11; + + QRCode.createData = function(typeNumber, errorCorrectLevel, dataList) { + + var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel); + + var buffer = new QRBitBuffer(); + + for (var i = 0; i < dataList.length; i++) { + var data = dataList[i]; + buffer.put(data.mode, 4); + buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber)); + data.write(buffer); + } + + // calc num max data. + var totalDataCount = 0; + for (var i = 0; i < rsBlocks.length; i++) { + totalDataCount += rsBlocks[i].dataCount; + } + + if (buffer.getLengthInBits() > totalDataCount * 8) { + throw new Error("code length overflow. (" + + buffer.getLengthInBits() + + ">" + + totalDataCount * 8 + + ")"); + } + + // end code + if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) { + buffer.put(0, 4); + } + + // padding + while (buffer.getLengthInBits() % 8 != 0) { + buffer.putBit(false); + } + + // padding + while (true) { + + if (buffer.getLengthInBits() >= totalDataCount * 8) { + break; + } + buffer.put(QRCode.PAD0, 8); + + if (buffer.getLengthInBits() >= totalDataCount * 8) { + break; + } + buffer.put(QRCode.PAD1, 8); + } + + return QRCode.createBytes(buffer, rsBlocks); + } + + QRCode.createBytes = function(buffer, rsBlocks) { + + var offset = 0; + + var maxDcCount = 0; + var maxEcCount = 0; + + var dcdata = new Array(rsBlocks.length); + var ecdata = new Array(rsBlocks.length); + + for (var r = 0; r < rsBlocks.length; r++) { + + var dcCount = rsBlocks[r].dataCount; + var ecCount = rsBlocks[r].totalCount - dcCount; + + maxDcCount = Math.max(maxDcCount, dcCount); + maxEcCount = Math.max(maxEcCount, ecCount); + + dcdata[r] = new Array(dcCount); + + for (var i = 0; i < dcdata[r].length; i++) { + dcdata[r][i] = 0xff & buffer.buffer[i + offset]; + } + offset += dcCount; + + var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount); + var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1); + + var modPoly = rawPoly.mod(rsPoly); + ecdata[r] = new Array(rsPoly.getLength() - 1); + for (var i = 0; i < ecdata[r].length; i++) { + var modIndex = i + modPoly.getLength() - ecdata[r].length; + ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0; + } + + } + + var totalCodeCount = 0; + for (var i = 0; i < rsBlocks.length; i++) { + totalCodeCount += rsBlocks[i].totalCount; + } + + var data = new Array(totalCodeCount); + var index = 0; + + for (var i = 0; i < maxDcCount; i++) { + for (var r = 0; r < rsBlocks.length; r++) { + if (i < dcdata[r].length) { + data[index++] = dcdata[r][i]; + } + } + } + + for (var i = 0; i < maxEcCount; i++) { + for (var r = 0; r < rsBlocks.length; r++) { + if (i < ecdata[r].length) { + data[index++] = ecdata[r][i]; + } + } + } + + return data; + + } + + //--------------------------------------------------------------------- + // QRMode + //--------------------------------------------------------------------- + + var QRMode = { + MODE_NUMBER: 1 << 0, + MODE_ALPHA_NUM: 1 << 1, + MODE_8BIT_BYTE: 1 << 2, + MODE_KANJI: 1 << 3 + }; + + //--------------------------------------------------------------------- + // QRErrorCorrectLevel + //--------------------------------------------------------------------- + + var QRErrorCorrectLevel = { + L: 1, + M: 0, + Q: 3, + H: 2 + }; + + //--------------------------------------------------------------------- + // QRMaskPattern + //--------------------------------------------------------------------- + + var QRMaskPattern = { + PATTERN000: 0, + PATTERN001: 1, + PATTERN010: 2, + PATTERN011: 3, + PATTERN100: 4, + PATTERN101: 5, + PATTERN110: 6, + PATTERN111: 7 + }; + + //--------------------------------------------------------------------- + // QRUtil + //--------------------------------------------------------------------- + + var QRUtil = { + + PATTERN_POSITION_TABLE: [ + [], + [6, 18], + [6, 22], + [6, 26], + [6, 30], + [6, 34], + [6, 22, 38], + [6, 24, 42], + [6, 26, 46], + [6, 28, 50], + [6, 30, 54], + [6, 32, 58], + [6, 34, 62], + [6, 26, 46, 66], + [6, 26, 48, 70], + [6, 26, 50, 74], + [6, 30, 54, 78], + [6, 30, 56, 82], + [6, 30, 58, 86], + [6, 34, 62, 90], + [6, 28, 50, 72, 94], + [6, 26, 50, 74, 98], + [6, 30, 54, 78, 102], + [6, 28, 54, 80, 106], + [6, 32, 58, 84, 110], + [6, 30, 58, 86, 114], + [6, 34, 62, 90, 118], + [6, 26, 50, 74, 98, 122], + [6, 30, 54, 78, 102, 126], + [6, 26, 52, 78, 104, 130], + [6, 30, 56, 82, 108, 134], + [6, 34, 60, 86, 112, 138], + [6, 30, 58, 86, 114, 142], + [6, 34, 62, 90, 118, 146], + [6, 30, 54, 78, 102, 126, 150], + [6, 24, 50, 76, 102, 128, 154], + [6, 28, 54, 80, 106, 132, 158], + [6, 32, 58, 84, 110, 136, 162], + [6, 26, 54, 82, 110, 138, 166], + [6, 30, 58, 86, 114, 142, 170] + ], + + G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0), + G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0), + G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1), + + getBCHTypeInfo: function(data) { + var d = data << 10; + while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) { + d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15))); + } + return ((data << 10) | d) ^ QRUtil.G15_MASK; + }, + + getBCHTypeNumber: function(data) { + var d = data << 12; + while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) { + d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18))); + } + return (data << 12) | d; + }, + + getBCHDigit: function(data) { + + var digit = 0; + + while (data != 0) { + digit++; + data >>>= 1; + } + + return digit; + }, + + getPatternPosition: function(typeNumber) { + return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1]; + }, + + getMask: function(maskPattern, i, j) { + + switch (maskPattern) { + + case QRMaskPattern.PATTERN000: + return (i + j) % 2 == 0; + case QRMaskPattern.PATTERN001: + return i % 2 == 0; + case QRMaskPattern.PATTERN010: + return j % 3 == 0; + case QRMaskPattern.PATTERN011: + return (i + j) % 3 == 0; + case QRMaskPattern.PATTERN100: + return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0; + case QRMaskPattern.PATTERN101: + return (i * j) % 2 + (i * j) % 3 == 0; + case QRMaskPattern.PATTERN110: + return ((i * j) % 2 + (i * j) % 3) % 2 == 0; + case QRMaskPattern.PATTERN111: + return ((i * j) % 3 + (i + j) % 2) % 2 == 0; + + default: + throw new Error("bad maskPattern:" + maskPattern); + } + }, + + getErrorCorrectPolynomial: function(errorCorrectLength) { + + var a = new QRPolynomial([1], 0); + + for (var i = 0; i < errorCorrectLength; i++) { + a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0)); + } + + return a; + }, + + getLengthInBits: function(mode, type) { + + if (1 <= type && type < 10) { + + // 1 - 9 + + switch (mode) { + case QRMode.MODE_NUMBER: + return 10; + case QRMode.MODE_ALPHA_NUM: + return 9; + case QRMode.MODE_8BIT_BYTE: + return 8; + case QRMode.MODE_KANJI: + return 8; + default: + throw new Error("mode:" + mode); + } + + } else if (type < 27) { + + // 10 - 26 + + switch (mode) { + case QRMode.MODE_NUMBER: + return 12; + case QRMode.MODE_ALPHA_NUM: + return 11; + case QRMode.MODE_8BIT_BYTE: + return 16; + case QRMode.MODE_KANJI: + return 10; + default: + throw new Error("mode:" + mode); + } + + } else if (type < 41) { + + // 27 - 40 + + switch (mode) { + case QRMode.MODE_NUMBER: + return 14; + case QRMode.MODE_ALPHA_NUM: + return 13; + case QRMode.MODE_8BIT_BYTE: + return 16; + case QRMode.MODE_KANJI: + return 12; + default: + throw new Error("mode:" + mode); + } + + } else { + throw new Error("type:" + type); + } + }, + + getLostPoint: function(qrCode) { + + var moduleCount = qrCode.getModuleCount(); + + var lostPoint = 0; + + // LEVEL1 + + for (var row = 0; row < moduleCount; row++) { + + for (var col = 0; col < moduleCount; col++) { + + var sameCount = 0; + var dark = qrCode.isDark(row, col); + + for (var r = -1; r <= 1; r++) { + + if (row + r < 0 || moduleCount <= row + r) { + continue; + } + + for (var c = -1; c <= 1; c++) { + + if (col + c < 0 || moduleCount <= col + c) { + continue; + } + + if (r == 0 && c == 0) { + continue; + } + + if (dark == qrCode.isDark(row + r, col + c)) { + sameCount++; + } + } + } + + if (sameCount > 5) { + lostPoint += (3 + sameCount - 5); + } + } + } + + // LEVEL2 + + for (var row = 0; row < moduleCount - 1; row++) { + for (var col = 0; col < moduleCount - 1; col++) { + var count = 0; + if (qrCode.isDark(row, col)) count++; + if (qrCode.isDark(row + 1, col)) count++; + if (qrCode.isDark(row, col + 1)) count++; + if (qrCode.isDark(row + 1, col + 1)) count++; + if (count == 0 || count == 4) { + lostPoint += 3; + } + } + } + + // LEVEL3 + + for (var row = 0; row < moduleCount; row++) { + for (var col = 0; col < moduleCount - 6; col++) { + if (qrCode.isDark(row, col) && + !qrCode.isDark(row, col + 1) && + qrCode.isDark(row, col + 2) && + qrCode.isDark(row, col + 3) && + qrCode.isDark(row, col + 4) && + !qrCode.isDark(row, col + 5) && + qrCode.isDark(row, col + 6)) { + lostPoint += 40; + } + } + } + + for (var col = 0; col < moduleCount; col++) { + for (var row = 0; row < moduleCount - 6; row++) { + if (qrCode.isDark(row, col) && + !qrCode.isDark(row + 1, col) && + qrCode.isDark(row + 2, col) && + qrCode.isDark(row + 3, col) && + qrCode.isDark(row + 4, col) && + !qrCode.isDark(row + 5, col) && + qrCode.isDark(row + 6, col)) { + lostPoint += 40; + } + } + } + + // LEVEL4 + + var darkCount = 0; + + for (var col = 0; col < moduleCount; col++) { + for (var row = 0; row < moduleCount; row++) { + if (qrCode.isDark(row, col)) { + darkCount++; + } + } + } + + var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5; + lostPoint += ratio * 10; + + return lostPoint; + } + + }; + + + //--------------------------------------------------------------------- + // QRMath + //--------------------------------------------------------------------- + + var QRMath = { + + glog: function(n) { + + if (n < 1) { + throw new Error("glog(" + n + ")"); + } + + return QRMath.LOG_TABLE[n]; + }, + + gexp: function(n) { + + while (n < 0) { + n += 255; + } + + while (n >= 256) { + n -= 255; + } + + return QRMath.EXP_TABLE[n]; + }, + + EXP_TABLE: new Array(256), + + LOG_TABLE: new Array(256) + + }; + + for (var i = 0; i < 8; i++) { + QRMath.EXP_TABLE[i] = 1 << i; + } + for (var i = 8; i < 256; i++) { + QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ + QRMath.EXP_TABLE[i - 5] ^ + QRMath.EXP_TABLE[i - 6] ^ + QRMath.EXP_TABLE[i - 8]; + } + for (var i = 0; i < 255; i++) { + QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i; + } + + //--------------------------------------------------------------------- + // QRPolynomial + //--------------------------------------------------------------------- + + function QRPolynomial(num, shift) { + + if (num.length == undefined) { + throw new Error(num.length + "/" + shift); + } + + var offset = 0; + + while (offset < num.length && num[offset] == 0) { + offset++; + } + + this.num = new Array(num.length - offset + shift); + for (var i = 0; i < num.length - offset; i++) { + this.num[i] = num[i + offset]; + } + } + + QRPolynomial.prototype = { + + get: function(index) { + return this.num[index]; + }, + + getLength: function() { + return this.num.length; + }, + + multiply: function(e) { + + var num = new Array(this.getLength() + e.getLength() - 1); + + for (var i = 0; i < this.getLength(); i++) { + for (var j = 0; j < e.getLength(); j++) { + num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j))); + } + } + + return new QRPolynomial(num, 0); + }, + + mod: function(e) { + + if (this.getLength() - e.getLength() < 0) { + return this; + } + + var ratio = QRMath.glog(this.get(0)) - QRMath.glog(e.get(0)); + + var num = new Array(this.getLength()); + + for (var i = 0; i < this.getLength(); i++) { + num[i] = this.get(i); + } + + for (var i = 0; i < e.getLength(); i++) { + num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio); + } + + // recursive call + return new QRPolynomial(num, 0).mod(e); + } + }; + + //--------------------------------------------------------------------- + // QRRSBlock + //--------------------------------------------------------------------- + + function QRRSBlock(totalCount, dataCount) { + this.totalCount = totalCount; + this.dataCount = dataCount; + } + + QRRSBlock.RS_BLOCK_TABLE = [ + + // L + // M + // Q + // H + + // 1 + [1, 26, 19], + [1, 26, 16], + [1, 26, 13], + [1, 26, 9], + + // 2 + [1, 44, 34], + [1, 44, 28], + [1, 44, 22], + [1, 44, 16], + + // 3 + [1, 70, 55], + [1, 70, 44], + [2, 35, 17], + [2, 35, 13], + + // 4 + [1, 100, 80], + [2, 50, 32], + [2, 50, 24], + [4, 25, 9], + + // 5 + [1, 134, 108], + [2, 67, 43], + [2, 33, 15, 2, 34, 16], + [2, 33, 11, 2, 34, 12], + + // 6 + [2, 86, 68], + [4, 43, 27], + [4, 43, 19], + [4, 43, 15], + + // 7 + [2, 98, 78], + [4, 49, 31], + [2, 32, 14, 4, 33, 15], + [4, 39, 13, 1, 40, 14], + + // 8 + [2, 121, 97], + [2, 60, 38, 2, 61, 39], + [4, 40, 18, 2, 41, 19], + [4, 40, 14, 2, 41, 15], + + // 9 + [2, 146, 116], + [3, 58, 36, 2, 59, 37], + [4, 36, 16, 4, 37, 17], + [4, 36, 12, 4, 37, 13], + + // 10 + [2, 86, 68, 2, 87, 69], + [4, 69, 43, 1, 70, 44], + [6, 43, 19, 2, 44, 20], + [6, 43, 15, 2, 44, 16], + + // 11 + [4, 101, 81], + [1, 80, 50, 4, 81, 51], + [4, 50, 22, 4, 51, 23], + [3, 36, 12, 8, 37, 13], + + // 12 + [2, 116, 92, 2, 117, 93], + [6, 58, 36, 2, 59, 37], + [4, 46, 20, 6, 47, 21], + [7, 42, 14, 4, 43, 15], + + // 13 + [4, 133, 107], + [8, 59, 37, 1, 60, 38], + [8, 44, 20, 4, 45, 21], + [12, 33, 11, 4, 34, 12], + + // 14 + [3, 145, 115, 1, 146, 116], + [4, 64, 40, 5, 65, 41], + [11, 36, 16, 5, 37, 17], + [11, 36, 12, 5, 37, 13], + + // 15 + [5, 109, 87, 1, 110, 88], + [5, 65, 41, 5, 66, 42], + [5, 54, 24, 7, 55, 25], + [11, 36, 12], + + // 16 + [5, 122, 98, 1, 123, 99], + [7, 73, 45, 3, 74, 46], + [15, 43, 19, 2, 44, 20], + [3, 45, 15, 13, 46, 16], + + // 17 + [1, 135, 107, 5, 136, 108], + [10, 74, 46, 1, 75, 47], + [1, 50, 22, 15, 51, 23], + [2, 42, 14, 17, 43, 15], + + // 18 + [5, 150, 120, 1, 151, 121], + [9, 69, 43, 4, 70, 44], + [17, 50, 22, 1, 51, 23], + [2, 42, 14, 19, 43, 15], + + // 19 + [3, 141, 113, 4, 142, 114], + [3, 70, 44, 11, 71, 45], + [17, 47, 21, 4, 48, 22], + [9, 39, 13, 16, 40, 14], + + // 20 + [3, 135, 107, 5, 136, 108], + [3, 67, 41, 13, 68, 42], + [15, 54, 24, 5, 55, 25], + [15, 43, 15, 10, 44, 16], + + // 21 + [4, 144, 116, 4, 145, 117], + [17, 68, 42], + [17, 50, 22, 6, 51, 23], + [19, 46, 16, 6, 47, 17], + + // 22 + [2, 139, 111, 7, 140, 112], + [17, 74, 46], + [7, 54, 24, 16, 55, 25], + [34, 37, 13], + + // 23 + [4, 151, 121, 5, 152, 122], + [4, 75, 47, 14, 76, 48], + [11, 54, 24, 14, 55, 25], + [16, 45, 15, 14, 46, 16], + + // 24 + [6, 147, 117, 4, 148, 118], + [6, 73, 45, 14, 74, 46], + [11, 54, 24, 16, 55, 25], + [30, 46, 16, 2, 47, 17], + + // 25 + [8, 132, 106, 4, 133, 107], + [8, 75, 47, 13, 76, 48], + [7, 54, 24, 22, 55, 25], + [22, 45, 15, 13, 46, 16], + + // 26 + [10, 142, 114, 2, 143, 115], + [19, 74, 46, 4, 75, 47], + [28, 50, 22, 6, 51, 23], + [33, 46, 16, 4, 47, 17], + + // 27 + [8, 152, 122, 4, 153, 123], + [22, 73, 45, 3, 74, 46], + [8, 53, 23, 26, 54, 24], + [12, 45, 15, 28, 46, 16], + + // 28 + [3, 147, 117, 10, 148, 118], + [3, 73, 45, 23, 74, 46], + [4, 54, 24, 31, 55, 25], + [11, 45, 15, 31, 46, 16], + + // 29 + [7, 146, 116, 7, 147, 117], + [21, 73, 45, 7, 74, 46], + [1, 53, 23, 37, 54, 24], + [19, 45, 15, 26, 46, 16], + + // 30 + [5, 145, 115, 10, 146, 116], + [19, 75, 47, 10, 76, 48], + [15, 54, 24, 25, 55, 25], + [23, 45, 15, 25, 46, 16], + + // 31 + [13, 145, 115, 3, 146, 116], + [2, 74, 46, 29, 75, 47], + [42, 54, 24, 1, 55, 25], + [23, 45, 15, 28, 46, 16], + + // 32 + [17, 145, 115], + [10, 74, 46, 23, 75, 47], + [10, 54, 24, 35, 55, 25], + [19, 45, 15, 35, 46, 16], + + // 33 + [17, 145, 115, 1, 146, 116], + [14, 74, 46, 21, 75, 47], + [29, 54, 24, 19, 55, 25], + [11, 45, 15, 46, 46, 16], + + // 34 + [13, 145, 115, 6, 146, 116], + [14, 74, 46, 23, 75, 47], + [44, 54, 24, 7, 55, 25], + [59, 46, 16, 1, 47, 17], + + // 35 + [12, 151, 121, 7, 152, 122], + [12, 75, 47, 26, 76, 48], + [39, 54, 24, 14, 55, 25], + [22, 45, 15, 41, 46, 16], + + // 36 + [6, 151, 121, 14, 152, 122], + [6, 75, 47, 34, 76, 48], + [46, 54, 24, 10, 55, 25], + [2, 45, 15, 64, 46, 16], + + // 37 + [17, 152, 122, 4, 153, 123], + [29, 74, 46, 14, 75, 47], + [49, 54, 24, 10, 55, 25], + [24, 45, 15, 46, 46, 16], + + // 38 + [4, 152, 122, 18, 153, 123], + [13, 74, 46, 32, 75, 47], + [48, 54, 24, 14, 55, 25], + [42, 45, 15, 32, 46, 16], + + // 39 + [20, 147, 117, 4, 148, 118], + [40, 75, 47, 7, 76, 48], + [43, 54, 24, 22, 55, 25], + [10, 45, 15, 67, 46, 16], + + // 40 + [19, 148, 118, 6, 149, 119], + [18, 75, 47, 31, 76, 48], + [34, 54, 24, 34, 55, 25], + [20, 45, 15, 61, 46, 16] + ]; + + QRRSBlock.getRSBlocks = function(typeNumber, errorCorrectLevel) { + + var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel); + + if (rsBlock == undefined) { + throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + + errorCorrectLevel); + } + + var length = rsBlock.length / 3; + + var list = new Array(); + + for (var i = 0; i < length; i++) { + + var count = rsBlock[i * 3 + 0]; + var totalCount = rsBlock[i * 3 + 1]; + var dataCount = rsBlock[i * 3 + 2]; + + for (var j = 0; j < count; j++) { + list.push(new QRRSBlock(totalCount, dataCount)); + } + } + + return list; + } + + QRRSBlock.getRsBlockTable = function(typeNumber, errorCorrectLevel) { + + switch (errorCorrectLevel) { + case QRErrorCorrectLevel.L: + return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0]; + case QRErrorCorrectLevel.M: + return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1]; + case QRErrorCorrectLevel.Q: + return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2]; + case QRErrorCorrectLevel.H: + return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3]; + default: + return undefined; + } + } + + //--------------------------------------------------------------------- + // QRBitBuffer + //--------------------------------------------------------------------- + + function QRBitBuffer() { + this.buffer = new Array(); + this.length = 0; + } + + QRBitBuffer.prototype = { + + get: function(index) { + var bufIndex = Math.floor(index / 8); + return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) == 1; + }, + + put: function(num, length) { + for (var i = 0; i < length; i++) { + this.putBit(((num >>> (length - i - 1)) & 1) == 1); + } + }, + + getLengthInBits: function() { + return this.length; + }, + + putBit: function(bit) { + + var bufIndex = Math.floor(this.length / 8); + if (this.buffer.length <= bufIndex) { + this.buffer.push(0); + } + + if (bit) { + this.buffer[bufIndex] |= (0x80 >>> (this.length % 8)); + } + + this.length++; + } + }; + + //--------------------------------------------------------------------- + // Support Chinese 字符编码支持中文 + // 使用mode 4 8bit + //--------------------------------------------------------------------- + function utf16To8(text) { + var result = ''; + var c; + for (var i = 0; i < text.length; i++) { + c = text.charCodeAt(i); + if (c >= 0x0001 && c <= 0x007F) { + result += text.charAt(i); + } else if (c > 0x07FF) { + result += String.fromCharCode(0xE0 | c >> 12 & 0x0F); + result += String.fromCharCode(0x80 | c >> 6 & 0x3F); + result += String.fromCharCode(0x80 | c >> 0 & 0x3F); + } else { + result += String.fromCharCode(0xC0 | c >> 6 & 0x1F); + result += String.fromCharCode(0x80 | c >> 0 & 0x3F); + } + } + return result; + } + + /** + * 队列 + */ + class Queue { + constructor() { + let waitingQueue = []; + let isRunning = false; //记录是否有未完成的任务 + function execute(task, resolve, reject) { + task() + .then((data) => { + resolve(data); + }) + .catch((e) => { + reject(e); + }) + .finally(() => { + //等待任务队列中如果有任务,则触发它;否则设置isRunning = false,表示无任务状态 + if (waitingQueue.length) { + const next = waitingQueue.shift(); + execute(next.task, next.resolve, next.reject); + } else { + isRunning = false; + } + }); + } + return function(task) { + return new Promise((resolve, reject) => { + if (isRunning) { + waitingQueue.push({ + task, + resolve, + reject + }); + } else { + isRunning = true; + execute(task, resolve, reject); + } + }); + }; + } + } + // const queue = new Queue(); + // queue(() => new Promise((resolve, reject) => { + // setTimeout(() => { + // resolve('task1'); + // }, 1000); + // })).then(data => console.log(data)); + // queue(() => new Promise((resolve, reject) => { + // setTimeout(() => { + // resolve('task2'); + // }, 100); + // })).then(data => console.log(data)); + // queue(() => new Promise((resolve, reject) => { + // setTimeout(() => { + // resolve('task3'); + // }, 300); + // })).then(data => console.log(data)); + + /** + * 纠错等级 + */ + uQRCode.errorCorrectLevel = QRErrorCorrectLevel; + + /** + * 预设默认值(基本,不包含各部分和艺术码参数) + */ + uQRCode.defaults = { + typeNumber: -1, // 版本,-1为自动计算,字符越多,版本越高 + errorCorrectLevel: QRErrorCorrectLevel.H, // 纠错等级 + text: '', // 二维码内容 + size: 354, // 大小 + useDynamicSize: false, // 使用动态尺寸,可以去掉方块小数点,绘制出来后没有白色细线 + margin: 0, // 边距 + background: { + color: '#FFFFFF' // 背景色 + }, + foreground: { + color: '#000000' // 前景色 + } + } + + /** + * 对象属性深度替换 + * @param {Object} o 原始对象/默认对象/被替换的对象 + * @param {Object} r 从这个对象里取值替换到o对象里 + * @return {Object} 替换后的新对象 + */ + uQRCode.deepReplace = function(o = {}, r = {}) { + let obj = { + ...o + } + for (let k in r) { + var vr = r[k]; + if (vr.constructor == Object) { + obj[k] = this.deepReplace(obj[k], vr); + } else if (vr.constructor == String && !vr) { + obj[k] = obj[k]; + } else { + obj[k] = vr; + } + } + return obj; + } + + /** + * 获取选项值 + */ + uQRCode.getOptions = function(options) { + options = uQRCode.deepReplace(uQRCode.defaults, options); + + /* 背景 */ + options.background = uQRCode.deepReplace({ + color: options.background.color, // 背景色 + image: { + src: '', + width: 1, // 图片宽 + height: 1, // 图片高 + align: ['center', 'center'], // 图片对齐方式水平,垂直 + anchor: [0, 0], // 图片位置,X坐标,Y坐标 + alpha: 1 // 透明度 + } + }, options.background); + /* 前景 */ + options.foreground = uQRCode.deepReplace({ + color: options.foreground.color, // 前景色 + image: { + src: '', + width: 1 / 4, // 图片宽 + height: 1 / 4, // 图片高 + align: ['center', 'center'], // 图片对齐方式水平,垂直 + anchor: [0, 0] // 图片位置,X坐标,Y坐标 + } + }, options.foreground); + /* 定位角 */ + options.positionDetection = uQRCode.deepReplace({ + backgroundColor: options.background.color, // 定位角区域背景色,默认值跟随背景色 + foregroundColor: options.foreground.color // 定位角小块颜色,默认值跟随前景色 + }, options.positionDetection); + /* 分割图案 */ + options.separator = uQRCode.deepReplace({ + color: options.background.color // 分割区域颜色,默认值跟随背景色 + }, options.separator); + /* 对齐图案 */ + options.alignment = uQRCode.deepReplace({ + backgroundColor: options.background.color, // 对齐区域背景色,默认值跟随背景色 + foregroundColor: options.foreground.color // 对齐小块颜色,默认值跟随前景色 + }, options.alignment); + /* 时序图案 */ + options.timing = uQRCode.deepReplace({ + backgroundColor: options.background.color, // 时序区域背景色,默认值跟随背景色 + foregroundColor: options.foreground.color // 时序小块颜色,默认值跟随前景色 + }, options.timing); + /* 暗块 */ + options.darkBlock = uQRCode.deepReplace({ + color: options.foreground.color // 暗块颜色 + }, options.darkBlock); + /* 版本信息 */ + options.versionInformation = uQRCode.deepReplace({ + backgroundColor: options.background.color, // 版本信息区域背景色,默认值跟随背景色 + foregroundColor: options.foreground.color // 版本信息小块颜色,默认值跟随前景色 + }, options.versionInformation); + + return options; + } + + /** + * 获取canvas实例 + */ + uQRCode.getCanvasContext = function(ctx) { + /* 兼容setFillStyle写法,主要在uni-app nvue gcanvas */ + ctx.setFillStyle = ctx.setFillStyle || function(color) { + ctx.fillStyle = color; + } + /* 兼容setFontSize写法,主要在微信小程序canvas2d */ + ctx.setFontSize = ctx.setFontSize || function(fontSize) { + ctx.font = `${fontSize}px`; + } + /* 兼容setTextAlign写法,主要在微信小程序canvas2d */ + ctx.setTextAlign = ctx.setTextAlign || function(align) { + ctx.textAlign = align; + } + /* 兼容setTextBaseline写法,主要在微信小程序canvas2d */ + ctx.setTextBaseline = ctx.setTextBaseline || function(textBaseline) { + ctx.textBaseline = textBaseline; + } + /* 若实例不包含draw方法则创建一个 */ + ctx.draw = ctx.draw || function(reserve, callback) { + callback && callback(); + } + return ctx; + } + + /* 队列实例,某些平台一起使用多个组件时需要通过队列逐一绘制,否则部分绘制方法异常,nvue端的iOS gcanvas尤其明显,在不通过队列绘制时会出现图片丢失的情况 */ + uQRCode.Queue = new Queue(); + uQRCode.QueueLoadImage = new Queue(); + + /* 缓存loadImage图片 */ + uQRCode.loadImageCache = []; + + /** + * 获取加载图片方法 + */ + uQRCode.getLoadImage = function(loadImage) { + if (typeof loadImage == 'function') { + return function(src) { + /* 解决iOS APP||NVUE同时绘制多个二维码导致图片丢失需使用队列 */ + return uQRCode.QueueLoadImage(() => new Promise((resolve, reject) => { + setTimeout(() => { + const cache = uQRCode.loadImageCache.find(x => x.src == src); + if (cache) { + resolve(cache.img); + } else { + loadImage(src).then(img => { + uQRCode.loadImageCache.push({ + src, + img + }); + resolve(img); + }); + } + }, 150); + })); + } + } else { + return function(src) { + return Promise.resolve(src); + } + } + } + + uQRCode.prototype = { + /** + * 实例化传入的选项值 + */ + options: {}, + + /** + * 画布实例 + */ + canvasContext: {}, + + /** + * 制作二维码全部数据 + */ + makeData: {}, + + /** + * 制作二维码主要模块数据,基于makeData的modules但数据格式不一致,这里的modules是定制过的 + */ + modules: [], + + /** + * 模块数量 + */ + moduleCount: 0, + + /** + * 获取制作二维码数据 + */ + getMakeData() { + let { + typeNumber, + errorCorrectLevel, + text + } = this.options; + var qrcode = new QRCode(typeNumber, errorCorrectLevel); + qrcode.addData(utf16To8(text.toString())); + qrcode.make(); + return qrcode; + }, + + /** + * 制作二维码方法 + */ + make() { + let makeData = this.makeData = this.getMakeData(); + this.modules = JSON.parse(JSON.stringify(makeData.modules)); + this.moduleCount = makeData.moduleCount; + this.options.typeNumber = makeData.typeNumber; + + /* 数据码 data */ + this.paintData(); + /* 定位图案 position detection */ + this.paintPositionDetection(); + /* 分隔图案 separator */ + this.paintSeparator(); + /* 对齐图案 alignment */ + this.paintAlignment(); + /* 时序图案 timing */ + this.paintTiming(); + /* 暗块 darkBlock */ + this.paintDarkBlock(); + /* 预留版本信息 version information */ + this.paintVersionInformation(); + }, + + paintData() { + let modules = this.modules; + let moduleCount = this.moduleCount; + let { + size, + margin, + background, + foreground, + useDynamicSize + } = this.options; + + /* dynamicSize自动计算出最适合绘制的尺寸,并按这个尺寸去绘制,可以解决canvas绘制小块间产生白线的问题(其实就是小数点精度问题),useDynamicSize=false可以取消这个设定 */ + // let dynamicSize = this.options.dynamicSize = Math.floor((size - margin * 2) / moduleCount) * moduleCount + margin * 2; // Math.floor向下取整缩放会模糊 + let dynamicSize = this.options.dynamicSize = Math.ceil((size - margin * 2) / moduleCount) * moduleCount + margin * 2; // Math.ceil向上取整缩放效果比floor清晰 + if (!useDynamicSize) { + dynamicSize = this.options.dynamicSize = size; + } + let tileSize = (dynamicSize - margin * 2) / moduleCount; + + for (var rowI = 0; rowI < modules.length; rowI++) { + for (var colI = 0; colI < modules.length; colI++) { + var tile = modules[rowI][colI]; + if (tile) { + modules[rowI][colI] = { + size: tileSize, + x: colI * tileSize + margin, + y: rowI * tileSize + margin, + type: ['foreground'], + color: foreground.color, + isBlack: true, + isDrawn: false + }; + } else { + modules[rowI][colI] = { + size: tileSize, + x: colI * tileSize + margin, + y: rowI * tileSize + margin, + type: ['background'], + color: background.color, + isBlack: false, + isDrawn: false + }; + } + } + } + }, + + paintPositionDetection() { + let modules = this.modules; + let size = this.moduleCount; + let { + positionDetection + } = this.options; + + //1) 定义基础图形索引(左上角)x ,y,v + let basePart = [ + [0, 0, 1], + [1, 0, 1], + [2, 0, 1], + [3, 0, 1], + [4, 0, 1], + [5, 0, 1], + [6, 0, 1], + [0, 1, 1], + [1, 1, 0], + [2, 1, 0], + [3, 1, 0], + [4, 1, 0], + [5, 1, 0], + [6, 1, 1], + [0, 2, 1], + [1, 2, 0], + [2, 2, 1], + [3, 2, 1], + [4, 2, 1], + [5, 2, 0], + [6, 2, 1], + [0, 3, 1], + [1, 3, 0], + [2, 3, 1], + [3, 3, 1], + [4, 3, 1], + [5, 3, 0], + [6, 3, 1], + [0, 4, 1], + [1, 4, 0], + [2, 4, 1], + [3, 4, 1], + [4, 4, 1], + [5, 4, 0], + [6, 4, 1], + [0, 5, 1], + [1, 5, 0], + [2, 5, 0], + [3, 5, 0], + [4, 5, 0], + [5, 5, 0], + [6, 5, 1], + [0, 6, 1], + [1, 6, 1], + [2, 6, 1], + [3, 6, 1], + [4, 6, 1], + [5, 6, 1], + [6, 6, 1] + ]; + let disc = size - 7; //size -7 + basePart.forEach(d => { + var ltItem = modules[d[0]][d[1]]; + var rtItem = modules[d[0] + disc][d[1]]; + var lbItem = modules[d[0]][d[1] + disc]; + lbItem.type.push('positionDetection'); + rtItem.type.push('positionDetection'); + ltItem.type.push('positionDetection'); + //绘制左上角 + ltItem.color = d[2] == 1 ? positionDetection.foregroundColor : positionDetection.backgroundColor; + //绘制右 + rtItem.color = d[2] == 1 ? positionDetection.foregroundColor : positionDetection.backgroundColor; + //绘制左 + lbItem.color = d[2] == 1 ? positionDetection.foregroundColor : positionDetection.backgroundColor; + }); + }, + + paintSeparator() { + let modules = this.modules; + let size = this.moduleCount; + let { + separator + } = this.options; + + //1) 定义基础图形索引(左上角) + [ + [7, 0], + [7, 1], + [7, 2], + [7, 3], + [7, 4], + [7, 5], + [7, 6], + [7, 7], + [0, 7], + [1, 7], + [2, 7], + [3, 7], + [4, 7], + [5, 7], + [6, 7] + ].forEach(d => { + var ltItem = modules[d[0]][d[1]]; + var rtItem = modules[size - d[0] - 1][d[1]]; + var lbItem = modules[d[0]][size - d[1] - 1]; + lbItem.type.push('separator'); + rtItem.type.push('separator'); + ltItem.type.push('separator'); + //绘制左上 + ltItem.color = separator.color; + //绘制右 + rtItem.color = separator.color; + //绘制左 + lbItem.color = separator.color; + }); + }, + + paintAlignment() { + let modules = this.modules; + let size = this.moduleCount; + let { + alignment, + typeNumber + } = this.options; + + //不同版本的对齐图案组合位置 + const ALIGNMENT_OF_VERSION = [ + [], + [6, 18], + [6, 22], + [6, 26], + [6, 30], + [6, 34], + [6, 22, 38], + [6, 24, 42], + [6, 26, 46], + [6, 28, 50], + [6, 30, 54], + [6, 32, 58], + [6, 34, 62], + [6, 26, 46, 66], + [6, 26, 48, 70], + [6, 26, 50, 74], + [6, 30, 54, 78], + [6, 30, 56, 82], + [6, 30, 58, 86], + [6, 34, 62, 90], + [6, 28, 50, 72, 94], + [6, 26, 50, 74, 98], + [6, 30, 54, 78, 102], + [6, 28, 54, 80, 106], + [6, 32, 58, 84, 110], + [6, 30, 58, 86, 114], + [6, 34, 62, 90, 118], + [6, 26, 50, 74, 98, 122], + [6, 30, 54, 78, 102, 126], + [6, 26, 52, 78, 104, 130], + [6, 30, 56, 82, 108, 134], + [6, 34, 60, 86, 112, 138], + [6, 30, 58, 86, 114, 142], + [6, 34, 62, 90, 118, 146], + [6, 30, 54, 78, 102, 126, 150], + [6, 24, 50, 76, 102, 128, 154], + [6, 28, 54, 80, 106, 132, 158], + [6, 32, 58, 84, 110, 136, 162], + [6, 26, 54, 82, 110, 138, 166], + [6, 30, 58, 86, 114, 142, 170] + ]; + // 对齐图案数量和中心位置根据版本定义 + const alignments = ALIGNMENT_OF_VERSION[typeNumber - 1]; + if (alignments) { + const calcMatrix = [ + [-2, -2, 1], + [-1, -2, 1], + [0, -2, 1], + [1, -2, 1], + [2, -2, 1], + [-2, -1, 1], + [-1, -1, 0], + [0, -1, 0], + [1, -1, 0], + [2, -1, 1], + [-2, 0, 1], + [-1, 0, 0], + [0, 0, 1], + [1, 0, 0], + [2, 0, 1], + [-2, 1, 1], + [-1, 1, 0], + [0, 1, 0], + [1, 1, 0], + [2, 1, 1], + [-2, 2, 1], + [-1, 2, 1], + [0, 2, 1], + [1, 2, 1], + [2, 2, 1] + ]; + const group_len = alignments.length; + for (let i = 0; i < group_len; i++) { + for (let j = 0; j < group_len; j++) { + //对齐图案不能污染 定位器和分隔器 + let { + x, + y + } = { + x: alignments[i], + y: alignments[j] + }; + if (!((x < 9 && y < 9) || (x > size - 9 - 1 && y < 9) || (y > size - 9 - 1 && x < 9))) { + calcMatrix.forEach(d => { + var alignmentItem = modules[x + d[0]][y + d[1]]; + alignmentItem.type.push('alignment'); + alignmentItem.color = d[2] == 1 ? alignment.foregroundColor : alignment.backgroundColor; + }); + } + } + } + } + }, + + paintTiming() { + let modules = this.modules; + let { + timing + } = this.options; + + let timingPartLen = modules.length - 16; + for (let i = 0; i < timingPartLen; i++) { + var xItem = modules[6][8 + i]; + var yItem = modules[8 + i][6]; + xItem.type.push('timing'); + yItem.type.push('timing'); + xItem.color = (1 & i) ^ 1 ? timing.foregroundColor : timing.backgroundColor; + yItem.color = (1 & i) ^ 1 ? timing.foregroundColor : timing.backgroundColor; + } + }, + + paintDarkBlock() { + let modules = this.modules; + let size = this.moduleCount; + let { + darkBlock + } = this.options; + + //创建暗模块 + var darkBlockItem = modules[size - 7 - 1][8]; + darkBlockItem.type.push('darkBlock'); + darkBlockItem.color = darkBlock.color; + }, + + paintVersionInformation() { + let modules = this.modules; + let size = this.moduleCount; + let { + versionInformation, + typeNumber: version + } = this.options; + + if (version < 7) { + return modules; + } + //预留版本信息 0 为补位,预留版本信息 是从索引7开始 + const VERSIONS = [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + '000111110010010100', + '001000010110111100', + '001001101010011001', + '001010010011010011', + '001011101111110110', + '001100011101100010', + '001101100001000111', + '001110011000001101', + '001111100100101000', + '010000101101111000', + '010001010001011101', + '010010101000010111', + '010011010100110010', + '010100100110100110', + '010101011010000011', + '010110100011001001', + '010111011111101100', + '011000111011000100', + '011001000111100001', + '011010111110101011', + '011011000010001110', + '011100110000011010', + '011101001100111111', + '011110110101110101', + '011111001001010000', + '100000100111010101', + '100001011011110000', + '100010100010111010', + '100011011110011111', + '100100101100001011', + '100101010000101110', + '100110101001100100', + '100111010101000001', + '101000110001101001' + ]; + + //两种方式获取预留格式信息,临时计算或者查字典 + //let version_codes = _v.correctVersionData(_v.version); + let version_codes = VERSIONS[version] + VERSIONS[version]; + //创建预留版本信息 + let disc = [size - 11, size - 10, size - 9]; + // 左+右 + let version_cells = [ + //左 + [5, disc[2]], + [5, disc[1]], + [5, disc[0]], + [4, disc[2]], + [4, disc[1]], + [4, disc[0]], + [3, disc[2]], + [3, disc[1]], + [3, disc[0]], + [2, disc[2]], + [2, disc[1]], + [2, disc[0]], + [1, disc[2]], + [1, disc[1]], + [1, disc[0]], + [0, disc[2]], + [0, disc[1]], + [0, disc[0]], + //右 + [disc[2], 5], + [disc[1], 5], + [disc[0], 5], + [disc[2], 4], + [disc[1], 4], + [disc[0], 4], + [disc[2], 3], + [disc[1], 3], + [disc[0], 3], + [disc[2], 2], + [disc[1], 2], + [disc[0], 2], + [disc[2], 1], + [disc[1], 1], + [disc[0], 1], + [disc[2], 0], + [disc[1], 0], + [disc[0], 0] + ]; + version_cells.forEach((d, index) => { + var versionInformationItem = modules[d[0]][d[1]]; + versionInformationItem.type.push('versionInformation'); + versionInformationItem.color = version_codes[index] == '1' ? versionInformation.foregroundColor : versionInformation.backgroundColor; + }); + }, + + /** + * 绘制二维码方法 + */ + draw(options) { + options = uQRCode.deepReplace({ + drawBackground: { + before: () => {}, + after: () => {} + }, + drawBackgroundImage: { + before: () => {}, + after: () => {} + }, + drawForeground: { + before: () => {}, + after: () => {} + }, + drawForegroundImage: { + before: () => {}, + after: () => {} + } + }, options); + + /* 绘制层级关系,最底层背景 -> 背景图片 -> 前景 -> 最顶层前景图片 */ + return new Promise((resolve, reject) => { + let ctx = this.canvasContext; + + const startup = () => { + /* 同时绘制多个二维码时使用队列绘制,防止内部方法冲突导致绘制失败 */ + return uQRCode.Queue(() => new Promise((queueResolve, queueReject) => { + setTimeout(() => { + ctx.draw(false); // 第一个draw false可以清空画布 + queueResolve(); + }, 150); + })); + } + startup() + .then(() => { + /* 绘制背景 */ + return this.drawBackground({ + before: options.drawBackground.before, + after: options.drawBackground.after + }); + }) + .then(() => { + /* 绘制背景图片 */ + return this.drawBackgroundImage({ + before: options.drawBackgroundImage.before, + after: options.drawBackgroundImage.after + }); + }) + .then(() => { + /* 绘制前景 */ + return this.drawForeground({ + before: options.drawForeground.before, + after: options.drawForeground.after + }); + }) + .then(() => { + /* 绘制前景图片 */ + return this.drawForegroundImage({ + before: options.drawForegroundImage.before, + after: options.drawForegroundImage.after + }); + }) + .then(() => { + /* 完成绘制 */ + resolve(); + }); + }); + }, + + drawBackground({ + before, + after + }) { + let { + dynamicSize: size, + background + } = this.options; + let ctx = this.canvasContext; + + return new Promise((resolve, reject) => { + (async () => { + await before(this); + + ctx.save(); + /* 填充背景色 */ + ctx.setFillStyle(background.color); + ctx.fillRect(0, 0, size, size); + ctx.restore(); + ctx.draw(true); // gcanvas需要每一阶段都draw一下,否则重绘有问题,例如uni-app nvue绘制图片会失败 + + await after(this); + resolve(); + })(); + }); + }, + + drawBackgroundImage({ + before, + after + }) { + let { + dynamicSize: size, + background + } = this.options; + let ctx = this.canvasContext; + + return new Promise((resolve, reject) => { + (async () => { + await before(this); + + if (background.image.src) { + ctx.save(); + + let x = 0; + let y = 0; + + let w = background.image.width * size; + let h = background.image.height * size; + let align = background.image.align; + let anchor = background.image.anchor; + let alpha = background.image.alpha; + + switch (align[0]) { + case 'left': + x = 0; + break; + case 'center': + x = size / 2 - w / 2; + break; + case 'right': + x = size - w; + break; + } + x += Number(anchor[0]); + + switch (align[1]) { + case 'top': + y = 0; + break; + case 'center': + y = size / 2 - h / 2; + break; + case 'bottom': + y = size - h; + break; + } + y += Number(anchor[1]); + + /* 设置透明度 */ + ctx.globalAlpha = alpha; + + /* 绘制图片 */ + const img = await this.loadImage(background.image.src); + ctx.drawImage(img, x, y, w, h); + ctx.restore(); + ctx.draw(true); // gcanvas需要每一阶段都draw一下,否则重绘有问题,例如uni-app nvue绘制图片会失败 + } + + await after(this); + resolve(); + })(); + }); + }, + + drawForeground({ + before, + after + }) { + let { + background + } = this.options; + let modules = this.modules; + let moduleCount = this.moduleCount; + let ctx = this.canvasContext; + + return new Promise((resolve, reject) => { + (async () => { + await before(this); + + ctx.save(); + for (var rowI = 0; rowI < moduleCount; rowI++) { + for (var colI = 0; colI < moduleCount; colI++) { + var tile = modules[rowI][colI]; + if (!tile.isDrawn && tile.color != background.color) { // 颜色不能与背景色一致,否则可能发生颜色重叠 + var color = tile.color; + ctx.setFillStyle(color); + ctx.fillRect(tile.x, tile.y, tile.size, tile.size); + tile.isDrawn = true; + } + } + } + ctx.restore(); + ctx.draw(true); // gcanvas需要每一阶段都draw一下,否则重绘有问题,例如uni-app nvue绘制图片会失败 + + await after(this); + resolve(); + })(); + }); + }, + + drawForegroundImage({ + before, + after + }) { + let { + dynamicSize: size, + foreground + } = this.options; + let ctx = this.canvasContext; + + return new Promise((resolve, reject) => { + (async () => { + await before(this); + + if (foreground.image.src) { + ctx.save(); + + // 绘制前景图 + let x = 0; + let y = 0; + + let w = foreground.image.width * size; + let h = foreground.image.height * size; + let align = foreground.image.align; + let anchor = foreground.image.anchor; + let alpha = foreground.image.alpha; + let shadow = foreground.image.shadow; + let border = foreground.image.border; + + switch (align[0]) { + case 'left': + x = 0; + break; + case 'center': + x = size / 2 - w / 2; + break; + case 'right': + x = size - w; + break; + } + x += Number(anchor[0]); + + switch (align[1]) { + case 'top': + y = 0; + break; + case 'center': + y = size / 2 - h / 2; + break; + case 'bottom': + y = size - h; + break; + } + y += Number(anchor[1]); + + /* 绘制图片 */ + const img = await this.loadImage(foreground.image.src); + ctx.drawImage(img, x, y, w, h); + ctx.restore(); + ctx.draw(true); // gcanvas需要每一阶段都draw一下,否则重绘有问题,例如uni-app nvue绘制图片会失败 + } + + await after(this); + resolve(); + })(); + }); + } + + } + +})(); + +export default uQRCode; diff --git a/uni_modules/Sansnn-uQRCode/package.json b/uni_modules/Sansnn-uQRCode/package.json new file mode 100644 index 0000000..5966ddd --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/package.json @@ -0,0 +1,83 @@ +{ + "id": "Sansnn-uQRCode", + "displayName": "uQRCode 二维码生成插件 支持nvue 支持nodejs服务端", + "version": "3.2.2", + "description": "uQRCode 是一款使用方式简单,高扩展的二维码生成插件。支持全端生成,支持canvas的地方就可以使用uQRCode。", + "keywords": [ + "uQRCode", + "二维码", + "qrcode", + "qr" +], + "repository": "https://github.com/Sansnn/uQRCode", + "engines": { + "HBuilderX": "^3.1.0" + }, + "dcloudext": { + "category": [ + "JS SDK", + "通用 SDK" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/u-qrcode" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/Sansnn-uQRCode/readme.md b/uni_modules/Sansnn-uQRCode/readme.md new file mode 100644 index 0000000..e5935be --- /dev/null +++ b/uni_modules/Sansnn-uQRCode/readme.md @@ -0,0 +1,274 @@ +# uQRCode + +**点击群号加入群聊【uQRCode交流群】:[695070434](https://jq.qq.com/?_wv=1027&k=JRjzDqiw)** + +uQRCode 生成方式简单,可扩展性高,适用所有前端应用和Node.js服务端,可运行到所有支持canvas的平台。支持NVUE(NVUE中使用GCanvas)。 + +支持自定义二维码渲染规则,可通过uQRCode API得到矩阵信息后,自行实现canvas或view+css渲染二维码,如随机颜色、圆点、方块、块与块之间的间距等,详情参考示例项目。 + +### 插件市场 +[https://ext.dcloud.net.cn/plugin?id=1287](https://ext.dcloud.net.cn/plugin?id=1287) + +### github +[https://github.com/Sansnn/uQRCode](https://github.com/Sansnn/uQRCode) + +### npm +[https://www.npmjs.com/package/u-qrcode](https://www.npmjs.com/package/u-qrcode) + +### 示例预览 +[https://static-c15f4b57-ef97-4d2b-b939-f580f910d7e2.bspapp.com](https://static-c15f4b57-ef97-4d2b-b939-f580f910d7e2.bspapp.com) + +### 二维码 +**什么是QR码** + +QR码属于矩阵式二维码中的一个种类,由DENSO(日本电装)公司开发,由JIS和ISO将其标准化。 + +**QR码的特点** + +一是高速读取(QR就是取自“Quick Response”的首字母),通过摄像头从拍摄到解码到显示内容也就三秒左右,对摄像的角度也没有什么要求; + +二是高容量、高密度,理论上内容经过压缩处理后可以存7089个数字,4296个字母和数字混合字符,2953个8位字节数据,1817个汉字; + +三是支持纠错处理,按照QR码的标准文档说明,QR码的纠错分为4个级别,分别是: +- level L : 最大 7% 的错误能够被纠正; +- level M : 最大 15% 的错误能够被纠正; +- level Q : 最大 25% 的错误能够被纠正; +- level H : 最大 30% 的错误能够被纠正; + +四是结构化,看似无规则的图形,其实对区域有严格的定义。 + +更多二维码介绍及原理:[https://blog.csdn.net/jason_ldh/article/details/11801355](https://blog.csdn.net/jason_ldh/article/details/11801355) + +### 组件使用 + +导入`u-qrcode`组件后,在 `template` 中创建 `` 组件 + +```html + +``` + +### 属性说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|canvasId |String |- |- |是 |组件标识/canvasId | +|value |String |- |- |是 |二维码内容 | +|size |Number |- |354 |否 |二维码大小,默认单位px,rpx需要使用uni.upx2px()转换| +|options |Object |- |- |否 |参数可选项,详见下方options说明 | + +### 事件说明 +|事件名 |参数 |返回值 |说明 | +|--- |--- |--- |:--- | +|click |- |void |点击事件 | +|complete |- |Object |生成完成事件,返回值success: true表示生成成功,false生成失败 | + +### 方法说明 +|方法名 |参数 |返回值 |说明 | +|--- |--- |--- |:--- | +|remake |- |void |重新生成 | +|toTempFilePath |Object:callback|void |导出临时路径 | +|save |Object:callback|void |保存 | + +#### options说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|typeNumber |Number |- |-1 |否 |二维码版本 | +|errorCorrectLevel |String/Number|L/M/Q/H/1/0/3/2|H |否 |纠错等级L/M/Q/H分别对应1/0/3/2 | +|useDynamicSize |Boolean |- |false |否 |是否使用动态尺寸,可以去除二维码小块白色细线 | +|margin |Number |- |0 |否 |填充边距,默认单位px | +|background |Object |- |- |否 |背景设置,详见下方options.background说明 | +|foreground |Object |- |- |否 |前景设置,详见下方options.foreground说明 | +|positionDetection |Object |- |- |否 |定位角设置,详见下方options.positionDetection说明 | +|separator |Object |- |- |否 |分割图案设置,详见下方options.separator说明 | +|alignment |Object |- |- |否 |对齐图案设置,详见下方options.alignment说明 | +|timing |Object |- |- |否 |时序图案设置,详见下方options.timing说明 | +|darkBlock |Object |- |- |否 |暗块设置,详见下方options.darkBlock说明 | +|versionInformation |Object |- |- |否 |版本信息设置,详见下方options.versionInformation说明 | + +#### options.background说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|color |String |- |#FFFFFF|否 |背景色,若需要透明背景可设置为rgba(0,0,0,0)| +|image |Object |- |- |否 |背景图片设置,详见下方options.background.image说明| + +#### options.background.image说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|src |String |- |- |否 |背景图片路径 | +|width |Number |- |1 |否 |指定背景图片宽度,1为二维码size的100% | +|height |Number |- |1 |否 |指定背景图片高度,1为二维码size的100% | +|align |Array|['left'/'center'/'right', 'top'/'center'/'bottom'] |['center', 'center'] |否 |指定背景图片对齐方式,[0]为水平方位,[1]为垂直方位 | +|anchor |Array|- |[0, 0] |否 |指定背景图片锚点,[0]为X轴偏移量,[1]为Y轴偏移量 | +|alpha |Number |0-1 |1 |否 |指定背景图片透明度 | + +#### options.foreground说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|color |String |- |#FFFFFF|否 |前景色 | +|image |Object |- |- |否 |前景图片设置,详见下方options.foreground.image说明 | + +#### options.foreground.image说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|src |String |- |- |否 |前景图片路径 | +|width |Number |- |1/4 |否 |指定前景图片宽度,1为二维码size的100% | +|height |Number |- |1/4 |否 |指定前景图片高度,1为二维码size的100% | +|align |Array|['left'/'center'/'right', 'top'/'center'/'bottom'] |['center', 'center'] |否 |指定前景图片对齐方式,[0]为水平方位,[1]为垂直方位 | +|anchor |Array|- |[0, 0] |否 |指定前景图片锚点,[0]为X轴偏移量,[1]为Y轴偏移量 | + +#### options.positionDetection说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|backgroundColor|String |- |options.background.color |否 |定位角区域背景色,默认值跟随背景色 | +|foregroundColor|String |- |options.foreground.color |否 |定位角小块颜色,默认值跟随前景色 | + +#### options.separator说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|color |String |- |options.background.color |否 |分割区域颜色,默认值跟随背景色 | + +#### options.alignment说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|backgroundColor|String |- |options.background.color |否 |对齐区域背景色,默认值跟随背景色 | +|foregroundColor|String |- |options.foreground.color |否 |对齐小块颜色,默认值跟随前景色 | + +#### options.timing说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|backgroundColor|String |- |options.background.color |否 |时序区域背景色,默认值跟随背景色 | +|foregroundColor|String |- |options.foreground.color |否 |时序小块颜色,默认值跟随前景色 | + +#### options.darkBlock说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|color |String |- |options.foreground.color |否 |暗块颜色,默认值跟随前景色 | + +#### options.versionInformation说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|backgroundColor|String |- |options.background.color |否 |版本信息区域背景色,默认值跟随背景色 | +|foregroundColor|String |- |options.foreground.color |否 |版本信息小块颜色,默认值跟随前景色 | + +### u-qrcode.js使用 + +引入u-qrcode.js + +``` javascript +import uQRCode from '../../uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode'; +``` + +或者使用npm安装 + +> npm i u-qrcode + +``` javascript +import uQRCode from 'u-qrcode'; +``` + +nodejs引入 + +``` javascript +import uQRCode from 'u-qrcode/module'; +``` + +在 `template` 中创建 `` 组件并设置 `id`,画布宽高 + +```html + +``` + +在 `script` 中调用生成方法 + +```javascript +import uQRCode from '../../uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode'; + +export default { + data() { + return { + text: 'uQRCode', + size: 256 + } + }, + onReady() { + const ctx = uni.createCanvasContext('qrcode'); + const uqrcode = new uQRCode( + { + text: this.text, + size: this.size + }, + ctx + ); + uqrcode.make(); + uqrcode.draw(); + } +} +``` + +### new uQRCode(options, canvasContext, loadImage)说明 + +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|options |Object |- |- |是 |包含组件属性中的options的所有属性,详见下方options说明 | +|canvasContext|Object |- |- |是 |canvas绘画上下文 | +|loadImage |Promise|- |- |否 |绘制图片时,某些平台必传,例如微信小程序2d绘图需要创建Image对象,不能直接使用路径,这时就需要传入canvas.createImage给loadImage方法,否则无法绘制图片 | + +#### options说明,包含组件属性中的options的所有属性,下方仅列举未包含的属性,其余属性请移步到组件属性options说明查看 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|text |String |- |- |是 |二维码内容 | +|size |Number |- |354 |否 |二维码大小 | + +### uQRCode实例属性 +|属性名 |类型 |说明 | +|--- |--- |:--- | +|options |Object |实例化传入的选项值 | +|canvasContext|Object |画布实例 | +|makeData |Object |制作二维码全部数据 | +|modules |Array |制作二维码主要模块数据 | +|moduleCount |Number |模块数量 | + +### uQRCode实例方法 +|方法名 |参数 |返回值 |说明 | +|--- |--- |--- |:--- | +|make |- |void |制作二维码方法 | +|draw |options|Promise|绘制二维码方法,绘制层级关系,最底层背景 -> 背景图片 -> 前景 -> 最顶层前景图片,options见下方说明 | + +#### draw(options)说明 +|属性名 |类型 |可选值 |默认值 |是否必填 |说明 | +|--- |--- |--- |--- |--- |:--- | +|drawBackground |Object: {before, after}|- |- |否 |绘制背景前后可执行自定义方法before,after | +|drawBackgroundImage|Object: {before, after}|- |- |否 |绘制背景图前后可执行自定义方法before,after| +|drawForeground |Object: {before, after}|- |- |否 |绘制前景前后可执行自定义方法before,after | +|drawForegroundImage|Object: {before, after}|- |- |否 |绘制前景图前后可执行自定义方法before,after| + +### uQRCode静态属性 +|属性名 |类型 |说明 | +|--- |--- |:--- | +|errorCorrectLevel|Object |纠错等级 | +|defaults |Object |预设默认值 | + +### uQRCode静态方法 +|方法名 |参数 |返回值 |说明 | +|--- |--- |--- |:--- | +|deepReplace|o, r |替换后的新对象 |对象属性深度替换 | + +### 常见问题 + +**如何扫码跳转指定网页** + +二维码内容直接放入完整的网页地址即可,例如:`https://ext.dcloud.net.cn/plugin?id=1287`。微信客户端不能是ip地址。 + +**nvue打包后生成失败** + +Canvas是作为独立的模块,打包时需要选择使用Canvas模块才能正常使用相关的功能。 需要在manifest.json的代码视图中配置如下(暂时还不支持可视化界面操作): +```javascript +"app-plus" : { + /* 模块配置 */ + "modules" : { + "Canvas" : "nvue canvas" //使用Canvas模块 + }, + //... +}, +//... +``` +保存好提交云端打包。 diff --git a/uni_modules/hpy-form-select/changelog.md b/uni_modules/hpy-form-select/changelog.md new file mode 100644 index 0000000..01f2a3e --- /dev/null +++ b/uni_modules/hpy-form-select/changelog.md @@ -0,0 +1,2 @@ +## 0.0.10(2022-04-26) +- 适配uni-forms校验 diff --git a/uni_modules/hpy-form-select/components/hpy-form-select/hpy-form-select.vue b/uni_modules/hpy-form-select/components/hpy-form-select/hpy-form-select.vue new file mode 100644 index 0000000..78de734 --- /dev/null +++ b/uni_modules/hpy-form-select/components/hpy-form-select/hpy-form-select.vue @@ -0,0 +1,255 @@ + + + + + diff --git a/uni_modules/hpy-form-select/package.json b/uni_modules/hpy-form-select/package.json new file mode 100644 index 0000000..c40ce8a --- /dev/null +++ b/uni_modules/hpy-form-select/package.json @@ -0,0 +1,87 @@ +{ + "id": "hpy-form-select", + "displayName": "picker选择器、下拉框,选择器", + "version": "0.0.10", + "description": "下拉选择器 基于 picker 简单封装", + "keywords": [ + "picker", + "选择器", + "下拉选择" +], + "repository": "", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [ + "uni-load-more" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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", + "阿里": "u", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "y", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/hpy-form-select/readme.md b/uni_modules/hpy-form-select/readme.md new file mode 100644 index 0000000..30f721e --- /dev/null +++ b/uni_modules/hpy-form-select/readme.md @@ -0,0 +1,169 @@ + +## hpy-form-select 下拉选择器 基于 [picker](https://uniapp.dcloud.io/component/picker?id=picker) 简单封装 + +> **组件名:hpy-form-select + +从底部弹起的滚动选择器。支持五种选择器,通过mode来区分,分别是普通选择器,多列选择器,时间选择器,日期选择器,省市区选择器,默认是普通选择器 + +## API + +### FilePicker Props + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
属性名类型默认值说明
islotBoolean | Stringfalse是否使用插槽
titleString请选择默认标题
modeString选择模式selector | multiSelector
startString表示有效日期范围的开始,字符串格式为"YYYY-MM-DD"
endString表示有效日期范围的结束,字符串格式为"YYYY-MM-DD"
fieldsStringday有效值 year、month、day,表示选择器的粒度,默认为 day,App 端未配置此项时使用系统 UI
customItemString可为每一列的顶部添加一个自定义的项
dataListArray选择器数据
textString显示值的key
nameString保存值的key
v-model | valueArray | Object绑定的数据
disabledBoolean | Stringfalse是否禁用
hideBorderBoolean | Stringfalse是否隐藏边框
hideArrowBoolean | Stringfalse是否隐藏箭头
+ + +## 使用示例 +## dataList 为对象数组时,name为实际保存的value值,text为显示的值 +## dataList 为对象数组[{name:'张三', age:'18'}, {name:'李四', age:'19'}]时,需要设置name、text属性,name为实际保存的value值,text为显示的值 +## +## ====================================================================================================== +## dataList 为普通数组['张三', '李四'] name、text可不设置 +## +## 类似: +## + + +```html + + + + + + + + + + + + + + 可自定义显示 + + + + + + + +``` + +```javascript +export default { + data() { + return { + formData:{ + hobbySelect:'' + }, + hobbyList: [{ + text: '足球', + value: 1 + }, { + text: '篮球', + value: 2 + }, { + text: '游泳', + value: 3 + }], + } + }, + methods:{ + change(e){ + console.log(e.index); + console.log(e.value); + console.log(e.data); + } + } +} + +``` \ No newline at end of file diff --git a/uni_modules/uni-badge/changelog.md b/uni_modules/uni-badge/changelog.md new file mode 100644 index 0000000..544ecc1 --- /dev/null +++ b/uni_modules/uni-badge/changelog.md @@ -0,0 +1,29 @@ +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-badge](https://uniapp.dcloud.io/component/uniui/uni-badge) +## 1.1.7(2021-11-08) +- 优化 升级ui +- 修改 size 属性默认值调整为 small +- 修改 type 属性,默认值调整为 error,info 替换 default +## 1.1.6(2021-09-22) +- 修复 在字节小程序上样式不生效的 bug +## 1.1.5(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.1.4(2021-07-29) +- 修复 去掉 nvue 不支持css 的 align-self 属性,nvue 下不暂支持 absolute 属性 +## 1.1.3(2021-06-24) +- 优化 示例项目 +## 1.1.1(2021-05-12) +- 新增 组件示例地址 +## 1.1.0(2021-05-12) +- 新增 uni-badge 的 absolute 属性,支持定位 +- 新增 uni-badge 的 offset 属性,支持定位偏移 +- 新增 uni-badge 的 is-dot 属性,支持仅显示有一个小点 +- 新增 uni-badge 的 max-num 属性,支持自定义封顶的数字值,超过 99 显示99+ +- 优化 uni-badge 属性 custom-style, 支持以对象形式自定义样式 +## 1.0.7(2021-05-07) +- 修复 uni-badge 在 App 端,数字小于10时不是圆形的bug +- 修复 uni-badge 在父元素不是 flex 布局时,宽度缩小的bug +- 新增 uni-badge 属性 custom-style, 支持自定义样式 +## 1.0.6(2021-02-04) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-badge/components/uni-badge/uni-badge.vue b/uni_modules/uni-badge/components/uni-badge/uni-badge.vue new file mode 100644 index 0000000..fcbfe93 --- /dev/null +++ b/uni_modules/uni-badge/components/uni-badge/uni-badge.vue @@ -0,0 +1,268 @@ + + + + + diff --git a/uni_modules/uni-badge/package.json b/uni_modules/uni-badge/package.json new file mode 100644 index 0000000..4e9e631 --- /dev/null +++ b/uni_modules/uni-badge/package.json @@ -0,0 +1,88 @@ +{ + "id": "uni-badge", + "displayName": "uni-badge 数字角标", + "version": "1.2.0", + "description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。", + "keywords": [ + "", + "badge", + "uni-ui", + "uniui", + "数字角标", + "徽章" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-badge/readme.md b/uni_modules/uni-badge/readme.md new file mode 100644 index 0000000..bdf175d --- /dev/null +++ b/uni_modules/uni-badge/readme.md @@ -0,0 +1,10 @@ +## Badge 数字角标 +> **组件名:uni-badge** +> 代码块: `uBadge` + +数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景, + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-badge) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/uni_modules/uni-calendar/changelog.md b/uni_modules/uni-calendar/changelog.md new file mode 100644 index 0000000..6df4493 --- /dev/null +++ b/uni_modules/uni-calendar/changelog.md @@ -0,0 +1,16 @@ +## 1.4.5(2022-02-25) +- 修复 条件编译 nvue 不支持的 css 样式 +## 1.4.4(2022-02-25) +- 修复 条件编译 nvue 不支持的 css 样式 +## 1.4.3(2021-09-22) +- 修复 startDate、 endDate 属性失效的 bug +## 1.4.2(2021-08-24) +- 新增 支持国际化 +## 1.4.1(2021-08-05) +- 修复 弹出层被 tabbar 遮盖 bug +## 1.4.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.3.16(2021-05-12) +- 新增 组件示例地址 +## 1.3.15(2021-02-04) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-calendar/components/uni-calendar/calendar.js b/uni_modules/uni-calendar/components/uni-calendar/calendar.js new file mode 100644 index 0000000..b8d7d6f --- /dev/null +++ b/uni_modules/uni-calendar/components/uni-calendar/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/uni-calendar/components/uni-calendar/i18n/en.json b/uni_modules/uni-calendar/components/uni-calendar/i18n/en.json new file mode 100644 index 0000000..fcbd13c --- /dev/null +++ b/uni_modules/uni-calendar/components/uni-calendar/i18n/en.json @@ -0,0 +1,12 @@ +{ + "uni-calender.ok": "ok", + "uni-calender.cancel": "cancel", + "uni-calender.today": "today", + "uni-calender.MON": "MON", + "uni-calender.TUE": "TUE", + "uni-calender.WED": "WED", + "uni-calender.THU": "THU", + "uni-calender.FRI": "FRI", + "uni-calender.SAT": "SAT", + "uni-calender.SUN": "SUN" +} diff --git a/uni_modules/uni-calendar/components/uni-calendar/i18n/index.js b/uni_modules/uni-calendar/components/uni-calendar/i18n/index.js new file mode 100644 index 0000000..de7509c --- /dev/null +++ b/uni_modules/uni-calendar/components/uni-calendar/i18n/index.js @@ -0,0 +1,8 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json b/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json new file mode 100644 index 0000000..1ca43de --- /dev/null +++ b/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json @@ -0,0 +1,12 @@ +{ + "uni-calender.ok": "确定", + "uni-calender.cancel": "取消", + "uni-calender.today": "今日", + "uni-calender.SUN": "日", + "uni-calender.MON": "一", + "uni-calender.TUE": "二", + "uni-calender.WED": "三", + "uni-calender.THU": "四", + "uni-calender.FRI": "五", + "uni-calender.SAT": "六" +} diff --git a/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json b/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json new file mode 100644 index 0000000..e0fe33b --- /dev/null +++ b/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json @@ -0,0 +1,12 @@ +{ + "uni-calender.ok": "確定", + "uni-calender.cancel": "取消", + "uni-calender.today": "今日", + "uni-calender.SUN": "日", + "uni-calender.MON": "一", + "uni-calender.TUE": "二", + "uni-calender.WED": "三", + "uni-calender.THU": "四", + "uni-calender.FRI": "五", + "uni-calender.SAT": "六" +} diff --git a/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue b/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue new file mode 100644 index 0000000..0353011 --- /dev/null +++ b/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue @@ -0,0 +1,181 @@ + + + + + diff --git a/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue b/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue new file mode 100644 index 0000000..a2c33d0 --- /dev/null +++ b/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue @@ -0,0 +1,554 @@ + + + + + diff --git a/uni_modules/uni-calendar/components/uni-calendar/util.js b/uni_modules/uni-calendar/components/uni-calendar/util.js new file mode 100644 index 0000000..bae9273 --- /dev/null +++ b/uni_modules/uni-calendar/components/uni-calendar/util.js @@ -0,0 +1,354 @@ +import CALENDAR from './calendar.js' + +class Calendar { + constructor({ + date, + selected, + startDate, + endDate, + range + } = {}) { + // 当前日期 + this.date = this.getDate(new Date()) // 当前初入日期 + // 打点信息 + this.selected = selected || []; + // 范围开始 + this.startDate = startDate + // 范围结束 + this.endDate = endDate + this.range = range + // 多选状态 + this.cleanMultipleStatus() + // 每周日期 + this.weeks = {} + // this._getWeek(this.date.fullDate) + } + /** + * 设置日期 + * @param {Object} date + */ + setDate(date) { + this.selectDate = this.getDate(date) + this._getWeek(this.selectDate.fullDate) + } + + /** + * 清理多选状态 + */ + cleanMultipleStatus() { + this.multipleStatus = { + before: '', + after: '', + data: [] + } + } + + /** + * 重置开始日期 + */ + resetSatrtDate(startDate) { + // 范围开始 + this.startDate = startDate + + } + + /** + * 重置结束日期 + */ + resetEndDate(endDate) { + // 范围结束 + this.endDate = endDate + } + + /** + * 获取任意时间 + */ + getDate(date, AddDayCount = 0, str = 'day') { + if (!date) { + date = new Date() + } + if (typeof date !== 'object') { + date = date.replace(/-/g, '/') + } + const dd = new Date(date) + switch (str) { + case 'day': + dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期 + break + case 'month': + if (dd.getDate() === 31) { + dd.setDate(dd.getDate() + AddDayCount) + } else { + dd.setMonth(dd.getMonth() + AddDayCount) // 获取AddDayCount天后的日期 + } + break + case 'year': + dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期 + break + } + const y = dd.getFullYear() + const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期,不足10补0 + const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号,不足10补0 + return { + fullDate: y + '-' + m + '-' + d, + year: y, + month: m, + date: d, + day: dd.getDay() + } + } + + + /** + * 获取上月剩余天数 + */ + _getLastMonthDays(firstDay, full) { + let dateArr = [] + for (let i = firstDay; i > 0; i--) { + const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate() + dateArr.push({ + date: beforeDate, + month: full.month - 1, + lunar: this.getlunar(full.year, full.month - 1, beforeDate), + disable: true + }) + } + return dateArr + } + /** + * 获取本月天数 + */ + _currentMonthDys(dateData, full) { + let dateArr = [] + let fullDate = this.date.fullDate + for (let i = 1; i <= dateData; i++) { + let isinfo = false + let nowDate = full.year + '-' + (full.month < 10 ? + full.month : full.month) + '-' + (i < 10 ? + '0' + i : i) + // 是否今天 + let isDay = fullDate === nowDate + // 获取打点信息 + let info = this.selected && this.selected.find((item) => { + if (this.dateEqual(nowDate, item.date)) { + return item + } + }) + + // 日期禁用 + let disableBefore = true + let disableAfter = true + if (this.startDate) { + // let dateCompBefore = this.dateCompare(this.startDate, fullDate) + // disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate) + disableBefore = this.dateCompare(this.startDate, nowDate) + } + + if (this.endDate) { + // let dateCompAfter = this.dateCompare(fullDate, this.endDate) + // disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate) + disableAfter = this.dateCompare(nowDate, this.endDate) + } + let multiples = this.multipleStatus.data + let checked = false + let multiplesStatus = -1 + if (this.range) { + if (multiples) { + multiplesStatus = multiples.findIndex((item) => { + return this.dateEqual(item, nowDate) + }) + } + if (multiplesStatus !== -1) { + checked = true + } + } + let data = { + fullDate: nowDate, + year: full.year, + date: i, + multiple: this.range ? checked : false, + beforeMultiple: this.dateEqual(this.multipleStatus.before, nowDate), + afterMultiple: this.dateEqual(this.multipleStatus.after, nowDate), + month: full.month, + lunar: this.getlunar(full.year, full.month, i), + disable: !(disableBefore && disableAfter), + isDay + } + if (info) { + data.extraInfo = info + } + + dateArr.push(data) + } + return dateArr + } + /** + * 获取下月天数 + */ + _getNextMonthDays(surplus, full) { + let dateArr = [] + for (let i = 1; i < surplus + 1; i++) { + dateArr.push({ + date: i, + month: Number(full.month) + 1, + lunar: this.getlunar(full.year, Number(full.month) + 1, i), + disable: true + }) + } + return dateArr + } + + /** + * 获取当前日期详情 + * @param {Object} date + */ + getInfo(date) { + if (!date) { + date = new Date() + } + const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate) + return dateInfo + } + + /** + * 比较时间大小 + */ + dateCompare(startDate, endDate) { + // 计算截止时间 + startDate = new Date(startDate.replace('-', '/').replace('-', '/')) + // 计算详细项的截止时间 + endDate = new Date(endDate.replace('-', '/').replace('-', '/')) + if (startDate <= endDate) { + return true + } else { + return false + } + } + + /** + * 比较时间是否相等 + */ + dateEqual(before, after) { + // 计算截止时间 + before = new Date(before.replace('-', '/').replace('-', '/')) + // 计算详细项的截止时间 + after = new Date(after.replace('-', '/').replace('-', '/')) + if (before.getTime() - after.getTime() === 0) { + return true + } else { + return false + } + } + + + /** + * 获取日期范围内所有日期 + * @param {Object} begin + * @param {Object} end + */ + geDateAll(begin, end) { + var arr = [] + var ab = begin.split('-') + var ae = end.split('-') + var db = new Date() + db.setFullYear(ab[0], ab[1] - 1, ab[2]) + var de = new Date() + de.setFullYear(ae[0], ae[1] - 1, ae[2]) + var unixDb = db.getTime() - 24 * 60 * 60 * 1000 + var unixDe = de.getTime() - 24 * 60 * 60 * 1000 + for (var k = unixDb; k <= unixDe;) { + k = k + 24 * 60 * 60 * 1000 + arr.push(this.getDate(new Date(parseInt(k))).fullDate) + } + return arr + } + /** + * 计算阴历日期显示 + */ + getlunar(year, month, date) { + return CALENDAR.solar2lunar(year, month, date) + } + /** + * 设置打点 + */ + setSelectInfo(data, value) { + this.selected = value + this._getWeek(data) + } + + /** + * 获取多选状态 + */ + setMultiple(fullDate) { + let { + before, + after + } = this.multipleStatus + + if (!this.range) return + if (before && after) { + this.multipleStatus.before = '' + this.multipleStatus.after = '' + this.multipleStatus.data = [] + } else { + if (!before) { + this.multipleStatus.before = fullDate + } else { + this.multipleStatus.after = fullDate + if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) { + this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after); + } else { + this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before); + } + } + } + this._getWeek(fullDate) + } + + /** + * 获取每周数据 + * @param {Object} dateData + */ + _getWeek(dateData) { + const { + fullDate, + year, + month, + date, + day + } = this.getDate(dateData) + let firstDay = new Date(year, month - 1, 1).getDay() + let currentDay = new Date(year, month, 0).getDate() + let dates = { + lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天 + currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数 + nextMonthDays: [], // 下个月开始几天 + weeks: [] + } + let canlender = [] + const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length) + dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData)) + canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays) + let weeks = {} + // 拼接数组 上个月开始几天 + 本月天数+ 下个月开始几天 + for (let i = 0; i < canlender.length; i++) { + if (i % 7 === 0) { + weeks[parseInt(i / 7)] = new Array(7) + } + weeks[parseInt(i / 7)][i % 7] = canlender[i] + } + this.canlender = canlender + this.weeks = weeks + } + + //静态方法 + // static init(date) { + // if (!this.instance) { + // this.instance = new Calendar(date); + // } + // return this.instance; + // } +} + + +export default Calendar diff --git a/uni_modules/uni-calendar/package.json b/uni_modules/uni-calendar/package.json new file mode 100644 index 0000000..40455c8 --- /dev/null +++ b/uni_modules/uni-calendar/package.json @@ -0,0 +1,88 @@ +{ + "id": "uni-calendar", + "displayName": "uni-calendar 日历", + "version": "1.4.5", + "description": "日历组件", + "keywords": [ + "uni-ui", + "uniui", + "日历", + "", + "打卡", + "日历选择" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-calendar/readme.md b/uni_modules/uni-calendar/readme.md new file mode 100644 index 0000000..4f3ca0e --- /dev/null +++ b/uni_modules/uni-calendar/readme.md @@ -0,0 +1,103 @@ + + +## Calendar 日历 +> **组件名:uni-calendar** +> 代码块: `uCalendar` + + +日历组件 + +> **注意事项** +> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。 +> - 本组件农历转换使用的js是 [@1900-2100区间内的公历、农历互转](https://github.com/jjonline/calendar.js) +> - 仅支持自定义组件模式 +> - `date`属性传入的应该是一个 String ,如: 2019-06-27 ,而不是 new Date() +> - 通过 `insert` 属性来确定当前的事件是 @change 还是 @confirm 。理应合并为一个事件,但是为了区分模式,现使用两个事件,这里需要注意 +> - 弹窗模式下无法阻止后面的元素滚动,如有需要阻止,请在弹窗弹出后,手动设置滚动元素为不可滚动 + + +### 安装方式 + +本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。 + +如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55) + +### 基本用法 + +在 ``template`` 中使用组件 + +```html + + + +``` + +### 通过方法打开日历 + +需要设置 `insert` 为 `false` + +```html + + + + +``` + +```javascript + +export default { + data() { + return {}; + }, + methods: { + open(){ + this.$refs.calendar.open(); + }, + confirm(e) { + console.log(e); + } + } +}; + +``` + + +## API + +### Calendar Props + +| 属性名 | 类型 | 默认值| 说明 | +| | | +| date | String |- | 自定义当前时间,默认为今天 | +| lunar | Boolean | false | 显示农历 | +| startDate | String |- | 日期选择范围-开始日期 | +| endDate | String |- | 日期选择范围-结束日期 | +| range | Boolean | false | 范围选择 | +| insert | Boolean | false | 插入模式,可选值,ture:插入模式;false:弹窗模式;默认为插入模式 | +|clearDate |Boolean |true |弹窗模式是否清空上次选择内容 | +| selected | Array |- | 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}] | +|showMonth | Boolean | true | 是否显示月份为背景 | + +### Calendar Events + +| 事件名 | 说明 |返回值| +| | | | +| open | 弹出日历组件,`insert :false` 时生效|- | + + + + + +## 组件示例 + +点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar](https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar) \ No newline at end of file diff --git a/uni_modules/uni-card/changelog.md b/uni_modules/uni-card/changelog.md new file mode 100644 index 0000000..c3cd8c4 --- /dev/null +++ b/uni_modules/uni-card/changelog.md @@ -0,0 +1,26 @@ +## 1.3.1(2021-12-20) +- 修复 在vue页面下略缩图显示不正常的bug +## 1.3.0(2021-11-19) +- 重构插槽的用法 ,header 替换为 title +- 新增 actions 插槽 +- 新增 cover 封面图属性和插槽 +- 新增 padding 内容默认内边距离 +- 新增 margin 卡片默认外边距离 +- 新增 spacing 卡片默认内边距 +- 新增 shadow 卡片阴影属性 +- 取消 mode 属性,可使用组合插槽代替 +- 取消 note 属性 ,使用actions插槽代替 +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-card](https://uniapp.dcloud.io/component/uniui/uni-card) +## 1.2.1(2021-07-30) +- 优化 vue3下事件警告的问题 +## 1.2.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.1.8(2021-07-01) +- 优化 图文卡片无图片加载时,提供占位图标 +- 新增 header 插槽,自定义卡片头部( 图文卡片 mode="style" 时,不支持) +- 修复 thumbnail 不存在仍然占位的 bug +## 1.1.7(2021-05-12) +- 新增 组件示例地址 +## 1.1.6(2021-02-04) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-card/components/uni-card/uni-card.vue b/uni_modules/uni-card/components/uni-card/uni-card.vue new file mode 100644 index 0000000..38cf594 --- /dev/null +++ b/uni_modules/uni-card/components/uni-card/uni-card.vue @@ -0,0 +1,270 @@ + + + + + diff --git a/uni_modules/uni-card/package.json b/uni_modules/uni-card/package.json new file mode 100644 index 0000000..f16224d --- /dev/null +++ b/uni_modules/uni-card/package.json @@ -0,0 +1,90 @@ +{ + "id": "uni-card", + "displayName": "uni-card 卡片", + "version": "1.3.1", + "description": "Card 组件,提供常见的卡片样式。", + "keywords": [ + "uni-ui", + "uniui", + "card", + "", + "卡片" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-icons", + "uni-scss" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-card/readme.md b/uni_modules/uni-card/readme.md new file mode 100644 index 0000000..7434e71 --- /dev/null +++ b/uni_modules/uni-card/readme.md @@ -0,0 +1,12 @@ + + +## Card 卡片 +> **组件名:uni-card** +> 代码块: `uCard` + +卡片视图组件。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-card) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/uni_modules/uni-collapse/changelog.md b/uni_modules/uni-collapse/changelog.md new file mode 100644 index 0000000..292e4c7 --- /dev/null +++ b/uni_modules/uni-collapse/changelog.md @@ -0,0 +1,36 @@ +## 1.4.3(2022-01-25) +- 修复 初始化的时候 ,open 属性失效的bug +## 1.4.2(2022-01-21) +- 修复 微信小程序resize后组件收起的bug +## 1.4.1(2021-11-22) +- 修复 vue3中个别scss变量无法找到的问题 +## 1.4.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-collapse](https://uniapp.dcloud.io/component/uniui/uni-collapse) +## 1.3.3(2021-08-17) +- 优化 show-arrow 属性默认为true +## 1.3.2(2021-08-17) +- 新增 show-arrow 属性,控制是否显示右侧箭头 +## 1.3.1(2021-07-30) +- 优化 vue3下小程序事件警告的问题 +## 1.3.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.2.2(2021-07-21) +- 修复 由1.2.0版本引起的 change 事件返回 undefined 的Bug +## 1.2.1(2021-07-21) +- 优化 组件示例 +## 1.2.0(2021-07-21) +- 新增 组件折叠动画 +- 新增 value\v-model 属性 ,动态修改面板折叠状态 +- 新增 title 插槽 ,可定义面板标题 +- 新增 border 属性 ,显示隐藏面板内容分隔线 +- 新增 title-border 属性 ,显示隐藏面板标题分隔线 +- 修复 resize 方法失效的Bug +- 修复 change 事件返回参数不正确的Bug +- 优化 H5、App 平台自动更具内容更新高度,无需调用 reszie() 方法 +## 1.1.7(2021-05-12) +- 新增 组件示例地址 +## 1.1.6(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 +## 1.1.5(2021-02-05) +- 调整为uni_modules目录规范 \ No newline at end of file diff --git a/uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue b/uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue new file mode 100644 index 0000000..d62a6a7 --- /dev/null +++ b/uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue @@ -0,0 +1,402 @@ + + + + + diff --git a/uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue b/uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue new file mode 100644 index 0000000..384c39a --- /dev/null +++ b/uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue @@ -0,0 +1,147 @@ + + + diff --git a/uni_modules/uni-collapse/package.json b/uni_modules/uni-collapse/package.json new file mode 100644 index 0000000..65349cf --- /dev/null +++ b/uni_modules/uni-collapse/package.json @@ -0,0 +1,89 @@ +{ + "id": "uni-collapse", + "displayName": "uni-collapse 折叠面板", + "version": "1.4.3", + "description": "Collapse 组件,可以折叠 / 展开的内容区域。", + "keywords": [ + "uni-ui", + "折叠", + "折叠面板", + "手风琴" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-collapse/readme.md b/uni_modules/uni-collapse/readme.md new file mode 100644 index 0000000..bc758eb --- /dev/null +++ b/uni_modules/uni-collapse/readme.md @@ -0,0 +1,12 @@ + + +## Collapse 折叠面板 +> **组件名:uni-collapse** +> 代码块: `uCollapse` +> 关联组件:`uni-collapse-item`、`uni-icons`。 + + +折叠面板用来折叠/显示过长的内容或者是列表。通常是在多内容分类项使用,折叠不重要的内容,显示重要内容。点击可以展开折叠部分。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-collapse) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-combox/changelog.md b/uni_modules/uni-combox/changelog.md new file mode 100644 index 0000000..23c2748 --- /dev/null +++ b/uni_modules/uni-combox/changelog.md @@ -0,0 +1,15 @@ +## 1.0.1(2021-11-23) +- 优化 label、label-width 属性 +## 1.0.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-combox](https://uniapp.dcloud.io/component/uniui/uni-combox) +## 0.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 0.0.6(2021-05-12) +- 新增 组件示例地址 +## 0.0.5(2021-04-21) +- 优化 添加依赖 uni-icons, 导入后自动下载依赖 +## 0.0.4(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 +## 0.0.3(2021-02-04) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-combox/components/uni-combox/uni-combox.vue b/uni_modules/uni-combox/components/uni-combox/uni-combox.vue new file mode 100644 index 0000000..500b6f8 --- /dev/null +++ b/uni_modules/uni-combox/components/uni-combox/uni-combox.vue @@ -0,0 +1,275 @@ + + + + + diff --git a/uni_modules/uni-combox/package.json b/uni_modules/uni-combox/package.json new file mode 100644 index 0000000..4a05c3f --- /dev/null +++ b/uni_modules/uni-combox/package.json @@ -0,0 +1,90 @@ +{ + "id": "uni-combox", + "displayName": "uni-combox 组合框", + "version": "1.0.1", + "description": "可以选择也可以输入的表单项 ", + "keywords": [ + "uni-ui", + "uniui", + "combox", + "组合框", + "select" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "n" + }, + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-combox/readme.md b/uni_modules/uni-combox/readme.md new file mode 100644 index 0000000..ffa2cc8 --- /dev/null +++ b/uni_modules/uni-combox/readme.md @@ -0,0 +1,11 @@ + + +## Combox 组合框 +> **组件名:uni-combox** +> 代码块: `uCombox` + + +组合框组件。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-combox) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-countdown/changelog.md b/uni_modules/uni-countdown/changelog.md new file mode 100644 index 0000000..f25beef --- /dev/null +++ b/uni_modules/uni-countdown/changelog.md @@ -0,0 +1,24 @@ +## 1.2.2(2022-01-19) +- 修复 在微信小程序中样式不生效的bug +## 1.2.1(2022-01-18) +- 新增 update 方法 ,在动态更新时间后,刷新组件 +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-countdown](https://uniapp.dcloud.io/component/uniui/uni-countdown) +## 1.1.3(2021-10-18) +- 重构 +- 新增 font-size 支持自定义字体大小 +## 1.1.2(2021-08-24) +- 新增 支持国际化 +## 1.1.1(2021-07-30) +- 优化 vue3下小程序事件警告的问题 +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.5(2021-06-18) +- 修复 uni-countdown 重复赋值跳两秒的 bug +## 1.0.4(2021-05-12) +- 新增 组件示例地址 +## 1.0.3(2021-05-08) +- 修复 uni-countdown 不能控制倒计时的 bug +## 1.0.2(2021-02-04) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-countdown/components/uni-countdown/i18n/en.json b/uni_modules/uni-countdown/components/uni-countdown/i18n/en.json new file mode 100644 index 0000000..06309cb --- /dev/null +++ b/uni_modules/uni-countdown/components/uni-countdown/i18n/en.json @@ -0,0 +1,6 @@ +{ + "uni-countdown.day": "day", + "uni-countdown.h": "h", + "uni-countdown.m": "m", + "uni-countdown.s": "s" +} diff --git a/uni_modules/uni-countdown/components/uni-countdown/i18n/index.js b/uni_modules/uni-countdown/components/uni-countdown/i18n/index.js new file mode 100644 index 0000000..de7509c --- /dev/null +++ b/uni_modules/uni-countdown/components/uni-countdown/i18n/index.js @@ -0,0 +1,8 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hans.json b/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hans.json new file mode 100644 index 0000000..358cdd1 --- /dev/null +++ b/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hans.json @@ -0,0 +1,6 @@ +{ + "uni-countdown.day": "天", + "uni-countdown.h": "时", + "uni-countdown.m": "分", + "uni-countdown.s": "秒" +} diff --git a/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hant.json b/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hant.json new file mode 100644 index 0000000..e5a63de --- /dev/null +++ b/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hant.json @@ -0,0 +1,6 @@ +{ + "uni-countdown.day": "天", + "uni-countdown.h": "時", + "uni-countdown.m": "分", + "uni-countdown.s": "秒" +} diff --git a/uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue b/uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue new file mode 100644 index 0000000..1f8ef4e --- /dev/null +++ b/uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue @@ -0,0 +1,271 @@ + + + diff --git a/uni_modules/uni-countdown/package.json b/uni_modules/uni-countdown/package.json new file mode 100644 index 0000000..70e99ee --- /dev/null +++ b/uni_modules/uni-countdown/package.json @@ -0,0 +1,86 @@ +{ + "id": "uni-countdown", + "displayName": "uni-countdown 倒计时", + "version": "1.2.2", + "description": "CountDown 倒计时组件", + "keywords": [ + "uni-ui", + "uniui", + "countdown", + "倒计时" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-countdown/readme.md b/uni_modules/uni-countdown/readme.md new file mode 100644 index 0000000..4bcb1aa --- /dev/null +++ b/uni_modules/uni-countdown/readme.md @@ -0,0 +1,10 @@ + + +## CountDown 倒计时 +> **组件名:uni-countdown** +> 代码块: `uCountDown` + +倒计时组件。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-countdown) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-data-checkbox/changelog.md b/uni_modules/uni-data-checkbox/changelog.md new file mode 100644 index 0000000..d8f420b --- /dev/null +++ b/uni_modules/uni-data-checkbox/changelog.md @@ -0,0 +1,41 @@ +## 1.0.1(2022-02-07) +- 修复 multiple 为 true 时,v-model 的值为 null 报错的 bug +## 1.0.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-data-checkbox](https://uniapp.dcloud.io/component/uniui/uni-data-checkbox) +## 0.2.5(2021-08-23) +- 修复 在uni-forms中 modelValue 中不存在当前字段,当前字段必填写也不参与校验的问题 +## 0.2.4(2021-08-17) +- 修复 单选 list 模式下 ,icon 为 left 时,选中图标不显示的问题 +## 0.2.3(2021-08-11) +- 修复 在 uni-forms 中重置表单,错误信息无法清除的问题 +## 0.2.2(2021-07-30) +- 优化 在uni-forms组件,与label不对齐的问题 +## 0.2.1(2021-07-27) +- 修复 单选默认值为0不能选中的Bug +## 0.2.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 0.1.11(2021-07-06) +- 优化 删除无用日志 +## 0.1.10(2021-07-05) +- 修复 由 0.1.9 引起的非 nvue 端图标不显示的问题 +## 0.1.9(2021-07-05) +- 修复 nvue 黑框样式问题 +## 0.1.8(2021-06-28) +- 修复 selectedTextColor 属性不生效的Bug +## 0.1.7(2021-06-02) +- 新增 map 属性,可以方便映射text/value属性 +## 0.1.6(2021-05-26) +- 修复 不关联服务空间的情况下组件报错的Bug +## 0.1.5(2021-05-12) +- 新增 组件示例地址 +## 0.1.4(2021-04-09) +- 修复 nvue 下无法选中的问题 +## 0.1.3(2021-03-22) +- 新增 disabled属性 +## 0.1.2(2021-02-24) +- 优化 默认颜色显示 +## 0.1.1(2021-02-24) +- 新增 支持nvue +## 0.1.0(2021-02-18) +- “暂无数据”显示居中 diff --git a/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue b/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue new file mode 100644 index 0000000..ccea7e9 --- /dev/null +++ b/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue @@ -0,0 +1,817 @@ + + + + + diff --git a/uni_modules/uni-data-checkbox/package.json b/uni_modules/uni-data-checkbox/package.json new file mode 100644 index 0000000..64131e7 --- /dev/null +++ b/uni_modules/uni-data-checkbox/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-data-checkbox", + "displayName": "uni-data-checkbox 数据选择器", + "version": "1.0.1", + "description": "通过数据驱动的单选框和复选框", + "keywords": [ + "uni-ui", + "checkbox", + "单选", + "多选", + "单选多选" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "^3.1.1" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-load-more","uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-data-checkbox/readme.md b/uni_modules/uni-data-checkbox/readme.md new file mode 100644 index 0000000..6eb253d --- /dev/null +++ b/uni_modules/uni-data-checkbox/readme.md @@ -0,0 +1,18 @@ + + +## DataCheckbox 数据驱动的单选复选框 +> **组件名:uni-data-checkbox** +> 代码块: `uDataCheckbox` + + +本组件是基于uni-app基础组件checkbox的封装。本组件要解决问题包括: + +1. 数据绑定型组件:给本组件绑定一个data,会自动渲染一组候选内容。再以往,开发者需要编写不少代码实现类似功能 +2. 自动的表单校验:组件绑定了data,且符合[uni-forms](https://ext.dcloud.net.cn/plugin?id=2773)组件的表单校验规范,搭配使用会自动实现表单校验 +3. 本组件合并了单选多选 +4. 本组件有若干风格选择,如普通的单选多选框、并列button风格、tag风格。开发者可以快速选择需要的风格。但作为一个封装组件,样式代码虽然不用自己写了,却会牺牲一定的样式自定义性 + +在uniCloud开发中,`DB Schema`中配置了enum枚举等类型后,在web控制台的[自动生成表单](https://uniapp.dcloud.io/uniCloud/schema?id=autocode)功能中,会自动生成``uni-data-checkbox``组件并绑定好data + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-data-checkbox) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-data-picker/changelog.md b/uni_modules/uni-data-picker/changelog.md new file mode 100644 index 0000000..486eedc --- /dev/null +++ b/uni_modules/uni-data-picker/changelog.md @@ -0,0 +1,56 @@ +## 1.0.3(2022-02-25) +- 修复 nvue 不支持的 v-show 的 bug +## 1.0.2(2022-02-25) +- 修复 条件编译 nvue 不支持的 css 样式 +## 1.0.1(2021-11-23) +- 修复 由上个版本引发的map、v-model等属性不生效的bug +## 1.0.0(2021-11-19) +- 优化 组件 UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-data-picker](https://uniapp.dcloud.io/component/uniui/uni-data-picker) +## 0.4.9(2021-10-28) +- 修复 VUE2 v-model 概率无效的 bug +## 0.4.8(2021-10-27) +- 修复 v-model 概率无效的 bug +## 0.4.7(2021-10-25) +- 新增 属性 spaceInfo 服务空间配置 HBuilderX 3.2.11+ +- 修复 树型 uniCloud 数据类型为 int 时报错的 bug +## 0.4.6(2021-10-19) +- 修复 非 VUE3 v-model 为 0 时无法选中的 bug +## 0.4.5(2021-09-26) +- 新增 清除已选项的功能(通过 clearIcon 属性配置是否显示按钮),同时提供 clear 方法以供调用,二者等效 +- 修复 readonly 为 true 时报错的 bug +## 0.4.4(2021-09-26) +- 修复 上一版本造成的 map 属性失效的 bug +- 新增 ellipsis 属性,支持配置 tab 选项长度过长时是否自动省略 +## 0.4.3(2021-09-24) +- 修复 某些情况下级联未触发的 bug +## 0.4.2(2021-09-23) +- 新增 提供 show 和 hide 方法,开发者可以通过 ref 调用 +- 新增 选项内容过长自动添加省略号 +## 0.4.1(2021-09-15) +- 新增 map 属性 字段映射,将 text/value 映射到数据中的其他字段 +## 0.4.0(2021-07-13) +- 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 0.3.5(2021-06-04) +- 修复 无法加载云端数据的问题 +## 0.3.4(2021-05-28) +- 修复 v-model 无效问题 +- 修复 loaddata 为空数据组时加载时间过长问题 +- 修复 上个版本引出的本地数据无法选择带有 children 的 2 级节点 +## 0.3.3(2021-05-12) +- 新增 组件示例地址 +## 0.3.2(2021-04-22) +- 修复 非树形数据有 where 属性查询报错的问题 +## 0.3.1(2021-04-15) +- 修复 本地数据概率无法回显时问题 +## 0.3.0(2021-04-07) +- 新增 支持云端非树形表结构数据 +- 修复 根节点 parent_field 字段等于 null 时选择界面错乱问题 +## 0.2.0(2021-03-15) +- 修复 nodeclick、popupopened、popupclosed 事件无法触发的问题 +## 0.1.9(2021-03-09) +- 修复 微信小程序某些情况下无法选择的问题 +## 0.1.8(2021-02-05) +- 优化 部分样式在 nvue 上的兼容表现 +## 0.1.7(2021-02-05) +- 调整为 uni_modules 目录规范 diff --git a/uni_modules/uni-data-picker/components/uni-data-picker/keypress.js b/uni_modules/uni-data-picker/components/uni-data-picker/keypress.js new file mode 100644 index 0000000..6ef26a2 --- /dev/null +++ b/uni_modules/uni-data-picker/components/uni-data-picker/keypress.js @@ -0,0 +1,45 @@ +// #ifdef H5 +export default { + name: 'Keypress', + props: { + disable: { + type: Boolean, + default: false + } + }, + mounted () { + const keyNames = { + esc: ['Esc', 'Escape'], + tab: 'Tab', + enter: 'Enter', + space: [' ', 'Spacebar'], + up: ['Up', 'ArrowUp'], + left: ['Left', 'ArrowLeft'], + right: ['Right', 'ArrowRight'], + down: ['Down', 'ArrowDown'], + delete: ['Backspace', 'Delete', 'Del'] + } + const listener = ($event) => { + if (this.disable) { + return + } + const keyName = Object.keys(keyNames).find(key => { + const keyName = $event.key + const value = keyNames[key] + return value === keyName || (Array.isArray(value) && value.includes(keyName)) + }) + if (keyName) { + // 避免和其他按键事件冲突 + setTimeout(() => { + this.$emit(keyName, {}) + }, 0) + } + } + document.addEventListener('keyup', listener) + this.$once('hook:beforeDestroy', () => { + document.removeEventListener('keyup', listener) + }) + }, + render: () => {} +} +// #endif diff --git a/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue b/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue new file mode 100644 index 0000000..a76af2e --- /dev/null +++ b/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue @@ -0,0 +1,539 @@ + + + + + diff --git a/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js new file mode 100644 index 0000000..c12fd54 --- /dev/null +++ b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js @@ -0,0 +1,563 @@ +export default { + props: { + localdata: { + type: [Array, Object], + default () { + return [] + } + }, + spaceInfo: { + type: Object, + default () { + return {} + } + }, + collection: { + type: String, + default: '' + }, + action: { + type: String, + default: '' + }, + field: { + type: String, + default: '' + }, + orderby: { + type: String, + default: '' + }, + where: { + type: [String, Object], + default: '' + }, + pageData: { + type: String, + default: 'add' + }, + pageCurrent: { + type: Number, + default: 1 + }, + pageSize: { + type: Number, + default: 20 + }, + getcount: { + type: [Boolean, String], + default: false + }, + getone: { + type: [Boolean, String], + default: false + }, + gettree: { + type: [Boolean, String], + default: false + }, + manual: { + type: Boolean, + default: false + }, + value: { + type: [Array, String, Number], + default () { + return [] + } + }, + modelValue: { + type: [Array, String, Number], + default () { + return [] + } + }, + preload: { + type: Boolean, + default: false + }, + stepSearh: { + type: Boolean, + default: true + }, + selfField: { + type: String, + default: '' + }, + parentField: { + type: String, + default: '' + }, + multiple: { + type: Boolean, + default: false + }, + map: { + type: Object, + default() { + return { + text: "text", + value: "value" + } + } + } + }, + data() { + return { + loading: false, + errorMessage: '', + loadMore: { + contentdown: '', + contentrefresh: '', + contentnomore: '' + }, + dataList: [], + selected: [], + selectedIndex: 0, + page: { + current: this.pageCurrent, + size: this.pageSize, + count: 0 + } + } + }, + computed: { + isLocaldata() { + return !this.collection.length + }, + postField() { + let fields = [this.field]; + if (this.parentField) { + fields.push(`${this.parentField} as parent_value`); + } + return fields.join(','); + }, + dataValue() { + let isModelValue = Array.isArray(this.modelValue) ? (this.modelValue.length > 0) : (this.modelValue !== null || this.modelValue !== undefined) + return isModelValue ? this.modelValue : this.value + }, + hasValue() { + if (typeof this.dataValue === 'number') { + return true + } + return (this.dataValue != null) && (this.dataValue.length > 0) + } + }, + created() { + this.$watch(() => { + var al = []; + ['pageCurrent', + 'pageSize', + 'spaceInfo', + 'value', + 'modelValue', + 'localdata', + 'collection', + 'action', + 'field', + 'orderby', + 'where', + 'getont', + 'getcount', + 'gettree' + ].forEach(key => { + al.push(this[key]) + }); + return al + }, (newValue, oldValue) => { + let needReset = false + for (let i = 2; i < newValue.length; i++) { + if (newValue[i] != oldValue[i]) { + needReset = true + break + } + } + if (newValue[0] != oldValue[0]) { + this.page.current = this.pageCurrent + } + this.page.size = this.pageSize + + this.onPropsChange() + }) + this._treeData = [] + }, + methods: { + onPropsChange() { + this._treeData = [] + }, + getCommand(options = {}) { + /* eslint-disable no-undef */ + let db = uniCloud.database(this.spaceInfo) + + const action = options.action || this.action + if (action) { + db = db.action(action) + } + + const collection = options.collection || this.collection + db = db.collection(collection) + + const where = options.where || this.where + if (!(!where || !Object.keys(where).length)) { + db = db.where(where) + } + + const field = options.field || this.field + if (field) { + db = db.field(field) + } + + const orderby = options.orderby || this.orderby + if (orderby) { + db = db.orderBy(orderby) + } + + const current = options.pageCurrent !== undefined ? options.pageCurrent : this.page.current + const size = options.pageSize !== undefined ? options.pageSize : this.page.size + const getCount = options.getcount !== undefined ? options.getcount : this.getcount + const getTree = options.gettree !== undefined ? options.gettree : this.gettree + + const getOptions = { + getCount, + getTree + } + if (options.getTreePath) { + getOptions.getTreePath = options.getTreePath + } + + db = db.skip(size * (current - 1)).limit(size).get(getOptions) + + return db + }, + getNodeData(callback) { + if (this.loading) { + return + } + this.loading = true + this.getCommand({ + field: this.postField, + where: this._pathWhere() + }).then((res) => { + this.loading = false + this.selected = res.result.data + callback && callback() + }).catch((err) => { + this.loading = false + this.errorMessage = err + }) + }, + getTreePath(callback) { + if (this.loading) { + return + } + this.loading = true + + this.getCommand({ + field: this.postField, + getTreePath: { + startWith: `${this.selfField}=='${this.dataValue}'` + } + }).then((res) => { + this.loading = false + let treePath = [] + this._extractTreePath(res.result.data, treePath) + this.selected = treePath + callback && callback() + }).catch((err) => { + this.loading = false + this.errorMessage = err + }) + }, + loadData() { + if (this.isLocaldata) { + this._processLocalData() + return + } + + if (this.dataValue != null) { + this._loadNodeData((data) => { + this._treeData = data + this._updateBindData() + this._updateSelected() + }) + return + } + + if (this.stepSearh) { + this._loadNodeData((data) => { + this._treeData = data + this._updateBindData() + }) + } else { + this._loadAllData((data) => { + this._treeData = [] + this._extractTree(data, this._treeData, null) + this._updateBindData() + }) + } + }, + _loadAllData(callback) { + if (this.loading) { + return + } + this.loading = true + + this.getCommand({ + field: this.postField, + gettree: true, + startwith: `${this.selfField}=='${this.dataValue}'` + }).then((res) => { + this.loading = false + callback(res.result.data) + this.onDataChange() + }).catch((err) => { + this.loading = false + this.errorMessage = err + }) + }, + _loadNodeData(callback, pw) { + if (this.loading) { + return + } + this.loading = true + + this.getCommand({ + field: this.postField, + where: pw || this._postWhere(), + pageSize: 500 + }).then((res) => { + this.loading = false + callback(res.result.data) + this.onDataChange() + }).catch((err) => { + this.loading = false + this.errorMessage = err + }) + }, + _pathWhere() { + let result = [] + let where_field = this._getParentNameByField(); + if (where_field) { + result.push(`${where_field} == '${this.dataValue}'`) + } + + if (this.where) { + return `(${this.where}) && (${result.join(' || ')})` + } + + return result.join(' || ') + }, + _postWhere() { + let result = [] + let selected = this.selected + let parentField = this.parentField + if (parentField) { + result.push(`${parentField} == null || ${parentField} == ""`) + } + if (selected.length) { + for (var i = 0; i < selected.length - 1; i++) { + result.push(`${parentField} == '${selected[i].value}'`) + } + } + + let where = [] + if (this.where) { + where.push(`(${this.where})`) + } + if (result.length) { + where.push(`(${result.join(' || ')})`) + } + + return where.join(' && ') + }, + _nodeWhere() { + let result = [] + let selected = this.selected + if (selected.length) { + result.push(`${this.parentField} == '${selected[selected.length - 1].value}'`) + } + + if (this.where) { + return `(${this.where}) && (${result.join(' || ')})` + } + + return result.join(' || ') + }, + _getParentNameByField() { + const fields = this.field.split(','); + let where_field = null; + for (let i = 0; i < fields.length; i++) { + const items = fields[i].split('as'); + if (items.length < 2) { + continue; + } + if (items[1].trim() === 'value') { + where_field = items[0].trim(); + break; + } + } + return where_field + }, + _isTreeView() { + return (this.parentField && this.selfField) + }, + _updateSelected() { + var dl = this.dataList + var sl = this.selected + let textField = this.map.text + let valueField = this.map.value + for (var i = 0; i < sl.length; i++) { + var value = sl[i].value + var dl2 = dl[i] + for (var j = 0; j < dl2.length; j++) { + var item2 = dl2[j] + if (item2[valueField] === value) { + sl[i].text = item2[textField] + break + } + } + } + }, + _updateBindData(node) { + const { + dataList, + hasNodes + } = this._filterData(this._treeData, this.selected) + + let isleaf = this._stepSearh === false && !hasNodes + + if (node) { + node.isleaf = isleaf + } + + this.dataList = dataList + this.selectedIndex = dataList.length - 1 + + if (!isleaf && this.selected.length < dataList.length) { + this.selected.push({ + value: null, + text: "请选择" + }) + } + + return { + isleaf, + hasNodes + } + }, + _filterData(data, paths) { + let dataList = [] + let hasNodes = true + + dataList.push(data.filter((item) => { + return (item.parent_value === null || item.parent_value === undefined || item.parent_value === '') + })) + for (let i = 0; i < paths.length; i++) { + var value = paths[i].value + var nodes = data.filter((item) => { + return item.parent_value === value + }) + + if (nodes.length) { + dataList.push(nodes) + } else { + hasNodes = false + } + } + + return { + dataList, + hasNodes + } + }, + _extractTree(nodes, result, parent_value) { + let list = result || [] + let valueField = this.map.value + for (let i = 0; i < nodes.length; i++) { + let node = nodes[i] + + let child = {} + for (let key in node) { + if (key !== 'children') { + child[key] = node[key] + } + } + if (parent_value !== null && parent_value !== undefined && parent_value !== '') { + child.parent_value = parent_value + } + result.push(child) + + let children = node.children + if (children) { + this._extractTree(children, result, node[valueField]) + } + } + }, + _extractTreePath(nodes, result) { + let list = result || [] + for (let i = 0; i < nodes.length; i++) { + let node = nodes[i] + + let child = {} + for (let key in node) { + if (key !== 'children') { + child[key] = node[key] + } + } + result.push(child) + + let children = node.children + if (children) { + this._extractTreePath(children, result) + } + } + }, + _findNodePath(key, nodes, path = []) { + let textField = this.map.text + let valueField = this.map.value + for (let i = 0; i < nodes.length; i++) { + let node = nodes[i] + let children = node.children + let text = node[textField] + let value = node[valueField] + + path.push({ + value, + text + }) + + if (value === key) { + return path + } + + if (children) { + const p = this._findNodePath(key, children, path) + if (p.length) { + return p + } + } + + path.pop() + } + return [] + }, + _processLocalData() { + this._treeData = [] + this._extractTree(this.localdata, this._treeData) + + var inputValue = this.dataValue + if (inputValue === undefined) { + return + } + + if (Array.isArray(inputValue)) { + inputValue = inputValue[inputValue.length - 1] + if (typeof inputValue === 'object' && inputValue[this.map.value]) { + inputValue = inputValue[this.map.value] + } + } + + this.selected = this._findNodePath(inputValue, this.localdata) + } + } +} diff --git a/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue new file mode 100644 index 0000000..72f8b33 --- /dev/null +++ b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue @@ -0,0 +1,333 @@ + + + + diff --git a/uni_modules/uni-data-picker/package.json b/uni_modules/uni-data-picker/package.json new file mode 100644 index 0000000..d4925ef --- /dev/null +++ b/uni_modules/uni-data-picker/package.json @@ -0,0 +1,92 @@ +{ + "id": "uni-data-picker", + "displayName": "uni-data-picker 数据驱动的picker选择器", + "version": "1.0.3", + "description": "单列、多列级联选择器,常用于省市区城市选择、公司部门选择、多级分类等场景", + "keywords": [ + "uni-ui", + "uniui", + "picker", + "级联", + "省市区", + "" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-load-more", + "uni-icons", + "uni-scss" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-data-picker/readme.md b/uni_modules/uni-data-picker/readme.md new file mode 100644 index 0000000..6cda224 --- /dev/null +++ b/uni_modules/uni-data-picker/readme.md @@ -0,0 +1,22 @@ +## DataPicker 级联选择 +> **组件名:uni-data-picker** +> 代码块: `uDataPicker` +> 关联组件:`uni-data-pickerview`、`uni-load-more`。 + + +`` 是一个选择类[datacom组件](https://uniapp.dcloud.net.cn/component/datacom)。 + +支持单列、和多列级联选择。列数没有限制,如果屏幕显示不全,顶部tab区域会左右滚动。 + +候选数据支持一次性加载完毕,也支持懒加载,比如示例图中,选择了“北京”后,动态加载北京的区县数据。 + +`` 组件尤其适用于地址选择、分类选择等选择类。 + +`` 支持本地数据、云端静态数据(json),uniCloud云数据库数据。 + +`` 可以通过JQL直连uniCloud云数据库,配套[DB Schema](https://uniapp.dcloud.net.cn/uniCloud/schema),可在schema2code中自动生成前端页面,还支持服务器端校验。 + +在uniCloud数据表中新建表“uni-id-address”和“opendb-city-china”,这2个表的schema自带foreignKey关联。在“uni-id-address”表的表结构页面使用schema2code生成前端页面,会自动生成地址管理的维护页面,自动从“opendb-city-china”表包含的中国所有省市区信息里选择地址。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-data-picker) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-dateformat/changelog.md b/uni_modules/uni-dateformat/changelog.md new file mode 100644 index 0000000..d551d7b --- /dev/null +++ b/uni_modules/uni-dateformat/changelog.md @@ -0,0 +1,10 @@ +## 1.0.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-dateformat](https://uniapp.dcloud.io/component/uniui/uni-dateformat) +## 0.0.5(2021-07-08) +- 调整 默认时间不再是当前时间,而是显示'-'字符 +## 0.0.4(2021-05-12) +- 新增 组件示例地址 +## 0.0.3(2021-02-04) +- 调整为uni_modules目录规范 +- 修复 iOS 平台日期格式化出错的问题 diff --git a/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js b/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js new file mode 100644 index 0000000..e00d559 --- /dev/null +++ b/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js @@ -0,0 +1,200 @@ +// yyyy-MM-dd hh:mm:ss.SSS 所有支持的类型 +function pad(str, length = 2) { + str += '' + while (str.length < length) { + str = '0' + str + } + return str.slice(-length) +} + +const parser = { + yyyy: (dateObj) => { + return pad(dateObj.year, 4) + }, + yy: (dateObj) => { + return pad(dateObj.year) + }, + MM: (dateObj) => { + return pad(dateObj.month) + }, + M: (dateObj) => { + return dateObj.month + }, + dd: (dateObj) => { + return pad(dateObj.day) + }, + d: (dateObj) => { + return dateObj.day + }, + hh: (dateObj) => { + return pad(dateObj.hour) + }, + h: (dateObj) => { + return dateObj.hour + }, + mm: (dateObj) => { + return pad(dateObj.minute) + }, + m: (dateObj) => { + return dateObj.minute + }, + ss: (dateObj) => { + return pad(dateObj.second) + }, + s: (dateObj) => { + return dateObj.second + }, + SSS: (dateObj) => { + return pad(dateObj.millisecond, 3) + }, + S: (dateObj) => { + return dateObj.millisecond + }, +} + +// 这都n年了iOS依然不认识2020-12-12,需要转换为2020/12/12 +function getDate(time) { + if (time instanceof Date) { + return time + } + switch (typeof time) { + case 'string': + { + // 2020-12-12T12:12:12.000Z、2020-12-12T12:12:12.000 + if (time.indexOf('T') > -1) { + return new Date(time) + } + return new Date(time.replace(/-/g, '/')) + } + default: + return new Date(time) + } +} + +export function formatDate(date, format = 'yyyy/MM/dd hh:mm:ss') { + if (!date && date !== 0) { + return '' + } + date = getDate(date) + const dateObj = { + year: date.getFullYear(), + month: date.getMonth() + 1, + day: date.getDate(), + hour: date.getHours(), + minute: date.getMinutes(), + second: date.getSeconds(), + millisecond: date.getMilliseconds() + } + const tokenRegExp = /yyyy|yy|MM|M|dd|d|hh|h|mm|m|ss|s|SSS|SS|S/ + let flag = true + let result = format + while (flag) { + flag = false + result = result.replace(tokenRegExp, function(matched) { + flag = true + return parser[matched](dateObj) + }) + } + return result +} + +export function friendlyDate(time, { + locale = 'zh', + threshold = [60000, 3600000], + format = 'yyyy/MM/dd hh:mm:ss' +}) { + if (time === '-') { + return time + } + if (!time && time !== 0) { + return '' + } + const localeText = { + zh: { + year: '年', + month: '月', + day: '天', + hour: '小时', + minute: '分钟', + second: '秒', + ago: '前', + later: '后', + justNow: '刚刚', + soon: '马上', + template: '{num}{unit}{suffix}' + }, + en: { + year: 'year', + month: 'month', + day: 'day', + hour: 'hour', + minute: 'minute', + second: 'second', + ago: 'ago', + later: 'later', + justNow: 'just now', + soon: 'soon', + template: '{num} {unit} {suffix}' + } + } + const text = localeText[locale] || localeText.zh + let date = getDate(time) + let ms = date.getTime() - Date.now() + let absMs = Math.abs(ms) + if (absMs < threshold[0]) { + return ms < 0 ? text.justNow : text.soon + } + if (absMs >= threshold[1]) { + return formatDate(date, format) + } + let num + let unit + let suffix = text.later + if (ms < 0) { + suffix = text.ago + ms = -ms + } + const seconds = Math.floor((ms) / 1000) + const minutes = Math.floor(seconds / 60) + const hours = Math.floor(minutes / 60) + const days = Math.floor(hours / 24) + const months = Math.floor(days / 30) + const years = Math.floor(months / 12) + switch (true) { + case years > 0: + num = years + unit = text.year + break + case months > 0: + num = months + unit = text.month + break + case days > 0: + num = days + unit = text.day + break + case hours > 0: + num = hours + unit = text.hour + break + case minutes > 0: + num = minutes + unit = text.minute + break + default: + num = seconds + unit = text.second + break + } + + if (locale === 'en') { + if (num === 1) { + num = 'a' + } else { + unit += 's' + } + } + + return text.template.replace(/{\s*num\s*}/g, num + '').replace(/{\s*unit\s*}/g, unit).replace(/{\s*suffix\s*}/g, + suffix) +} diff --git a/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue b/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue new file mode 100644 index 0000000..c5ed030 --- /dev/null +++ b/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/uni_modules/uni-dateformat/package.json b/uni_modules/uni-dateformat/package.json new file mode 100644 index 0000000..786a670 --- /dev/null +++ b/uni_modules/uni-dateformat/package.json @@ -0,0 +1,88 @@ +{ + "id": "uni-dateformat", + "displayName": "uni-dateformat 日期格式化", + "version": "1.0.0", + "description": "日期格式化组件,可以将日期格式化为1分钟前、刚刚等形式", + "keywords": [ + "uni-ui", + "uniui", + "日期格式化", + "时间格式化", + "格式化时间", + "" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-dateformat/readme.md b/uni_modules/uni-dateformat/readme.md new file mode 100644 index 0000000..37ddb6e --- /dev/null +++ b/uni_modules/uni-dateformat/readme.md @@ -0,0 +1,11 @@ + + +### DateFormat 日期格式化 +> **组件名:uni-dateformat** +> 代码块: `uDateformat` + + +日期格式化组件。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-dateformat) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-datetime-picker/changelog.md b/uni_modules/uni-datetime-picker/changelog.md new file mode 100644 index 0000000..9611a30 --- /dev/null +++ b/uni_modules/uni-datetime-picker/changelog.md @@ -0,0 +1,89 @@ +## 2.2.4(2022-03-31) +- 修复 Vue3 下动态赋值,单选类型未响应的 bug +## 2.2.3(2022-03-28) +- 修复 Vue3 下动态赋值未响应的 bug +## 2.2.2(2021-12-10) +- 修复 clear-icon 属性在小程序平台不生效的 bug +## 2.2.1(2021-12-10) +- 修复 日期范围选在小程序平台,必须多点击一次才能取消选中状态的 bug +## 2.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-datetime-picker](https://uniapp.dcloud.io/component/uniui/uni-datetime-picker) +## 2.1.5(2021-11-09) +- 新增 提供组件设计资源,组件样式调整 +## 2.1.4(2021-09-10) +- 修复 hide-second 在移动端的 bug +- 修复 单选赋默认值时,赋值日期未高亮的 bug +- 修复 赋默认值时,移动端未正确显示时间的 bug +## 2.1.3(2021-09-09) +- 新增 hide-second 属性,支持只使用时分,隐藏秒 +## 2.1.2(2021-09-03) +- 优化 取消选中时(范围选)直接开始下一次选择, 避免多点一次 +- 优化 移动端支持清除按钮,同时支持通过 ref 调用组件的 clear 方法 +- 优化 调整字号大小,美化日历界面 +- 修复 因国际化导致的 placeholder 失效的 bug +## 2.1.1(2021-08-24) +- 新增 支持国际化 +- 优化 范围选择器在 pc 端过宽的问题 +## 2.1.0(2021-08-09) +- 新增 适配 vue3 +## 2.0.19(2021-08-09) +- 新增 支持作为 uni-forms 子组件相关功能 +- 修复 在 uni-forms 中使用时,选择时间报 NAN 错误的 bug +## 2.0.18(2021-08-05) +- 修复 type 属性动态赋值无效的 bug +- 修复 ‘确认’按钮被 tabbar 遮盖 bug +- 修复 组件未赋值时范围选左、右日历相同的 bug +## 2.0.17(2021-08-04) +- 修复 范围选未正确显示当前值的 bug +- 修复 h5 平台(移动端)报错 'cale' of undefined 的 bug +## 2.0.16(2021-07-21) +- 新增 return-type 属性支持返回 date 日期对象 +## 2.0.15(2021-07-14) +- 修复 单选日期类型,初始赋值后不在当前日历的 bug +- 新增 clearIcon 属性,显示框的清空按钮可配置显示隐藏(仅 pc 有效) +- 优化 移动端移除显示框的清空按钮,无实际用途 +## 2.0.14(2021-07-14) +- 修复 组件赋值为空,界面未更新的 bug +- 修复 start 和 end 不能动态赋值的 bug +- 修复 范围选类型,用户选择后再次选择右侧日历(结束日期)显示不正确的 bug +## 2.0.13(2021-07-08) +- 修复 范围选择不能动态赋值的 bug +## 2.0.12(2021-07-08) +- 修复 范围选择的初始时间在一个月内时,造成无法选择的bug +## 2.0.11(2021-07-08) +- 优化 弹出层在超出视窗边缘定位不准确的问题 +## 2.0.10(2021-07-08) +- 修复 范围起始点样式的背景色与今日样式的字体前景色融合,导致日期字体看不清的 bug +- 优化 弹出层在超出视窗边缘被遮盖的问题 +## 2.0.9(2021-07-07) +- 新增 maskClick 事件 +- 修复 特殊情况日历 rpx 布局错误的 bug,rpx -> px +- 修复 范围选择时清空返回值不合理的bug,['', ''] -> [] +## 2.0.8(2021-07-07) +- 新增 日期时间显示框支持插槽 +## 2.0.7(2021-07-01) +- 优化 添加 uni-icons 依赖 +## 2.0.6(2021-05-22) +- 修复 图标在小程序上不显示的 bug +- 优化 重命名引用组件,避免潜在组件命名冲突 +## 2.0.5(2021-05-20) +- 优化 代码目录扁平化 +## 2.0.4(2021-05-12) +- 新增 组件示例地址 +## 2.0.3(2021-05-10) +- 修复 ios 下不识别 '-' 日期格式的 bug +- 优化 pc 下弹出层添加边框和阴影 +## 2.0.2(2021-05-08) +- 修复 在 admin 中获取弹出层定位错误的bug +## 2.0.1(2021-05-08) +- 修复 type 属性向下兼容,默认值从 date 变更为 datetime +## 2.0.0(2021-04-30) +- 支持日历形式的日期+时间的范围选择 + > 注意:此版本不向后兼容,不再支持单独时间选择(type=time)及相关的 hide-second 属性(时间选可使用内置组件 picker) +## 1.0.6(2021-03-18) +- 新增 hide-second 属性,时间支持仅选择时、分 +- 修复 选择跟显示的日期不一样的 bug +- 修复 chang事件触发2次的 bug +- 修复 分、秒 end 范围错误的 bug +- 优化 更好的 nvue 适配 diff --git a/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue new file mode 100644 index 0000000..3d2dbea --- /dev/null +++ b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue @@ -0,0 +1,185 @@ + + + + + diff --git a/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue new file mode 100644 index 0000000..f05adaf --- /dev/null +++ b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue @@ -0,0 +1,898 @@ + + + + + diff --git a/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json new file mode 100644 index 0000000..cc76311 --- /dev/null +++ b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json @@ -0,0 +1,19 @@ +{ + "uni-datetime-picker.selectDate": "select date", + "uni-datetime-picker.selectTime": "select time", + "uni-datetime-picker.selectDateTime": "select datetime", + "uni-datetime-picker.startDate": "start date", + "uni-datetime-picker.endDate": "end date", + "uni-datetime-picker.startTime": "start time", + "uni-datetime-picker.endTime": "end time", + "uni-datetime-picker.ok": "ok", + "uni-datetime-picker.clear": "clear", + "uni-datetime-picker.cancel": "cancel", + "uni-calender.MON": "MON", + "uni-calender.TUE": "TUE", + "uni-calender.WED": "WED", + "uni-calender.THU": "THU", + "uni-calender.FRI": "FRI", + "uni-calender.SAT": "SAT", + "uni-calender.SUN": "SUN" +} diff --git a/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/index.js b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/index.js new file mode 100644 index 0000000..de7509c --- /dev/null +++ b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/index.js @@ -0,0 +1,8 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hans.json b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hans.json new file mode 100644 index 0000000..7bc7405 --- /dev/null +++ b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hans.json @@ -0,0 +1,19 @@ +{ + "uni-datetime-picker.selectDate": "选择日期", + "uni-datetime-picker.selectTime": "选择时间", + "uni-datetime-picker.selectDateTime": "选择日期时间", + "uni-datetime-picker.startDate": "开始日期", + "uni-datetime-picker.endDate": "结束日期", + "uni-datetime-picker.startTime": "开始时间", + "uni-datetime-picker.endTime": "结束时间", + "uni-datetime-picker.ok": "确定", + "uni-datetime-picker.clear": "清除", + "uni-datetime-picker.cancel": "取消", + "uni-calender.SUN": "日", + "uni-calender.MON": "一", + "uni-calender.TUE": "二", + "uni-calender.WED": "三", + "uni-calender.THU": "四", + "uni-calender.FRI": "五", + "uni-calender.SAT": "六" +} diff --git a/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hant.json b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hant.json new file mode 100644 index 0000000..7d37043 --- /dev/null +++ b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hant.json @@ -0,0 +1,19 @@ +{ + "uni-datetime-picker.selectDate": "選擇日期", + "uni-datetime-picker.selectTime": "選擇時間", + "uni-datetime-picker.selectDateTime": "選擇日期時間", + "uni-datetime-picker.startDate": "開始日期", + "uni-datetime-picker.endDate": "結束日期", + "uni-datetime-picker.startTime": "開始时间", + "uni-datetime-picker.endTime": "結束时间", + "uni-datetime-picker.ok": "確定", + "uni-datetime-picker.clear": "清除", + "uni-datetime-picker.cancel": "取消", + "uni-calender.SUN": "日", + "uni-calender.MON": "一", + "uni-calender.TUE": "二", + "uni-calender.WED": "三", + "uni-calender.THU": "四", + "uni-calender.FRI": "五", + "uni-calender.SAT": "六" +} diff --git a/uni_modules/uni-datetime-picker/components/uni-datetime-picker/keypress.js b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/keypress.js new file mode 100644 index 0000000..9601aba --- /dev/null +++ b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/keypress.js @@ -0,0 +1,45 @@ +// #ifdef H5 +export default { + name: 'Keypress', + props: { + disable: { + type: Boolean, + default: false + } + }, + mounted () { + const keyNames = { + esc: ['Esc', 'Escape'], + tab: 'Tab', + enter: 'Enter', + space: [' ', 'Spacebar'], + up: ['Up', 'ArrowUp'], + left: ['Left', 'ArrowLeft'], + right: ['Right', 'ArrowRight'], + down: ['Down', 'ArrowDown'], + delete: ['Backspace', 'Delete', 'Del'] + } + const listener = ($event) => { + if (this.disable) { + return + } + const keyName = Object.keys(keyNames).find(key => { + const keyName = $event.key + const value = keyNames[key] + return value === keyName || (Array.isArray(value) && value.includes(keyName)) + }) + if (keyName) { + // 避免和其他按键事件冲突 + setTimeout(() => { + this.$emit(keyName, {}) + }, 0) + } + } + document.addEventListener('keyup', listener) + this.$once('hook:beforeDestroy', () => { + document.removeEventListener('keyup', listener) + }) + }, + render: () => {} +} +// #endif \ No newline at end of file diff --git a/uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue new file mode 100644 index 0000000..699aa63 --- /dev/null +++ b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue @@ -0,0 +1,927 @@ + + + + + diff --git a/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue new file mode 100644 index 0000000..ea00857 --- /dev/null +++ b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue @@ -0,0 +1,997 @@ + + + + diff --git a/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js new file mode 100644 index 0000000..efa5773 --- /dev/null +++ b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js @@ -0,0 +1,410 @@ +class Calendar { + constructor({ + date, + selected, + startDate, + endDate, + range, + // multipleStatus + } = {}) { + // 当前日期 + this.date = this.getDate(new Date()) // 当前初入日期 + // 打点信息 + this.selected = selected || []; + // 范围开始 + this.startDate = startDate + // 范围结束 + this.endDate = endDate + this.range = range + // 多选状态 + this.cleanMultipleStatus() + // 每周日期 + this.weeks = {} + // this._getWeek(this.date.fullDate) + // this.multipleStatus = multipleStatus + this.lastHover = false + } + /** + * 设置日期 + * @param {Object} date + */ + setDate(date) { + this.selectDate = this.getDate(date) + this._getWeek(this.selectDate.fullDate) + } + + /** + * 清理多选状态 + */ + cleanMultipleStatus() { + this.multipleStatus = { + before: '', + after: '', + data: [] + } + } + + /** + * 重置开始日期 + */ + resetSatrtDate(startDate) { + // 范围开始 + this.startDate = startDate + + } + + /** + * 重置结束日期 + */ + resetEndDate(endDate) { + // 范围结束 + this.endDate = endDate + } + + /** + * 获取任意时间 + */ + getDate(date, AddDayCount = 0, str = 'day') { + if (!date) { + date = new Date() + } + if (typeof date !== 'object') { + date = date.replace(/-/g, '/') + } + const dd = new Date(date) + switch (str) { + case 'day': + dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期 + break + case 'month': + if (dd.getDate() === 31) { + dd.setDate(dd.getDate() + AddDayCount) + } else { + dd.setMonth(dd.getMonth() + AddDayCount) // 获取AddDayCount天后的日期 + } + break + case 'year': + dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期 + break + } + const y = dd.getFullYear() + const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期,不足10补0 + const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号,不足10补0 + return { + fullDate: y + '-' + m + '-' + d, + year: y, + month: m, + date: d, + day: dd.getDay() + } + } + + + /** + * 获取上月剩余天数 + */ + _getLastMonthDays(firstDay, full) { + let dateArr = [] + for (let i = firstDay; i > 0; i--) { + const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate() + dateArr.push({ + date: beforeDate, + month: full.month - 1, + disable: true + }) + } + return dateArr + } + /** + * 获取本月天数 + */ + _currentMonthDys(dateData, full) { + let dateArr = [] + let fullDate = this.date.fullDate + for (let i = 1; i <= dateData; i++) { + let isinfo = false + let nowDate = full.year + '-' + (full.month < 10 ? + full.month : full.month) + '-' + (i < 10 ? + '0' + i : i) + // 是否今天 + let isDay = fullDate === nowDate + // 获取打点信息 + let info = this.selected && this.selected.find((item) => { + if (this.dateEqual(nowDate, item.date)) { + return item + } + }) + + // 日期禁用 + let disableBefore = true + let disableAfter = true + if (this.startDate) { + // let dateCompBefore = this.dateCompare(this.startDate, fullDate) + // disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate) + disableBefore = this.dateCompare(this.startDate, nowDate) + } + + if (this.endDate) { + // let dateCompAfter = this.dateCompare(fullDate, this.endDate) + // disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate) + disableAfter = this.dateCompare(nowDate, this.endDate) + } + let multiples = this.multipleStatus.data + let checked = false + let multiplesStatus = -1 + if (this.range) { + if (multiples) { + multiplesStatus = multiples.findIndex((item) => { + return this.dateEqual(item, nowDate) + }) + } + if (multiplesStatus !== -1) { + checked = true + } + } + let data = { + fullDate: nowDate, + year: full.year, + date: i, + multiple: this.range ? checked : false, + beforeMultiple: this.isLogicBefore(nowDate, this.multipleStatus.before, this.multipleStatus.after), + afterMultiple: this.isLogicAfter(nowDate, this.multipleStatus.before, this.multipleStatus.after), + month: full.month, + disable: !(disableBefore && disableAfter), + isDay, + userChecked: false + } + if (info) { + data.extraInfo = info + } + + dateArr.push(data) + } + return dateArr + } + /** + * 获取下月天数 + */ + _getNextMonthDays(surplus, full) { + let dateArr = [] + for (let i = 1; i < surplus + 1; i++) { + dateArr.push({ + date: i, + month: Number(full.month) + 1, + disable: true + }) + } + return dateArr + } + + /** + * 获取当前日期详情 + * @param {Object} date + */ + getInfo(date) { + if (!date) { + date = new Date() + } + const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate) + return dateInfo + } + + /** + * 比较时间大小 + */ + dateCompare(startDate, endDate) { + // 计算截止时间 + startDate = new Date(startDate.replace('-', '/').replace('-', '/')) + // 计算详细项的截止时间 + endDate = new Date(endDate.replace('-', '/').replace('-', '/')) + if (startDate <= endDate) { + return true + } else { + return false + } + } + + /** + * 比较时间是否相等 + */ + dateEqual(before, after) { + // 计算截止时间 + before = new Date(before.replace('-', '/').replace('-', '/')) + // 计算详细项的截止时间 + after = new Date(after.replace('-', '/').replace('-', '/')) + if (before.getTime() - after.getTime() === 0) { + return true + } else { + return false + } + } + + /** + * 比较真实起始日期 + */ + + isLogicBefore(currentDay, before, after) { + let logicBefore = before + if (before && after) { + logicBefore = this.dateCompare(before, after) ? before : after + } + return this.dateEqual(logicBefore, currentDay) + } + + isLogicAfter(currentDay, before, after) { + let logicAfter = after + if (before && after) { + logicAfter = this.dateCompare(before, after) ? after : before + } + return this.dateEqual(logicAfter, currentDay) + } + + /** + * 获取日期范围内所有日期 + * @param {Object} begin + * @param {Object} end + */ + geDateAll(begin, end) { + var arr = [] + var ab = begin.split('-') + var ae = end.split('-') + var db = new Date() + db.setFullYear(ab[0], ab[1] - 1, ab[2]) + var de = new Date() + de.setFullYear(ae[0], ae[1] - 1, ae[2]) + var unixDb = db.getTime() - 24 * 60 * 60 * 1000 + var unixDe = de.getTime() - 24 * 60 * 60 * 1000 + for (var k = unixDb; k <= unixDe;) { + k = k + 24 * 60 * 60 * 1000 + arr.push(this.getDate(new Date(parseInt(k))).fullDate) + } + return arr + } + + /** + * 获取多选状态 + */ + setMultiple(fullDate) { + let { + before, + after + } = this.multipleStatus + if (!this.range) return + if (before && after) { + if (!this.lastHover) { + this.lastHover = true + return + } + this.multipleStatus.before = fullDate + this.multipleStatus.after = '' + this.multipleStatus.data = [] + this.multipleStatus.fulldate = '' + this.lastHover = false + } else { + if (!before) { + this.multipleStatus.before = fullDate + this.lastHover = false + } else { + this.multipleStatus.after = fullDate + if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) { + this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus + .after); + } else { + this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus + .before); + } + this.lastHover = true + } + } + this._getWeek(fullDate) + } + + /** + * 鼠标 hover 更新多选状态 + */ + setHoverMultiple(fullDate) { + let { + before, + after + } = this.multipleStatus + + if (!this.range) return + if (this.lastHover) return + + if (!before) { + this.multipleStatus.before = fullDate + } else { + this.multipleStatus.after = fullDate + if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) { + this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after); + } else { + this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before); + } + } + this._getWeek(fullDate) + } + + /** + * 更新默认值多选状态 + */ + setDefaultMultiple(before, after) { + this.multipleStatus.before = before + this.multipleStatus.after = after + if (before && after) { + if (this.dateCompare(before, after)) { + this.multipleStatus.data = this.geDateAll(before, after); + this._getWeek(after) + } else { + this.multipleStatus.data = this.geDateAll(after, before); + this._getWeek(before) + } + } + } + + /** + * 获取每周数据 + * @param {Object} dateData + */ + _getWeek(dateData) { + const { + fullDate, + year, + month, + date, + day + } = this.getDate(dateData) + let firstDay = new Date(year, month - 1, 1).getDay() + let currentDay = new Date(year, month, 0).getDate() + let dates = { + lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天 + currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数 + nextMonthDays: [], // 下个月开始几天 + weeks: [] + } + let canlender = [] + const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length) + dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData)) + canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays) + let weeks = {} + // 拼接数组 上个月开始几天 + 本月天数+ 下个月开始几天 + for (let i = 0; i < canlender.length; i++) { + if (i % 7 === 0) { + weeks[parseInt(i / 7)] = new Array(7) + } + weeks[parseInt(i / 7)][i % 7] = canlender[i] + } + this.canlender = canlender + this.weeks = weeks + } + + //静态方法 + // static init(date) { + // if (!this.instance) { + // this.instance = new Calendar(date); + // } + // return this.instance; + // } +} + + +export default Calendar diff --git a/uni_modules/uni-datetime-picker/package.json b/uni_modules/uni-datetime-picker/package.json new file mode 100644 index 0000000..0e44103 --- /dev/null +++ b/uni_modules/uni-datetime-picker/package.json @@ -0,0 +1,90 @@ +{ + "id": "uni-datetime-picker", + "displayName": "uni-datetime-picker 日期选择器", + "version": "2.2.4", + "description": "uni-datetime-picker 日期时间选择器,支持日历,支持范围选择", + "keywords": [ + "uni-datetime-picker", + "uni-ui", + "uniui", + "日期时间选择器", + "日期时间" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "n" + }, + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-datetime-picker/readme.md b/uni_modules/uni-datetime-picker/readme.md new file mode 100644 index 0000000..162fbef --- /dev/null +++ b/uni_modules/uni-datetime-picker/readme.md @@ -0,0 +1,21 @@ + + +> `重要通知:组件升级更新 2.0.0 后,支持日期+时间范围选择,组件 ui 将使用日历选择日期,ui 变化较大,同时支持 PC 和 移动端。此版本不向后兼容,不再支持单独的时间选择(type=time)及相关的 hide-second 属性(时间选可使用内置组件 picker)。若仍需使用旧版本,可在插件市场下载*非uni_modules版本*,旧版本将不再维护` + +## DatetimePicker 时间选择器 + +> **组件名:uni-datetime-picker** +> 代码块: `uDatetimePicker` + + +该组件的优势是,支持**时间戳**输入和输出(起始时间、终止时间也支持时间戳),可**同时选择**日期和时间。 + +若只是需要单独选择日期和时间,不需要时间戳输入和输出,可使用原生的 picker 组件。 + +**_点击 picker 默认值规则:_** + +- 若设置初始值 value, 会显示在 picker 显示框中 +- 若无初始值 value,则初始值 value 为当前本地时间 Date.now(), 但不会显示在 picker 显示框中 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-datetime-picker) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-drawer/changelog.md b/uni_modules/uni-drawer/changelog.md new file mode 100644 index 0000000..6d2488c --- /dev/null +++ b/uni_modules/uni-drawer/changelog.md @@ -0,0 +1,13 @@ +## 1.2.1(2021-11-22) +- 修复 vue3中个别scss变量无法找到的问题 +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-drawer](https://uniapp.dcloud.io/component/uniui/uni-drawer) +## 1.1.1(2021-07-30) +- 优化 vue3下事件警告的问题 +## 1.1.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.7(2021-05-12) +- 新增 组件示例地址 +## 1.0.6(2021-02-04) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-drawer/components/uni-drawer/keypress.js b/uni_modules/uni-drawer/components/uni-drawer/keypress.js new file mode 100644 index 0000000..62dda46 --- /dev/null +++ b/uni_modules/uni-drawer/components/uni-drawer/keypress.js @@ -0,0 +1,45 @@ +// #ifdef H5 +export default { + name: 'Keypress', + props: { + disable: { + type: Boolean, + default: false + } + }, + mounted () { + const keyNames = { + esc: ['Esc', 'Escape'], + tab: 'Tab', + enter: 'Enter', + space: [' ', 'Spacebar'], + up: ['Up', 'ArrowUp'], + left: ['Left', 'ArrowLeft'], + right: ['Right', 'ArrowRight'], + down: ['Down', 'ArrowDown'], + delete: ['Backspace', 'Delete', 'Del'] + } + const listener = ($event) => { + if (this.disable) { + return + } + const keyName = Object.keys(keyNames).find(key => { + const keyName = $event.key + const value = keyNames[key] + return value === keyName || (Array.isArray(value) && value.includes(keyName)) + }) + if (keyName) { + // 避免和其他按键事件冲突 + setTimeout(() => { + this.$emit(keyName, {}) + }, 0) + } + } + document.addEventListener('keyup', listener) + // this.$once('hook:beforeDestroy', () => { + // document.removeEventListener('keyup', listener) + // }) + }, + render: () => {} +} +// #endif diff --git a/uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue b/uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue new file mode 100644 index 0000000..82331a8 --- /dev/null +++ b/uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue @@ -0,0 +1,183 @@ + + + + + diff --git a/uni_modules/uni-drawer/package.json b/uni_modules/uni-drawer/package.json new file mode 100644 index 0000000..dd056e4 --- /dev/null +++ b/uni_modules/uni-drawer/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-drawer", + "displayName": "uni-drawer 抽屉", + "version": "1.2.1", + "description": "抽屉式导航,用于展示侧滑菜单,侧滑导航。", + "keywords": [ + "uni-ui", + "uniui", + "drawer", + "抽屉", + "侧滑导航" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-drawer/readme.md b/uni_modules/uni-drawer/readme.md new file mode 100644 index 0000000..dcf6e6b --- /dev/null +++ b/uni_modules/uni-drawer/readme.md @@ -0,0 +1,10 @@ + + +## Drawer 抽屉 +> **组件名:uni-drawer** +> 代码块: `uDrawer` + +抽屉侧滑菜单。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-drawer) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-easyinput/changelog.md b/uni_modules/uni-easyinput/changelog.md new file mode 100644 index 0000000..1cbe623 --- /dev/null +++ b/uni_modules/uni-easyinput/changelog.md @@ -0,0 +1,35 @@ +## 1.0.2(2022-04-12) +- 修复 默认值不生效的bug +## 1.0.1(2022-04-02) +- 修复 value不能为0的bug +## 1.0.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-easyinput](https://uniapp.dcloud.io/component/uniui/uni-easyinput) +## 0.1.4(2021-08-20) +- 修复 在 uni-forms 的动态表单中默认值校验不通过的 bug +## 0.1.3(2021-08-11) +- 修复 在 uni-forms 中重置表单,错误信息无法清除的问题 +## 0.1.2(2021-07-30) +- 优化 vue3下事件警告的问题 +## 0.1.1 +- 优化 errorMessage 属性支持 Boolean 类型 +## 0.1.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 0.0.16(2021-06-29) +- 修复 confirmType 属性(仅 type="text" 生效)导致多行文本框无法换行的 bug +## 0.0.15(2021-06-21) +- 修复 passwordIcon 属性拼写错误的 bug +## 0.0.14(2021-06-18) +- 新增 passwordIcon 属性,当type=password时是否显示小眼睛图标 +- 修复 confirmType 属性不生效的问题 +## 0.0.13(2021-06-04) +- 修复 disabled 状态可清出内容的 bug +## 0.0.12(2021-05-12) +- 新增 组件示例地址 +## 0.0.11(2021-05-07) +- 修复 input-border 属性不生效的问题 +## 0.0.10(2021-04-30) +- 修复 ios 遮挡文字、显示一半的问题 +## 0.0.9(2021-02-05) +- 调整为uni_modules目录规范 +- 优化 兼容 nvue 页面 diff --git a/uni_modules/uni-easyinput/components/uni-easyinput/common.js b/uni_modules/uni-easyinput/components/uni-easyinput/common.js new file mode 100644 index 0000000..df9abe1 --- /dev/null +++ b/uni_modules/uni-easyinput/components/uni-easyinput/common.js @@ -0,0 +1,56 @@ +/** + * @desc 函数防抖 + * @param func 目标函数 + * @param wait 延迟执行毫秒数 + * @param immediate true - 立即执行, false - 延迟执行 + */ +export const debounce = function(func, wait = 1000, immediate = true) { + let timer; + console.log(1); + return function() { + console.log(123); + let context = this, + args = arguments; + if (timer) clearTimeout(timer); + if (immediate) { + let callNow = !timer; + timer = setTimeout(() => { + timer = null; + }, wait); + if (callNow) func.apply(context, args); + } else { + timer = setTimeout(() => { + func.apply(context, args); + }, wait) + } + } +} +/** + * @desc 函数节流 + * @param func 函数 + * @param wait 延迟执行毫秒数 + * @param type 1 使用表时间戳,在时间段开始的时候触发 2 使用表定时器,在时间段结束的时候触发 + */ +export const throttle = (func, wait = 1000, type = 1) => { + let previous = 0; + let timeout; + return function() { + let context = this; + let args = arguments; + if (type === 1) { + let now = Date.now(); + + if (now - previous > wait) { + func.apply(context, args); + previous = now; + } + } else if (type === 2) { + if (!timeout) { + timeout = setTimeout(() => { + timeout = null; + func.apply(context, args) + }, wait) + } + } + } +} diff --git a/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue b/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue new file mode 100644 index 0000000..33f73bd --- /dev/null +++ b/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue @@ -0,0 +1,461 @@ + + + + + diff --git a/uni_modules/uni-easyinput/package.json b/uni_modules/uni-easyinput/package.json new file mode 100644 index 0000000..f1195b1 --- /dev/null +++ b/uni_modules/uni-easyinput/package.json @@ -0,0 +1,90 @@ +{ + "id": "uni-easyinput", + "displayName": "uni-easyinput 增强输入框", + "version": "1.0.2", + "description": "Easyinput 组件是对原生input组件的增强", + "keywords": [ + "uni-ui", + "uniui", + "input", + "uni-easyinput", + "输入框" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-easyinput/readme.md b/uni_modules/uni-easyinput/readme.md new file mode 100644 index 0000000..f1faf8f --- /dev/null +++ b/uni_modules/uni-easyinput/readme.md @@ -0,0 +1,11 @@ + + +### Easyinput 增强输入框 +> **组件名:uni-easyinput** +> 代码块: `uEasyinput` + + +easyinput 组件是对原生input组件的增强 ,是专门为配合表单组件[uni-forms](https://ext.dcloud.net.cn/plugin?id=2773)而设计的,easyinput 内置了边框,图标等,同时包含 input 所有功能 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-easyinput) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-fab/changelog.md b/uni_modules/uni-fab/changelog.md new file mode 100644 index 0000000..24e26b1 --- /dev/null +++ b/uni_modules/uni-fab/changelog.md @@ -0,0 +1,17 @@ +## 1.2.2(2021-12-29) +- 更新 组件依赖 +## 1.2.1(2021-11-19) +- 修复 阴影颜色不正确的bug +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-fab](https://uniapp.dcloud.io/component/uniui/uni-fab) +## 1.1.1(2021-11-09) +- 新增 提供组件设计资源,组件样式调整 +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.7(2021-05-12) +- 新增 组件示例地址 +## 1.0.6(2021-02-05) +- 调整为uni_modules目录规范 +- 优化 按钮背景色调整 +- 优化 兼容pc端 diff --git a/uni_modules/uni-fab/components/uni-fab/uni-fab.vue b/uni_modules/uni-fab/components/uni-fab/uni-fab.vue new file mode 100644 index 0000000..bef97f1 --- /dev/null +++ b/uni_modules/uni-fab/components/uni-fab/uni-fab.vue @@ -0,0 +1,475 @@ + + + + + diff --git a/uni_modules/uni-fab/package.json b/uni_modules/uni-fab/package.json new file mode 100644 index 0000000..0f27daa --- /dev/null +++ b/uni_modules/uni-fab/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-fab", + "displayName": "uni-fab 悬浮按钮", + "version": "1.2.2", + "description": "悬浮按钮 fab button ,点击可展开一个图标按钮菜单。", + "keywords": [ + "uni-ui", + "uniui", + "按钮", + "悬浮按钮", + "fab" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss","uni-icons"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-fab/readme.md b/uni_modules/uni-fab/readme.md new file mode 100644 index 0000000..9a444e8 --- /dev/null +++ b/uni_modules/uni-fab/readme.md @@ -0,0 +1,9 @@ +## Fab 悬浮按钮 +> **组件名:uni-fab** +> 代码块: `uFab` + + +点击可展开一个图形按钮菜单 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-fab) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-fav/changelog.md b/uni_modules/uni-fav/changelog.md new file mode 100644 index 0000000..4b3f8c2 --- /dev/null +++ b/uni_modules/uni-fav/changelog.md @@ -0,0 +1,17 @@ +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-fav](https://uniapp.dcloud.io/component/uniui/uni-fav) +## 1.1.1(2021-08-24) +- 新增 支持国际化 +## 1.1.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.6(2021-05-12) +- 新增 组件示例地址 +## 1.0.5(2021-04-21) +- 优化 添加依赖 uni-icons, 导入后自动下载依赖 +## 1.0.4(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 +## 1.0.3(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 +## 1.0.2(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-fav/components/uni-fav/i18n/en.json b/uni_modules/uni-fav/components/uni-fav/i18n/en.json new file mode 100644 index 0000000..9a0759e --- /dev/null +++ b/uni_modules/uni-fav/components/uni-fav/i18n/en.json @@ -0,0 +1,4 @@ +{ + "uni-fav.collect": "collect", + "uni-fav.collected": "collected" +} diff --git a/uni_modules/uni-fav/components/uni-fav/i18n/index.js b/uni_modules/uni-fav/components/uni-fav/i18n/index.js new file mode 100644 index 0000000..de7509c --- /dev/null +++ b/uni_modules/uni-fav/components/uni-fav/i18n/index.js @@ -0,0 +1,8 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hans.json b/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hans.json new file mode 100644 index 0000000..67c89bf --- /dev/null +++ b/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hans.json @@ -0,0 +1,4 @@ +{ + "uni-fav.collect": "收藏", + "uni-fav.collected": "已收藏" +} diff --git a/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hant.json b/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hant.json new file mode 100644 index 0000000..67c89bf --- /dev/null +++ b/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hant.json @@ -0,0 +1,4 @@ +{ + "uni-fav.collect": "收藏", + "uni-fav.collected": "已收藏" +} diff --git a/uni_modules/uni-fav/components/uni-fav/uni-fav.vue b/uni_modules/uni-fav/components/uni-fav/uni-fav.vue new file mode 100644 index 0000000..4e87bc8 --- /dev/null +++ b/uni_modules/uni-fav/components/uni-fav/uni-fav.vue @@ -0,0 +1,156 @@ + + + + + diff --git a/uni_modules/uni-fav/package.json b/uni_modules/uni-fav/package.json new file mode 100644 index 0000000..39e4f33 --- /dev/null +++ b/uni_modules/uni-fav/package.json @@ -0,0 +1,89 @@ +{ + "id": "uni-fav", + "displayName": "uni-fav 收藏按钮", + "version": "1.2.0", + "description": " Fav 收藏组件,可自定义颜色、大小。", + "keywords": [ + "fav", + "uni-ui", + "uniui", + "收藏" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-fav/readme.md b/uni_modules/uni-fav/readme.md new file mode 100644 index 0000000..4de125d --- /dev/null +++ b/uni_modules/uni-fav/readme.md @@ -0,0 +1,10 @@ + + +## Fav 收藏按钮 +> **组件名:uni-fav** +> 代码块: `uFav` + +用于收藏功能,可点击切换选中、不选中的状态。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-fav) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-file-picker/changelog.md b/uni_modules/uni-file-picker/changelog.md new file mode 100644 index 0000000..840a9e6 --- /dev/null +++ b/uni_modules/uni-file-picker/changelog.md @@ -0,0 +1,61 @@ +## 1.0.1(2021-11-23) +- 修复 参数为对象的情况下,url在某些情况显示错误的bug +## 1.0.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-file-picker](https://uniapp.dcloud.io/component/uniui/uni-file-picker) +## 0.2.16(2021-11-08) +- 修复 传入空对象 ,显示错误的Bug +## 0.2.15(2021-08-30) +- 修复 return-type="object" 时且存在v-model时,无法删除文件的Bug +## 0.2.14(2021-08-23) +- 新增 参数中返回 fileID 字段 +## 0.2.13(2021-08-23) +- 修复 腾讯云传入fileID 不能回显的bug +- 修复 选择图片后,不能放大的问题 +## 0.2.12(2021-08-17) +- 修复 由于 0.2.11 版本引起的不能回显图片的Bug +## 0.2.11(2021-08-16) +- 新增 clearFiles(index) 方法,可以手动删除指定文件 +- 修复 v-model 值设为 null 报错的Bug +## 0.2.10(2021-08-13) +- 修复 return-type="object" 时,无法删除文件的Bug +## 0.2.9(2021-08-03) +- 修复 auto-upload 属性失效的Bug +## 0.2.8(2021-07-31) +- 修复 fileExtname属性不指定值报错的Bug +## 0.2.7(2021-07-31) +- 修复 在某种场景下图片不回显的Bug +## 0.2.6(2021-07-30) +- 修复 return-type为object下,返回值不正确的Bug +## 0.2.5(2021-07-30) +- 修复(重要) H5 平台下如果和uni-forms组件一同使用导致页面卡死的问题 +## 0.2.3(2021-07-28) +- 优化 调整示例代码 +## 0.2.2(2021-07-27) +- 修复 vue3 下赋值错误的Bug +- 优化 h5平台下上传文件导致页面卡死的问题 +## 0.2.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 0.1.1(2021-07-02) +- 修复 sourceType 缺少默认值导致 ios 无法选择文件 +## 0.1.0(2021-06-30) +- 优化 解耦与uniCloud的强绑定关系 ,如不绑定服务空间,默认autoUpload为false且不可更改 +## 0.0.11(2021-06-30) +- 修复 由 0.0.10 版本引发的 returnType 属性失效的问题 +## 0.0.10(2021-06-29) +- 优化 文件上传后进度条消失时机 +## 0.0.9(2021-06-29) +- 修复 在uni-forms 中,删除文件 ,获取的值不对的Bug +## 0.0.8(2021-06-15) +- 修复 删除文件时无法触发 v-model 的Bug +## 0.0.7(2021-05-12) +- 新增 组件示例地址 +## 0.0.6(2021-04-09) +- 修复 选择的文件非 file-extname 字段指定的扩展名报错的Bug +## 0.0.5(2021-04-09) +- 优化 更新组件示例 +## 0.0.4(2021-04-09) +- 优化 file-extname 字段支持字符串写法,多个扩展名需要用逗号分隔 +## 0.0.3(2021-02-05) +- 调整为uni_modules目录规范 +- 修复 微信小程序不指定 fileExtname 属性选择失败的Bug diff --git a/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js b/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js new file mode 100644 index 0000000..24a07f5 --- /dev/null +++ b/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js @@ -0,0 +1,224 @@ +'use strict'; + +const ERR_MSG_OK = 'chooseAndUploadFile:ok'; +const ERR_MSG_FAIL = 'chooseAndUploadFile:fail'; + +function chooseImage(opts) { + const { + count, + sizeType = ['original', 'compressed'], + sourceType = ['album', 'camera'], + extension + } = opts + return new Promise((resolve, reject) => { + uni.chooseImage({ + count, + sizeType, + sourceType, + extension, + success(res) { + resolve(normalizeChooseAndUploadFileRes(res, 'image')); + }, + fail(res) { + reject({ + errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL), + }); + }, + }); + }); +} + +function chooseVideo(opts) { + const { + camera, + compressed, + maxDuration, + sourceType = ['album', 'camera'], + extension + } = opts; + return new Promise((resolve, reject) => { + uni.chooseVideo({ + camera, + compressed, + maxDuration, + sourceType, + extension, + success(res) { + const { + tempFilePath, + duration, + size, + height, + width + } = res; + resolve(normalizeChooseAndUploadFileRes({ + errMsg: 'chooseVideo:ok', + tempFilePaths: [tempFilePath], + tempFiles: [ + { + name: (res.tempFile && res.tempFile.name) || '', + path: tempFilePath, + size, + type: (res.tempFile && res.tempFile.type) || '', + width, + height, + duration, + fileType: 'video', + cloudPath: '', + }, ], + }, 'video')); + }, + fail(res) { + reject({ + errMsg: res.errMsg.replace('chooseVideo:fail', ERR_MSG_FAIL), + }); + }, + }); + }); +} + +function chooseAll(opts) { + const { + count, + extension + } = opts; + return new Promise((resolve, reject) => { + let chooseFile = uni.chooseFile; + if (typeof wx !== 'undefined' && + typeof wx.chooseMessageFile === 'function') { + chooseFile = wx.chooseMessageFile; + } + if (typeof chooseFile !== 'function') { + return reject({ + errMsg: ERR_MSG_FAIL + ' 请指定 type 类型,该平台仅支持选择 image 或 video。', + }); + } + chooseFile({ + type: 'all', + count, + extension, + success(res) { + resolve(normalizeChooseAndUploadFileRes(res)); + }, + fail(res) { + reject({ + errMsg: res.errMsg.replace('chooseFile:fail', ERR_MSG_FAIL), + }); + }, + }); + }); +} + +function normalizeChooseAndUploadFileRes(res, fileType) { + res.tempFiles.forEach((item, index) => { + if (!item.name) { + item.name = item.path.substring(item.path.lastIndexOf('/') + 1); + } + if (fileType) { + item.fileType = fileType; + } + item.cloudPath = + Date.now() + '_' + index + item.name.substring(item.name.lastIndexOf('.')); + }); + if (!res.tempFilePaths) { + res.tempFilePaths = res.tempFiles.map((file) => file.path); + } + return res; +} + +function uploadCloudFiles(files, max = 5, onUploadProgress) { + files = JSON.parse(JSON.stringify(files)) + const len = files.length + let count = 0 + let self = this + return new Promise(resolve => { + while (count < max) { + next() + } + + function next() { + let cur = count++ + if (cur >= len) { + !files.find(item => !item.url && !item.errMsg) && resolve(files) + return + } + const fileItem = files[cur] + const index = self.files.findIndex(v => v.uuid === fileItem.uuid) + fileItem.url = '' + delete fileItem.errMsg + + uniCloud + .uploadFile({ + filePath: fileItem.path, + cloudPath: fileItem.cloudPath, + fileType: fileItem.fileType, + onUploadProgress: res => { + res.index = index + onUploadProgress && onUploadProgress(res) + } + }) + .then(res => { + fileItem.url = res.fileID + fileItem.index = index + if (cur < len) { + next() + } + }) + .catch(res => { + fileItem.errMsg = res.errMsg || res.message + fileItem.index = index + if (cur < len) { + next() + } + }) + } + }) +} + + + + + +function uploadFiles(choosePromise, { + onChooseFile, + onUploadProgress +}) { + return choosePromise + .then((res) => { + if (onChooseFile) { + const customChooseRes = onChooseFile(res); + if (typeof customChooseRes !== 'undefined') { + return Promise.resolve(customChooseRes).then((chooseRes) => typeof chooseRes === 'undefined' ? + res : chooseRes); + } + } + return res; + }) + .then((res) => { + if (res === false) { + return { + errMsg: ERR_MSG_OK, + tempFilePaths: [], + tempFiles: [], + }; + } + return res + }) +} + +function chooseAndUploadFile(opts = { + type: 'all' +}) { + if (opts.type === 'image') { + return uploadFiles(chooseImage(opts), opts); + } + else if (opts.type === 'video') { + return uploadFiles(chooseVideo(opts), opts); + } + return uploadFiles(chooseAll(opts), opts); +} + +export { + chooseAndUploadFile, + uploadCloudFiles +}; diff --git a/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue b/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue new file mode 100644 index 0000000..a9d05a8 --- /dev/null +++ b/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue @@ -0,0 +1,651 @@ + + + + + diff --git a/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue b/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue new file mode 100644 index 0000000..625d92e --- /dev/null +++ b/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue @@ -0,0 +1,325 @@ + + + + + diff --git a/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue b/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue new file mode 100644 index 0000000..2a29bc2 --- /dev/null +++ b/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue @@ -0,0 +1,292 @@ + + + + + diff --git a/uni_modules/uni-file-picker/components/uni-file-picker/utils.js b/uni_modules/uni-file-picker/components/uni-file-picker/utils.js new file mode 100644 index 0000000..60aaa3e --- /dev/null +++ b/uni_modules/uni-file-picker/components/uni-file-picker/utils.js @@ -0,0 +1,109 @@ +/** + * 获取文件名和后缀 + * @param {String} name + */ +export const get_file_ext = (name) => { + const last_len = name.lastIndexOf('.') + const len = name.length + return { + name: name.substring(0, last_len), + ext: name.substring(last_len + 1, len) + } +} + +/** + * 获取扩展名 + * @param {Array} fileExtname + */ +export const get_extname = (fileExtname) => { + if (!Array.isArray(fileExtname)) { + let extname = fileExtname.replace(/(\[|\])/g, '') + return extname.split(',') + } else { + return fileExtname + } + return [] +} + +/** + * 获取文件和检测是否可选 + */ +export const get_files_and_is_max = (res, _extname) => { + let filePaths = [] + let files = [] + if(!_extname || _extname.length === 0){ + return { + filePaths, + files + } + } + res.tempFiles.forEach(v => { + let fileFullName = get_file_ext(v.name) + const extname = fileFullName.ext.toLowerCase() + if (_extname.indexOf(extname) !== -1) { + files.push(v) + filePaths.push(v.path) + } + }) + if (files.length !== res.tempFiles.length) { + uni.showToast({ + title: `当前选择了${res.tempFiles.length}个文件 ,${res.tempFiles.length - files.length} 个文件格式不正确`, + icon: 'none', + duration: 5000 + }) + } + + return { + filePaths, + files + } +} + + +/** + * 获取图片信息 + * @param {Object} filepath + */ +export const get_file_info = (filepath) => { + return new Promise((resolve, reject) => { + uni.getImageInfo({ + src: filepath, + success(res) { + resolve(res) + }, + fail(err) { + reject(err) + } + }) + }) +} +/** + * 获取封装数据 + */ +export const get_file_data = async (files, type = 'image') => { + // 最终需要上传数据库的数据 + let fileFullName = get_file_ext(files.name) + const extname = fileFullName.ext.toLowerCase() + let filedata = { + name: files.name, + uuid: files.uuid, + extname: extname || '', + cloudPath: files.cloudPath, + fileType: files.fileType, + url: files.path || files.path, + size: files.size, //单位是字节 + image: {}, + path: files.path, + video: {} + } + if (type === 'image') { + const imageinfo = await get_file_info(files.path) + delete filedata.video + filedata.image.width = imageinfo.width + filedata.image.height = imageinfo.height + filedata.image.location = imageinfo.path + } else { + delete filedata.image + } + return filedata +} diff --git a/uni_modules/uni-file-picker/package.json b/uni_modules/uni-file-picker/package.json new file mode 100644 index 0000000..d659bb5 --- /dev/null +++ b/uni_modules/uni-file-picker/package.json @@ -0,0 +1,86 @@ +{ + "id": "uni-file-picker", + "displayName": "uni-file-picker 文件选择上传", + "version": "1.0.1", + "description": "文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间", + "keywords": [ + "uni-ui", + "uniui", + "图片上传", + "文件上传" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "n" + }, + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-file-picker/readme.md b/uni_modules/uni-file-picker/readme.md new file mode 100644 index 0000000..c8399a5 --- /dev/null +++ b/uni_modules/uni-file-picker/readme.md @@ -0,0 +1,11 @@ + +## FilePicker 文件选择上传 + +> **组件名:uni-file-picker** +> 代码块: `uFilePicker` + + +文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-file-picker) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-forms/changelog.md b/uni_modules/uni-forms/changelog.md new file mode 100644 index 0000000..26e120b --- /dev/null +++ b/uni_modules/uni-forms/changelog.md @@ -0,0 +1,60 @@ +## 1.3.2(2021-12-09) +- +## 1.3.1(2021-11-19) +- 修复 label 插槽不生效的bug +## 1.3.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-forms](https://uniapp.dcloud.io/component/uniui/uni-forms) +## 1.2.7(2021-08-13) +- 修复 没有添加校验规则的字段依然报错的Bug +## 1.2.6(2021-08-11) +- 修复 重置表单错误信息无法清除的问题 +## 1.2.5(2021-08-11) +- 优化 组件文档 +## 1.2.4(2021-08-11) +- 修复 表单验证只生效一次的问题 +## 1.2.3(2021-07-30) +- 优化 vue3下事件警告的问题 +## 1.2.2(2021-07-26) +- 修复 vue2 下条件编译导致destroyed生命周期失效的Bug +- 修复 1.2.1 引起的示例在小程序平台报错的Bug +## 1.2.1(2021-07-22) +- 修复 动态校验表单,默认值为空的情况下校验失效的Bug +- 修复 不指定name属性时,运行报错的Bug +- 优化 label默认宽度从65调整至70,使required为true且四字时不换行 +- 优化 组件示例,新增动态校验示例代码 +- 优化 组件文档,使用方式更清晰 +## 1.2.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.1.2(2021-06-25) +- 修复 pattern 属性在微信小程序平台无效的问题 +## 1.1.1(2021-06-22) +- 修复 validate-trigger属性为submit且err-show-type属性为toast时不能弹出的Bug +## 1.1.0(2021-06-22) +- 修复 只写setRules方法而导致校验不生效的Bug +- 修复 由上个办法引发的错误提示文字错位的Bug +## 1.0.48(2021-06-21) +- 修复 不设置 label 属性 ,无法设置label插槽的问题 +## 1.0.47(2021-06-21) +- 修复 不设置label属性,label-width属性不生效的bug +- 修复 setRules 方法与rules属性冲突的问题 +## 1.0.46(2021-06-04) +- 修复 动态删减数据导致报错的问题 +## 1.0.45(2021-06-04) +- 新增 modelValue 属性 ,value 即将废弃 +## 1.0.44(2021-06-02) +- 新增 uni-forms-item 可以设置单独的 rules +- 新增 validate 事件增加 keepitem 参数,可以选择那些字段不过滤 +- 优化 submit 事件重命名为 validate +## 1.0.43(2021-05-12) +- 新增 组件示例地址 +## 1.0.42(2021-04-30) +- 修复 自定义检验器失效的问题 +## 1.0.41(2021-03-05) +- 更新 校验器 +- 修复 表单规则设置类型为 number 的情况下,值为0校验失败的Bug +## 1.0.40(2021-03-04) +- 修复 动态显示uni-forms-item的情况下,submit 方法获取值错误的Bug +## 1.0.39(2021-02-05) +- 调整为uni_modules目录规范 +- 修复 校验器传入 int 等类型 ,返回String类型的Bug diff --git a/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue b/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue new file mode 100644 index 0000000..a5ae8ab --- /dev/null +++ b/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue @@ -0,0 +1,509 @@ + + + + + diff --git a/uni_modules/uni-forms/components/uni-forms/uni-forms.vue b/uni_modules/uni-forms/components/uni-forms/uni-forms.vue new file mode 100644 index 0000000..d8b4e66 --- /dev/null +++ b/uni_modules/uni-forms/components/uni-forms/uni-forms.vue @@ -0,0 +1,472 @@ + + + + + diff --git a/uni_modules/uni-forms/components/uni-forms/validate.js b/uni_modules/uni-forms/components/uni-forms/validate.js new file mode 100644 index 0000000..1834c6c --- /dev/null +++ b/uni_modules/uni-forms/components/uni-forms/validate.js @@ -0,0 +1,486 @@ +var pattern = { + email: /^\S+?@\S+?\.\S+?$/, + idcard: /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/, + 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') +}; + +const FORMAT_MAPPING = { + "int": 'integer', + "bool": 'boolean', + "double": 'number', + "long": 'number', + "password": 'string' + // "fileurls": 'array' +} + +function formatMessage(args, resources = '') { + var defaultMessage = ['label'] + defaultMessage.forEach((item) => { + if (args[item] === undefined) { + args[item] = '' + } + }) + + let str = resources + for (let key in args) { + let reg = new RegExp('{' + key + '}') + str = str.replace(reg, args[key]) + } + return str +} + +function isEmptyValue(value, type) { + if (value === undefined || value === null) { + return true; + } + + if (typeof value === 'string' && !value) { + return true; + } + + if (Array.isArray(value) && !value.length) { + return true; + } + + if (type === 'object' && !Object.keys(value).length) { + return true; + } + + return false; +} + +const types = { + integer(value) { + return types.number(value) && parseInt(value, 10) === value; + }, + string(value) { + return typeof value === 'string'; + }, + number(value) { + if (isNaN(value)) { + return false; + } + return typeof value === 'number'; + }, + "boolean": function(value) { + return typeof value === 'boolean'; + }, + "float": function(value) { + return types.number(value) && !types.integer(value); + }, + array(value) { + return Array.isArray(value); + }, + object(value) { + return typeof value === 'object' && !types.array(value); + }, + date(value) { + return value instanceof Date; + }, + timestamp(value) { + if (!this.integer(value) || Math.abs(value).toString().length > 16) { + return false + } + return true; + }, + file(value) { + return typeof value.url === 'string'; + }, + email(value) { + return typeof value === 'string' && !!value.match(pattern.email) && value.length < 255; + }, + url(value) { + return typeof value === 'string' && !!value.match(pattern.url); + }, + pattern(reg, value) { + try { + return new RegExp(reg).test(value); + } catch (e) { + return false; + } + }, + method(value) { + return typeof value === 'function'; + }, + idcard(value) { + return typeof value === 'string' && !!value.match(pattern.idcard); + }, + 'url-https'(value) { + return this.url(value) && value.startsWith('https://'); + }, + 'url-scheme'(value) { + return value.startsWith('://'); + }, + 'url-web'(value) { + return false; + } +} + +class RuleValidator { + + constructor(message) { + this._message = message + } + + async validateRule(fieldKey, fieldValue, value, data, allData) { + var result = null + + let rules = fieldValue.rules + + let hasRequired = rules.findIndex((item) => { + return item.required + }) + if (hasRequired < 0) { + if (value === null || value === undefined) { + return result + } + if (typeof value === 'string' && !value.length) { + return result + } + } + + var message = this._message + + if (rules === undefined) { + return message['default'] + } + + for (var i = 0; i < rules.length; i++) { + let rule = rules[i] + let vt = this._getValidateType(rule) + + Object.assign(rule, { + label: fieldValue.label || `["${fieldKey}"]` + }) + + if (RuleValidatorHelper[vt]) { + result = RuleValidatorHelper[vt](rule, value, message) + if (result != null) { + break + } + } + + if (rule.validateExpr) { + let now = Date.now() + let resultExpr = rule.validateExpr(value, allData, now) + if (resultExpr === false) { + result = this._getMessage(rule, rule.errorMessage || this._message['default']) + break + } + } + + if (rule.validateFunction) { + result = await this.validateFunction(rule, value, data, allData, vt) + if (result !== null) { + break + } + } + } + + if (result !== null) { + result = message.TAG + result + } + + return result + } + + async validateFunction(rule, value, data, allData, vt) { + let result = null + try { + let callbackMessage = null + const res = await rule.validateFunction(rule, value, allData || data, (message) => { + callbackMessage = message + }) + if (callbackMessage || (typeof res === 'string' && res) || res === false) { + result = this._getMessage(rule, callbackMessage || res, vt) + } + } catch (e) { + result = this._getMessage(rule, e.message, vt) + } + return result + } + + _getMessage(rule, message, vt) { + return formatMessage(rule, message || rule.errorMessage || this._message[vt] || message['default']) + } + + _getValidateType(rule) { + var result = '' + if (rule.required) { + result = 'required' + } else if (rule.format) { + result = 'format' + } else if (rule.arrayType) { + result = 'arrayTypeFormat' + } else if (rule.range) { + result = 'range' + } else if (rule.maximum !== undefined || rule.minimum !== undefined) { + result = 'rangeNumber' + } else if (rule.maxLength !== undefined || rule.minLength !== undefined) { + result = 'rangeLength' + } else if (rule.pattern) { + result = 'pattern' + } else if (rule.validateFunction) { + result = 'validateFunction' + } + return result + } +} + +const RuleValidatorHelper = { + required(rule, value, message) { + if (rule.required && isEmptyValue(value, rule.format || typeof value)) { + return formatMessage(rule, rule.errorMessage || message.required); + } + + return null + }, + + range(rule, value, message) { + const { + range, + errorMessage + } = rule; + + let list = new Array(range.length); + for (let i = 0; i < range.length; i++) { + const item = range[i]; + if (types.object(item) && item.value !== undefined) { + list[i] = item.value; + } else { + list[i] = item; + } + } + + let result = false + if (Array.isArray(value)) { + result = (new Set(value.concat(list)).size === list.length); + } else { + if (list.indexOf(value) > -1) { + result = true; + } + } + + if (!result) { + return formatMessage(rule, errorMessage || message['enum']); + } + + return null + }, + + rangeNumber(rule, value, message) { + if (!types.number(value)) { + return formatMessage(rule, rule.errorMessage || message.pattern.mismatch); + } + + let { + minimum, + maximum, + exclusiveMinimum, + exclusiveMaximum + } = rule; + let min = exclusiveMinimum ? value <= minimum : value < minimum; + let max = exclusiveMaximum ? value >= maximum : value > maximum; + + if (minimum !== undefined && min) { + return formatMessage(rule, rule.errorMessage || message['number'][exclusiveMinimum ? + 'exclusiveMinimum' : 'minimum' + ]) + } else if (maximum !== undefined && max) { + return formatMessage(rule, rule.errorMessage || message['number'][exclusiveMaximum ? + 'exclusiveMaximum' : 'maximum' + ]) + } else if (minimum !== undefined && maximum !== undefined && (min || max)) { + return formatMessage(rule, rule.errorMessage || message['number'].range) + } + + return null + }, + + rangeLength(rule, value, message) { + if (!types.string(value) && !types.array(value)) { + return formatMessage(rule, rule.errorMessage || message.pattern.mismatch); + } + + let min = rule.minLength; + let max = rule.maxLength; + let val = value.length; + + if (min !== undefined && val < min) { + return formatMessage(rule, rule.errorMessage || message['length'].minLength) + } else if (max !== undefined && val > max) { + return formatMessage(rule, rule.errorMessage || message['length'].maxLength) + } else if (min !== undefined && max !== undefined && (val < min || val > max)) { + return formatMessage(rule, rule.errorMessage || message['length'].range) + } + + return null + }, + + pattern(rule, value, message) { + if (!types['pattern'](rule.pattern, value)) { + return formatMessage(rule, rule.errorMessage || message.pattern.mismatch); + } + + return null + }, + + format(rule, value, message) { + var customTypes = Object.keys(types); + var format = FORMAT_MAPPING[rule.format] ? FORMAT_MAPPING[rule.format] : (rule.format || rule.arrayType); + + if (customTypes.indexOf(format) > -1) { + if (!types[format](value)) { + return formatMessage(rule, rule.errorMessage || message.typeError); + } + } + + return null + }, + + arrayTypeFormat(rule, value, message) { + if (!Array.isArray(value)) { + return formatMessage(rule, rule.errorMessage || message.typeError); + } + + for (let i = 0; i < value.length; i++) { + const element = value[i]; + let formatResult = this.format(rule, element, message) + if (formatResult !== null) { + return formatResult + } + } + + return null + } +} + +class SchemaValidator extends RuleValidator { + + constructor(schema, options) { + super(SchemaValidator.message); + + this._schema = schema + this._options = options || null + } + + updateSchema(schema) { + this._schema = schema + } + + async validate(data, allData) { + let result = this._checkFieldInSchema(data) + if (!result) { + result = await this.invokeValidate(data, false, allData) + } + return result.length ? result[0] : null + } + + async validateAll(data, allData) { + let result = this._checkFieldInSchema(data) + if (!result) { + result = await this.invokeValidate(data, true, allData) + } + return result + } + + async validateUpdate(data, allData) { + let result = this._checkFieldInSchema(data) + if (!result) { + result = await this.invokeValidateUpdate(data, false, allData) + } + return result.length ? result[0] : null + } + + async invokeValidate(data, all, allData) { + let result = [] + let schema = this._schema + for (let key in schema) { + let value = schema[key] + let errorMessage = await this.validateRule(key, value, data[key], data, allData) + if (errorMessage != null) { + result.push({ + key, + errorMessage + }) + if (!all) break + } + } + return result + } + + async invokeValidateUpdate(data, all, allData) { + let result = [] + for (let key in data) { + let errorMessage = await this.validateRule(key, this._schema[key], data[key], data, allData) + if (errorMessage != null) { + result.push({ + key, + errorMessage + }) + if (!all) break + } + } + return result + } + + _checkFieldInSchema(data) { + var keys = Object.keys(data) + var keys2 = Object.keys(this._schema) + if (new Set(keys.concat(keys2)).size === keys2.length) { + return '' + } + + var noExistFields = keys.filter((key) => { + return keys2.indexOf(key) < 0; + }) + var errorMessage = formatMessage({ + field: JSON.stringify(noExistFields) + }, SchemaValidator.message.TAG + SchemaValidator.message['defaultInvalid']) + return [{ + key: 'invalid', + errorMessage + }] + } +} + +function Message() { + return { + TAG: "", + default: '验证错误', + defaultInvalid: '提交的字段{field}在数据库中并不存在', + validateFunction: '验证无效', + required: '{label}必填', + 'enum': '{label}超出范围', + timestamp: '{label}格式无效', + whitespace: '{label}不能为空', + typeError: '{label}类型无效', + date: { + format: '{label}日期{value}格式无效', + parse: '{label}日期无法解析,{value}无效', + invalid: '{label}日期{value}无效' + }, + length: { + minLength: '{label}长度不能少于{minLength}', + maxLength: '{label}长度不能超过{maxLength}', + range: '{label}必须介于{minLength}和{maxLength}之间' + }, + number: { + minimum: '{label}不能小于{minimum}', + maximum: '{label}不能大于{maximum}', + exclusiveMinimum: '{label}不能小于等于{minimum}', + exclusiveMaximum: '{label}不能大于等于{maximum}', + range: '{label}必须介于{minimum}and{maximum}之间' + }, + pattern: { + mismatch: '{label}格式不匹配' + } + }; +} + + +SchemaValidator.message = new Message(); + +export default SchemaValidator diff --git a/uni_modules/uni-forms/package.json b/uni_modules/uni-forms/package.json new file mode 100644 index 0000000..dfa7af4 --- /dev/null +++ b/uni_modules/uni-forms/package.json @@ -0,0 +1,90 @@ +{ + "id": "uni-forms", + "displayName": "uni-forms 表单", + "version": "1.3.2", + "description": "由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据", + "keywords": [ + "uni-ui", + "表单", + "校验", + "表单校验", + "表单验证" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-forms/readme.md b/uni_modules/uni-forms/readme.md new file mode 100644 index 0000000..63d5a04 --- /dev/null +++ b/uni_modules/uni-forms/readme.md @@ -0,0 +1,23 @@ + + +## Forms 表单 + +> **组件名:uni-forms** +> 代码块: `uForms`、`uni-forms-item` +> 关联组件:`uni-forms-item`、`uni-easyinput`、`uni-data-checkbox`、`uni-group`。 + + +uni-app的内置组件已经有了 `
`组件,用于提交表单内容。 + +然而几乎每个表单都需要做表单验证,为了方便做表单验证,减少重复开发,`uni ui` 又基于 ``组件封装了 ``组件,内置了表单验证功能。 + +`` 提供了 `rules`属性来描述校验规则、``子组件来包裹具体的表单项,以及给原生或三方组件提供了 `binddata()` 来设置表单值。 + +每个要校验的表单项,不管input还是checkbox,都必须放在``组件中,且一个``组件只能放置一个表单项。 + +``组件内部预留了显示error message的区域,默认是在表单项的底部。 + +另外,``组件下面的各个表单项,可以通过``包裹为不同的分组。同一``下的不同表单项目将聚拢在一起,同其他group保持垂直间距。``仅影响视觉效果。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-forms) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-goods-nav/changelog.md b/uni_modules/uni-goods-nav/changelog.md new file mode 100644 index 0000000..d970649 --- /dev/null +++ b/uni_modules/uni-goods-nav/changelog.md @@ -0,0 +1,16 @@ +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-goods-nav](https://uniapp.dcloud.io/component/uniui/uni-goods-nav) +## 1.1.1(2021-08-24) +- 新增 支持国际化 +## 1.1.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.7(2021-05-12) +- 新增 组件示例地址 +## 1.0.6(2021-04-21) +- 优化 添加依赖 uni-icons, 导入后自动下载依赖 +## 1.0.5(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 + +## 1.0.4(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/en.json b/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/en.json new file mode 100644 index 0000000..dcdba41 --- /dev/null +++ b/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/en.json @@ -0,0 +1,6 @@ +{ + "uni-goods-nav.options.shop": "shop", + "uni-goods-nav.options.cart": "cart", + "uni-goods-nav.buttonGroup.addToCart": "add to cart", + "uni-goods-nav.buttonGroup.buyNow": "buy now" +} diff --git a/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/index.js b/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/index.js new file mode 100644 index 0000000..de7509c --- /dev/null +++ b/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/index.js @@ -0,0 +1,8 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hans.json b/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hans.json new file mode 100644 index 0000000..48ee344 --- /dev/null +++ b/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hans.json @@ -0,0 +1,6 @@ +{ + "uni-goods-nav.options.shop": "店铺", + "uni-goods-nav.options.cart": "购物车", + "uni-goods-nav.buttonGroup.addToCart": "加入购物车", + "uni-goods-nav.buttonGroup.buyNow": "立即购买" +} diff --git a/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hant.json b/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hant.json new file mode 100644 index 0000000..d0a0255 --- /dev/null +++ b/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hant.json @@ -0,0 +1,6 @@ +{ + "uni-goods-nav.options.shop": "店鋪", + "uni-goods-nav.options.cart": "購物車", + "uni-goods-nav.buttonGroup.addToCart": "加入購物車", + "uni-goods-nav.buttonGroup.buyNow": "立即購買" +} diff --git a/uni_modules/uni-goods-nav/components/uni-goods-nav/uni-goods-nav.vue b/uni_modules/uni-goods-nav/components/uni-goods-nav/uni-goods-nav.vue new file mode 100644 index 0000000..8a246c5 --- /dev/null +++ b/uni_modules/uni-goods-nav/components/uni-goods-nav/uni-goods-nav.vue @@ -0,0 +1,224 @@ + + + + + diff --git a/uni_modules/uni-goods-nav/package.json b/uni_modules/uni-goods-nav/package.json new file mode 100644 index 0000000..99cd567 --- /dev/null +++ b/uni_modules/uni-goods-nav/package.json @@ -0,0 +1,88 @@ +{ + "id": "uni-goods-nav", + "displayName": "uni-goods-nav 商品导航", + "version": "1.2.0", + "description": "商品导航组件主要用于电商类应用底部导航,可自定义加入购物车,购买等操作", + "keywords": [ + "uni-ui", + "uniui", + "商品导航" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-goods-nav/readme.md b/uni_modules/uni-goods-nav/readme.md new file mode 100644 index 0000000..07df93f --- /dev/null +++ b/uni_modules/uni-goods-nav/readme.md @@ -0,0 +1,10 @@ + + +## GoodsNav 商品导航 +> **组件名:uni-goods-nav** +> 代码块: `uGoodsNav` + +商品加入购物车,立即购买等。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-goods-nav) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-grid/changelog.md b/uni_modules/uni-grid/changelog.md new file mode 100644 index 0000000..d301166 --- /dev/null +++ b/uni_modules/uni-grid/changelog.md @@ -0,0 +1,13 @@ +## 1.4.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-grid](https://uniapp.dcloud.io/component/uniui/uni-grid) +## 1.3.2(2021-11-09) +- 新增 提供组件设计资源,组件样式调整 +## 1.3.1(2021-07-30) +- 优化 vue3下事件警告的问题 +## 1.3.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.2.4(2021-05-12) +- 新增 组件示例地址 +## 1.2.3(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue b/uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue new file mode 100644 index 0000000..20fd54e --- /dev/null +++ b/uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue @@ -0,0 +1,127 @@ + + + + + diff --git a/uni_modules/uni-grid/components/uni-grid/uni-grid.vue b/uni_modules/uni-grid/components/uni-grid/uni-grid.vue new file mode 100644 index 0000000..96a412f --- /dev/null +++ b/uni_modules/uni-grid/components/uni-grid/uni-grid.vue @@ -0,0 +1,142 @@ + + + + + diff --git a/uni_modules/uni-grid/package.json b/uni_modules/uni-grid/package.json new file mode 100644 index 0000000..ccb2c91 --- /dev/null +++ b/uni_modules/uni-grid/package.json @@ -0,0 +1,86 @@ +{ + "id": "uni-grid", + "displayName": "uni-grid 宫格", + "version": "1.4.0", + "description": "Grid 宫格组件,提供移动端常见的宫格布局,如九宫格。", + "keywords": [ + "uni-ui", + "uniui", + "九宫格", + "表格" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss","uni-icons"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-grid/readme.md b/uni_modules/uni-grid/readme.md new file mode 100644 index 0000000..0aa44cc --- /dev/null +++ b/uni_modules/uni-grid/readme.md @@ -0,0 +1,11 @@ + + +## Grid 宫格 +> **组件名:uni-grid** +> 代码块: `uGrid` + + +宫格组件。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-grid) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-group/changelog.md b/uni_modules/uni-group/changelog.md new file mode 100644 index 0000000..5bb3559 --- /dev/null +++ b/uni_modules/uni-group/changelog.md @@ -0,0 +1,14 @@ +## 1.2.1(2021-11-22) +- 修复 vue3中某些scss变量无法找到的问题 +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-group](https://uniapp.dcloud.io/component/uniui/uni-group) +## 1.1.7(2021-11-08) +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +- 优化 组件文档 +## 1.0.3(2021-05-12) +- 新增 组件示例地址 +## 1.0.2(2021-02-05) +- 调整为uni_modules目录规范 +- 优化 兼容 nvue 页面 diff --git a/uni_modules/uni-group/components/uni-group/uni-group.vue b/uni_modules/uni-group/components/uni-group/uni-group.vue new file mode 100644 index 0000000..3e4c806 --- /dev/null +++ b/uni_modules/uni-group/components/uni-group/uni-group.vue @@ -0,0 +1,130 @@ + + + + diff --git a/uni_modules/uni-group/package.json b/uni_modules/uni-group/package.json new file mode 100644 index 0000000..532dd15 --- /dev/null +++ b/uni_modules/uni-group/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-group", + "displayName": "uni-group 分组", + "version": "1.2.1", + "description": "分组组件可用于将组件用于分组,添加间隔,以产生明显的区块", + "keywords": [ + "uni-ui", + "uniui", + "group", + "分组", + "" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-group/readme.md b/uni_modules/uni-group/readme.md new file mode 100644 index 0000000..bae67f4 --- /dev/null +++ b/uni_modules/uni-group/readme.md @@ -0,0 +1,9 @@ + +## Group 分组 +> **组件名:uni-group** +> 代码块: `uGroup` + +分组组件可用于将组件分组,添加间隔,以产生明显的区块。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-group) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-icons/changelog.md b/uni_modules/uni-icons/changelog.md new file mode 100644 index 0000000..6449885 --- /dev/null +++ b/uni_modules/uni-icons/changelog.md @@ -0,0 +1,22 @@ +## 1.3.5(2022-01-24) +- 优化 size 属性可以传入不带单位的字符串数值 +## 1.3.4(2022-01-24) +- 优化 size 支持其他单位 +## 1.3.3(2022-01-17) +- 修复 nvue 有些图标不显示的bug,兼容老版本图标 +## 1.3.2(2021-12-01) +- 优化 示例可复制图标名称 +## 1.3.1(2021-11-23) +- 优化 兼容旧组件 type 值 +## 1.3.0(2021-11-19) +- 新增 更多图标 +- 优化 自定义图标使用方式 +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-icons](https://uniapp.dcloud.io/component/uniui/uni-icons) +## 1.1.7(2021-11-08) +## 1.2.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.1.5(2021-05-12) +- 新增 组件示例地址 +## 1.1.4(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-icons/components/uni-icons/icons.js b/uni_modules/uni-icons/components/uni-icons/icons.js new file mode 100644 index 0000000..7889936 --- /dev/null +++ b/uni_modules/uni-icons/components/uni-icons/icons.js @@ -0,0 +1,1169 @@ +export default { + "id": "2852637", + "name": "uniui图标库", + "font_family": "uniicons", + "css_prefix_text": "uniui-", + "description": "", + "glyphs": [ + { + "icon_id": "25027049", + "name": "yanse", + "font_class": "color", + "unicode": "e6cf", + "unicode_decimal": 59087 + }, + { + "icon_id": "25027048", + "name": "wallet", + "font_class": "wallet", + "unicode": "e6b1", + "unicode_decimal": 59057 + }, + { + "icon_id": "25015720", + "name": "settings-filled", + "font_class": "settings-filled", + "unicode": "e6ce", + "unicode_decimal": 59086 + }, + { + "icon_id": "25015434", + "name": "shimingrenzheng-filled", + "font_class": "auth-filled", + "unicode": "e6cc", + "unicode_decimal": 59084 + }, + { + "icon_id": "24934246", + "name": "shop-filled", + "font_class": "shop-filled", + "unicode": "e6cd", + "unicode_decimal": 59085 + }, + { + "icon_id": "24934159", + "name": "staff-filled-01", + "font_class": "staff-filled", + "unicode": "e6cb", + "unicode_decimal": 59083 + }, + { + "icon_id": "24932461", + "name": "VIP-filled", + "font_class": "vip-filled", + "unicode": "e6c6", + "unicode_decimal": 59078 + }, + { + "icon_id": "24932462", + "name": "plus_circle_fill", + "font_class": "plus-filled", + "unicode": "e6c7", + "unicode_decimal": 59079 + }, + { + "icon_id": "24932463", + "name": "folder_add-filled", + "font_class": "folder-add-filled", + "unicode": "e6c8", + "unicode_decimal": 59080 + }, + { + "icon_id": "24932464", + "name": "yanse-filled", + "font_class": "color-filled", + "unicode": "e6c9", + "unicode_decimal": 59081 + }, + { + "icon_id": "24932465", + "name": "tune-filled", + "font_class": "tune-filled", + "unicode": "e6ca", + "unicode_decimal": 59082 + }, + { + "icon_id": "24932455", + "name": "a-rilidaka-filled", + "font_class": "calendar-filled", + "unicode": "e6c0", + "unicode_decimal": 59072 + }, + { + "icon_id": "24932456", + "name": "notification-filled", + "font_class": "notification-filled", + "unicode": "e6c1", + "unicode_decimal": 59073 + }, + { + "icon_id": "24932457", + "name": "wallet-filled", + "font_class": "wallet-filled", + "unicode": "e6c2", + "unicode_decimal": 59074 + }, + { + "icon_id": "24932458", + "name": "paihangbang-filled", + "font_class": "medal-filled", + "unicode": "e6c3", + "unicode_decimal": 59075 + }, + { + "icon_id": "24932459", + "name": "gift-filled", + "font_class": "gift-filled", + "unicode": "e6c4", + "unicode_decimal": 59076 + }, + { + "icon_id": "24932460", + "name": "fire-filled", + "font_class": "fire-filled", + "unicode": "e6c5", + "unicode_decimal": 59077 + }, + { + "icon_id": "24928001", + "name": "refreshempty", + "font_class": "refreshempty", + "unicode": "e6bf", + "unicode_decimal": 59071 + }, + { + "icon_id": "24926853", + "name": "location-ellipse", + "font_class": "location-filled", + "unicode": "e6af", + "unicode_decimal": 59055 + }, + { + "icon_id": "24926735", + "name": "person-filled", + "font_class": "person-filled", + "unicode": "e69d", + "unicode_decimal": 59037 + }, + { + "icon_id": "24926703", + "name": "personadd-filled", + "font_class": "personadd-filled", + "unicode": "e698", + "unicode_decimal": 59032 + }, + { + "icon_id": "24923351", + "name": "back", + "font_class": "back", + "unicode": "e6b9", + "unicode_decimal": 59065 + }, + { + "icon_id": "24923352", + "name": "forward", + "font_class": "forward", + "unicode": "e6ba", + "unicode_decimal": 59066 + }, + { + "icon_id": "24923353", + "name": "arrowthinright", + "font_class": "arrow-right", + "unicode": "e6bb", + "unicode_decimal": 59067 + }, + { + "icon_id": "24923353", + "name": "arrowthinright", + "font_class": "arrowthinright", + "unicode": "e6bb", + "unicode_decimal": 59067 + }, + { + "icon_id": "24923354", + "name": "arrowthinleft", + "font_class": "arrow-left", + "unicode": "e6bc", + "unicode_decimal": 59068 + }, + { + "icon_id": "24923354", + "name": "arrowthinleft", + "font_class": "arrowthinleft", + "unicode": "e6bc", + "unicode_decimal": 59068 + }, + { + "icon_id": "24923355", + "name": "arrowthinup", + "font_class": "arrow-up", + "unicode": "e6bd", + "unicode_decimal": 59069 + }, + { + "icon_id": "24923355", + "name": "arrowthinup", + "font_class": "arrowthinup", + "unicode": "e6bd", + "unicode_decimal": 59069 + }, + { + "icon_id": "24923356", + "name": "arrowthindown", + "font_class": "arrow-down", + "unicode": "e6be", + "unicode_decimal": 59070 + },{ + "icon_id": "24923356", + "name": "arrowthindown", + "font_class": "arrowthindown", + "unicode": "e6be", + "unicode_decimal": 59070 + }, + { + "icon_id": "24923349", + "name": "arrowdown", + "font_class": "bottom", + "unicode": "e6b8", + "unicode_decimal": 59064 + },{ + "icon_id": "24923349", + "name": "arrowdown", + "font_class": "arrowdown", + "unicode": "e6b8", + "unicode_decimal": 59064 + }, + { + "icon_id": "24923346", + "name": "arrowright", + "font_class": "right", + "unicode": "e6b5", + "unicode_decimal": 59061 + }, + { + "icon_id": "24923346", + "name": "arrowright", + "font_class": "arrowright", + "unicode": "e6b5", + "unicode_decimal": 59061 + }, + { + "icon_id": "24923347", + "name": "arrowup", + "font_class": "top", + "unicode": "e6b6", + "unicode_decimal": 59062 + }, + { + "icon_id": "24923347", + "name": "arrowup", + "font_class": "arrowup", + "unicode": "e6b6", + "unicode_decimal": 59062 + }, + { + "icon_id": "24923348", + "name": "arrowleft", + "font_class": "left", + "unicode": "e6b7", + "unicode_decimal": 59063 + }, + { + "icon_id": "24923348", + "name": "arrowleft", + "font_class": "arrowleft", + "unicode": "e6b7", + "unicode_decimal": 59063 + }, + { + "icon_id": "24923334", + "name": "eye", + "font_class": "eye", + "unicode": "e651", + "unicode_decimal": 58961 + }, + { + "icon_id": "24923335", + "name": "eye-filled", + "font_class": "eye-filled", + "unicode": "e66a", + "unicode_decimal": 58986 + }, + { + "icon_id": "24923336", + "name": "eye-slash", + "font_class": "eye-slash", + "unicode": "e6b3", + "unicode_decimal": 59059 + }, + { + "icon_id": "24923337", + "name": "eye-slash-filled", + "font_class": "eye-slash-filled", + "unicode": "e6b4", + "unicode_decimal": 59060 + }, + { + "icon_id": "24923305", + "name": "info-filled", + "font_class": "info-filled", + "unicode": "e649", + "unicode_decimal": 58953 + }, + { + "icon_id": "24923299", + "name": "reload-01", + "font_class": "reload", + "unicode": "e6b2", + "unicode_decimal": 59058 + }, + { + "icon_id": "24923195", + "name": "mic_slash_fill", + "font_class": "micoff-filled", + "unicode": "e6b0", + "unicode_decimal": 59056 + }, + { + "icon_id": "24923165", + "name": "map-pin-ellipse", + "font_class": "map-pin-ellipse", + "unicode": "e6ac", + "unicode_decimal": 59052 + }, + { + "icon_id": "24923166", + "name": "map-pin", + "font_class": "map-pin", + "unicode": "e6ad", + "unicode_decimal": 59053 + }, + { + "icon_id": "24923167", + "name": "location", + "font_class": "location", + "unicode": "e6ae", + "unicode_decimal": 59054 + }, + { + "icon_id": "24923064", + "name": "starhalf", + "font_class": "starhalf", + "unicode": "e683", + "unicode_decimal": 59011 + }, + { + "icon_id": "24923065", + "name": "star", + "font_class": "star", + "unicode": "e688", + "unicode_decimal": 59016 + }, + { + "icon_id": "24923066", + "name": "star-filled", + "font_class": "star-filled", + "unicode": "e68f", + "unicode_decimal": 59023 + }, + { + "icon_id": "24899646", + "name": "a-rilidaka", + "font_class": "calendar", + "unicode": "e6a0", + "unicode_decimal": 59040 + }, + { + "icon_id": "24899647", + "name": "fire", + "font_class": "fire", + "unicode": "e6a1", + "unicode_decimal": 59041 + }, + { + "icon_id": "24899648", + "name": "paihangbang", + "font_class": "medal", + "unicode": "e6a2", + "unicode_decimal": 59042 + }, + { + "icon_id": "24899649", + "name": "font", + "font_class": "font", + "unicode": "e6a3", + "unicode_decimal": 59043 + }, + { + "icon_id": "24899650", + "name": "gift", + "font_class": "gift", + "unicode": "e6a4", + "unicode_decimal": 59044 + }, + { + "icon_id": "24899651", + "name": "link", + "font_class": "link", + "unicode": "e6a5", + "unicode_decimal": 59045 + }, + { + "icon_id": "24899652", + "name": "notification", + "font_class": "notification", + "unicode": "e6a6", + "unicode_decimal": 59046 + }, + { + "icon_id": "24899653", + "name": "staff", + "font_class": "staff", + "unicode": "e6a7", + "unicode_decimal": 59047 + }, + { + "icon_id": "24899654", + "name": "VIP", + "font_class": "vip", + "unicode": "e6a8", + "unicode_decimal": 59048 + }, + { + "icon_id": "24899655", + "name": "folder_add", + "font_class": "folder-add", + "unicode": "e6a9", + "unicode_decimal": 59049 + }, + { + "icon_id": "24899656", + "name": "tune", + "font_class": "tune", + "unicode": "e6aa", + "unicode_decimal": 59050 + }, + { + "icon_id": "24899657", + "name": "shimingrenzheng", + "font_class": "auth", + "unicode": "e6ab", + "unicode_decimal": 59051 + }, + { + "icon_id": "24899565", + "name": "person", + "font_class": "person", + "unicode": "e699", + "unicode_decimal": 59033 + }, + { + "icon_id": "24899566", + "name": "email-filled", + "font_class": "email-filled", + "unicode": "e69a", + "unicode_decimal": 59034 + }, + { + "icon_id": "24899567", + "name": "phone-filled", + "font_class": "phone-filled", + "unicode": "e69b", + "unicode_decimal": 59035 + }, + { + "icon_id": "24899568", + "name": "phone", + "font_class": "phone", + "unicode": "e69c", + "unicode_decimal": 59036 + }, + { + "icon_id": "24899570", + "name": "email", + "font_class": "email", + "unicode": "e69e", + "unicode_decimal": 59038 + }, + { + "icon_id": "24899571", + "name": "personadd", + "font_class": "personadd", + "unicode": "e69f", + "unicode_decimal": 59039 + }, + { + "icon_id": "24899558", + "name": "chatboxes-filled", + "font_class": "chatboxes-filled", + "unicode": "e692", + "unicode_decimal": 59026 + }, + { + "icon_id": "24899559", + "name": "contact", + "font_class": "contact", + "unicode": "e693", + "unicode_decimal": 59027 + }, + { + "icon_id": "24899560", + "name": "chatbubble-filled", + "font_class": "chatbubble-filled", + "unicode": "e694", + "unicode_decimal": 59028 + }, + { + "icon_id": "24899561", + "name": "contact-filled", + "font_class": "contact-filled", + "unicode": "e695", + "unicode_decimal": 59029 + }, + { + "icon_id": "24899562", + "name": "chatboxes", + "font_class": "chatboxes", + "unicode": "e696", + "unicode_decimal": 59030 + }, + { + "icon_id": "24899563", + "name": "chatbubble", + "font_class": "chatbubble", + "unicode": "e697", + "unicode_decimal": 59031 + }, + { + "icon_id": "24881290", + "name": "upload-filled", + "font_class": "upload-filled", + "unicode": "e68e", + "unicode_decimal": 59022 + }, + { + "icon_id": "24881292", + "name": "upload", + "font_class": "upload", + "unicode": "e690", + "unicode_decimal": 59024 + }, + { + "icon_id": "24881293", + "name": "weixin", + "font_class": "weixin", + "unicode": "e691", + "unicode_decimal": 59025 + }, + { + "icon_id": "24881274", + "name": "compose", + "font_class": "compose", + "unicode": "e67f", + "unicode_decimal": 59007 + }, + { + "icon_id": "24881275", + "name": "qq", + "font_class": "qq", + "unicode": "e680", + "unicode_decimal": 59008 + }, + { + "icon_id": "24881276", + "name": "download-filled", + "font_class": "download-filled", + "unicode": "e681", + "unicode_decimal": 59009 + }, + { + "icon_id": "24881277", + "name": "pengyouquan", + "font_class": "pyq", + "unicode": "e682", + "unicode_decimal": 59010 + }, + { + "icon_id": "24881279", + "name": "sound", + "font_class": "sound", + "unicode": "e684", + "unicode_decimal": 59012 + }, + { + "icon_id": "24881280", + "name": "trash-filled", + "font_class": "trash-filled", + "unicode": "e685", + "unicode_decimal": 59013 + }, + { + "icon_id": "24881281", + "name": "sound-filled", + "font_class": "sound-filled", + "unicode": "e686", + "unicode_decimal": 59014 + }, + { + "icon_id": "24881282", + "name": "trash", + "font_class": "trash", + "unicode": "e687", + "unicode_decimal": 59015 + }, + { + "icon_id": "24881284", + "name": "videocam-filled", + "font_class": "videocam-filled", + "unicode": "e689", + "unicode_decimal": 59017 + }, + { + "icon_id": "24881285", + "name": "spinner-cycle", + "font_class": "spinner-cycle", + "unicode": "e68a", + "unicode_decimal": 59018 + }, + { + "icon_id": "24881286", + "name": "weibo", + "font_class": "weibo", + "unicode": "e68b", + "unicode_decimal": 59019 + }, + { + "icon_id": "24881288", + "name": "videocam", + "font_class": "videocam", + "unicode": "e68c", + "unicode_decimal": 59020 + }, + { + "icon_id": "24881289", + "name": "download", + "font_class": "download", + "unicode": "e68d", + "unicode_decimal": 59021 + }, + { + "icon_id": "24879601", + "name": "help", + "font_class": "help", + "unicode": "e679", + "unicode_decimal": 59001 + }, + { + "icon_id": "24879602", + "name": "navigate-filled", + "font_class": "navigate-filled", + "unicode": "e67a", + "unicode_decimal": 59002 + }, + { + "icon_id": "24879603", + "name": "plusempty", + "font_class": "plusempty", + "unicode": "e67b", + "unicode_decimal": 59003 + }, + { + "icon_id": "24879604", + "name": "smallcircle", + "font_class": "smallcircle", + "unicode": "e67c", + "unicode_decimal": 59004 + }, + { + "icon_id": "24879605", + "name": "minus-filled", + "font_class": "minus-filled", + "unicode": "e67d", + "unicode_decimal": 59005 + }, + { + "icon_id": "24879606", + "name": "micoff", + "font_class": "micoff", + "unicode": "e67e", + "unicode_decimal": 59006 + }, + { + "icon_id": "24879588", + "name": "closeempty", + "font_class": "closeempty", + "unicode": "e66c", + "unicode_decimal": 58988 + }, + { + "icon_id": "24879589", + "name": "clear", + "font_class": "clear", + "unicode": "e66d", + "unicode_decimal": 58989 + }, + { + "icon_id": "24879590", + "name": "navigate", + "font_class": "navigate", + "unicode": "e66e", + "unicode_decimal": 58990 + }, + { + "icon_id": "24879591", + "name": "minus", + "font_class": "minus", + "unicode": "e66f", + "unicode_decimal": 58991 + }, + { + "icon_id": "24879592", + "name": "image", + "font_class": "image", + "unicode": "e670", + "unicode_decimal": 58992 + }, + { + "icon_id": "24879593", + "name": "mic", + "font_class": "mic", + "unicode": "e671", + "unicode_decimal": 58993 + }, + { + "icon_id": "24879594", + "name": "paperplane", + "font_class": "paperplane", + "unicode": "e672", + "unicode_decimal": 58994 + }, + { + "icon_id": "24879595", + "name": "close", + "font_class": "close", + "unicode": "e673", + "unicode_decimal": 58995 + }, + { + "icon_id": "24879596", + "name": "help-filled", + "font_class": "help-filled", + "unicode": "e674", + "unicode_decimal": 58996 + }, + { + "icon_id": "24879597", + "name": "plus-filled", + "font_class": "paperplane-filled", + "unicode": "e675", + "unicode_decimal": 58997 + }, + { + "icon_id": "24879598", + "name": "plus", + "font_class": "plus", + "unicode": "e676", + "unicode_decimal": 58998 + }, + { + "icon_id": "24879599", + "name": "mic-filled", + "font_class": "mic-filled", + "unicode": "e677", + "unicode_decimal": 58999 + }, + { + "icon_id": "24879600", + "name": "image-filled", + "font_class": "image-filled", + "unicode": "e678", + "unicode_decimal": 59000 + }, + { + "icon_id": "24855900", + "name": "locked-filled", + "font_class": "locked-filled", + "unicode": "e668", + "unicode_decimal": 58984 + }, + { + "icon_id": "24855901", + "name": "info", + "font_class": "info", + "unicode": "e669", + "unicode_decimal": 58985 + }, + { + "icon_id": "24855903", + "name": "locked", + "font_class": "locked", + "unicode": "e66b", + "unicode_decimal": 58987 + }, + { + "icon_id": "24855884", + "name": "camera-filled", + "font_class": "camera-filled", + "unicode": "e658", + "unicode_decimal": 58968 + }, + { + "icon_id": "24855885", + "name": "chat-filled", + "font_class": "chat-filled", + "unicode": "e659", + "unicode_decimal": 58969 + }, + { + "icon_id": "24855886", + "name": "camera", + "font_class": "camera", + "unicode": "e65a", + "unicode_decimal": 58970 + }, + { + "icon_id": "24855887", + "name": "circle", + "font_class": "circle", + "unicode": "e65b", + "unicode_decimal": 58971 + }, + { + "icon_id": "24855888", + "name": "checkmarkempty", + "font_class": "checkmarkempty", + "unicode": "e65c", + "unicode_decimal": 58972 + }, + { + "icon_id": "24855889", + "name": "chat", + "font_class": "chat", + "unicode": "e65d", + "unicode_decimal": 58973 + }, + { + "icon_id": "24855890", + "name": "circle-filled", + "font_class": "circle-filled", + "unicode": "e65e", + "unicode_decimal": 58974 + }, + { + "icon_id": "24855891", + "name": "flag", + "font_class": "flag", + "unicode": "e65f", + "unicode_decimal": 58975 + }, + { + "icon_id": "24855892", + "name": "flag-filled", + "font_class": "flag-filled", + "unicode": "e660", + "unicode_decimal": 58976 + }, + { + "icon_id": "24855893", + "name": "gear-filled", + "font_class": "gear-filled", + "unicode": "e661", + "unicode_decimal": 58977 + }, + { + "icon_id": "24855894", + "name": "home", + "font_class": "home", + "unicode": "e662", + "unicode_decimal": 58978 + }, + { + "icon_id": "24855895", + "name": "home-filled", + "font_class": "home-filled", + "unicode": "e663", + "unicode_decimal": 58979 + }, + { + "icon_id": "24855896", + "name": "gear", + "font_class": "gear", + "unicode": "e664", + "unicode_decimal": 58980 + }, + { + "icon_id": "24855897", + "name": "smallcircle-filled", + "font_class": "smallcircle-filled", + "unicode": "e665", + "unicode_decimal": 58981 + }, + { + "icon_id": "24855898", + "name": "map-filled", + "font_class": "map-filled", + "unicode": "e666", + "unicode_decimal": 58982 + }, + { + "icon_id": "24855899", + "name": "map", + "font_class": "map", + "unicode": "e667", + "unicode_decimal": 58983 + }, + { + "icon_id": "24855825", + "name": "refresh-filled", + "font_class": "refresh-filled", + "unicode": "e656", + "unicode_decimal": 58966 + }, + { + "icon_id": "24855826", + "name": "refresh", + "font_class": "refresh", + "unicode": "e657", + "unicode_decimal": 58967 + }, + { + "icon_id": "24855808", + "name": "cloud-upload", + "font_class": "cloud-upload", + "unicode": "e645", + "unicode_decimal": 58949 + }, + { + "icon_id": "24855809", + "name": "cloud-download-filled", + "font_class": "cloud-download-filled", + "unicode": "e646", + "unicode_decimal": 58950 + }, + { + "icon_id": "24855810", + "name": "cloud-download", + "font_class": "cloud-download", + "unicode": "e647", + "unicode_decimal": 58951 + }, + { + "icon_id": "24855811", + "name": "cloud-upload-filled", + "font_class": "cloud-upload-filled", + "unicode": "e648", + "unicode_decimal": 58952 + }, + { + "icon_id": "24855813", + "name": "redo", + "font_class": "redo", + "unicode": "e64a", + "unicode_decimal": 58954 + }, + { + "icon_id": "24855814", + "name": "images-filled", + "font_class": "images-filled", + "unicode": "e64b", + "unicode_decimal": 58955 + }, + { + "icon_id": "24855815", + "name": "undo-filled", + "font_class": "undo-filled", + "unicode": "e64c", + "unicode_decimal": 58956 + }, + { + "icon_id": "24855816", + "name": "more", + "font_class": "more", + "unicode": "e64d", + "unicode_decimal": 58957 + }, + { + "icon_id": "24855817", + "name": "more-filled", + "font_class": "more-filled", + "unicode": "e64e", + "unicode_decimal": 58958 + }, + { + "icon_id": "24855818", + "name": "undo", + "font_class": "undo", + "unicode": "e64f", + "unicode_decimal": 58959 + }, + { + "icon_id": "24855819", + "name": "images", + "font_class": "images", + "unicode": "e650", + "unicode_decimal": 58960 + }, + { + "icon_id": "24855821", + "name": "paperclip", + "font_class": "paperclip", + "unicode": "e652", + "unicode_decimal": 58962 + }, + { + "icon_id": "24855822", + "name": "settings", + "font_class": "settings", + "unicode": "e653", + "unicode_decimal": 58963 + }, + { + "icon_id": "24855823", + "name": "search", + "font_class": "search", + "unicode": "e654", + "unicode_decimal": 58964 + }, + { + "icon_id": "24855824", + "name": "redo-filled", + "font_class": "redo-filled", + "unicode": "e655", + "unicode_decimal": 58965 + }, + { + "icon_id": "24841702", + "name": "list", + "font_class": "list", + "unicode": "e644", + "unicode_decimal": 58948 + }, + { + "icon_id": "24841489", + "name": "mail-open-filled", + "font_class": "mail-open-filled", + "unicode": "e63a", + "unicode_decimal": 58938 + }, + { + "icon_id": "24841491", + "name": "hand-thumbsdown-filled", + "font_class": "hand-down-filled", + "unicode": "e63c", + "unicode_decimal": 58940 + }, + { + "icon_id": "24841492", + "name": "hand-thumbsdown", + "font_class": "hand-down", + "unicode": "e63d", + "unicode_decimal": 58941 + }, + { + "icon_id": "24841493", + "name": "hand-thumbsup-filled", + "font_class": "hand-up-filled", + "unicode": "e63e", + "unicode_decimal": 58942 + }, + { + "icon_id": "24841494", + "name": "hand-thumbsup", + "font_class": "hand-up", + "unicode": "e63f", + "unicode_decimal": 58943 + }, + { + "icon_id": "24841496", + "name": "heart-filled", + "font_class": "heart-filled", + "unicode": "e641", + "unicode_decimal": 58945 + }, + { + "icon_id": "24841498", + "name": "mail-open", + "font_class": "mail-open", + "unicode": "e643", + "unicode_decimal": 58947 + }, + { + "icon_id": "24841488", + "name": "heart", + "font_class": "heart", + "unicode": "e639", + "unicode_decimal": 58937 + }, + { + "icon_id": "24839963", + "name": "loop", + "font_class": "loop", + "unicode": "e633", + "unicode_decimal": 58931 + }, + { + "icon_id": "24839866", + "name": "pulldown", + "font_class": "pulldown", + "unicode": "e632", + "unicode_decimal": 58930 + }, + { + "icon_id": "24813798", + "name": "scan", + "font_class": "scan", + "unicode": "e62a", + "unicode_decimal": 58922 + }, + { + "icon_id": "24813786", + "name": "bars", + "font_class": "bars", + "unicode": "e627", + "unicode_decimal": 58919 + }, + { + "icon_id": "24813788", + "name": "cart-filled", + "font_class": "cart-filled", + "unicode": "e629", + "unicode_decimal": 58921 + }, + { + "icon_id": "24813790", + "name": "checkbox", + "font_class": "checkbox", + "unicode": "e62b", + "unicode_decimal": 58923 + }, + { + "icon_id": "24813791", + "name": "checkbox-filled", + "font_class": "checkbox-filled", + "unicode": "e62c", + "unicode_decimal": 58924 + }, + { + "icon_id": "24813794", + "name": "shop", + "font_class": "shop", + "unicode": "e62f", + "unicode_decimal": 58927 + }, + { + "icon_id": "24813795", + "name": "headphones", + "font_class": "headphones", + "unicode": "e630", + "unicode_decimal": 58928 + }, + { + "icon_id": "24813796", + "name": "cart", + "font_class": "cart", + "unicode": "e631", + "unicode_decimal": 58929 + } + ] +} diff --git a/uni_modules/uni-icons/components/uni-icons/uni-icons.vue b/uni_modules/uni-icons/components/uni-icons/uni-icons.vue new file mode 100644 index 0000000..86e7444 --- /dev/null +++ b/uni_modules/uni-icons/components/uni-icons/uni-icons.vue @@ -0,0 +1,96 @@ + + + + + diff --git a/uni_modules/uni-icons/components/uni-icons/uniicons.css b/uni_modules/uni-icons/components/uni-icons/uniicons.css new file mode 100644 index 0000000..2f56eab --- /dev/null +++ b/uni_modules/uni-icons/components/uni-icons/uniicons.css @@ -0,0 +1,663 @@ +.uniui-color:before { + content: "\e6cf"; +} + +.uniui-wallet:before { + content: "\e6b1"; +} + +.uniui-settings-filled:before { + content: "\e6ce"; +} + +.uniui-auth-filled:before { + content: "\e6cc"; +} + +.uniui-shop-filled:before { + content: "\e6cd"; +} + +.uniui-staff-filled:before { + content: "\e6cb"; +} + +.uniui-vip-filled:before { + content: "\e6c6"; +} + +.uniui-plus-filled:before { + content: "\e6c7"; +} + +.uniui-folder-add-filled:before { + content: "\e6c8"; +} + +.uniui-color-filled:before { + content: "\e6c9"; +} + +.uniui-tune-filled:before { + content: "\e6ca"; +} + +.uniui-calendar-filled:before { + content: "\e6c0"; +} + +.uniui-notification-filled:before { + content: "\e6c1"; +} + +.uniui-wallet-filled:before { + content: "\e6c2"; +} + +.uniui-medal-filled:before { + content: "\e6c3"; +} + +.uniui-gift-filled:before { + content: "\e6c4"; +} + +.uniui-fire-filled:before { + content: "\e6c5"; +} + +.uniui-refreshempty:before { + content: "\e6bf"; +} + +.uniui-location-filled:before { + content: "\e6af"; +} + +.uniui-person-filled:before { + content: "\e69d"; +} + +.uniui-personadd-filled:before { + content: "\e698"; +} + +.uniui-back:before { + content: "\e6b9"; +} + +.uniui-forward:before { + content: "\e6ba"; +} + +.uniui-arrow-right:before { + content: "\e6bb"; +} + +.uniui-arrowthinright:before { + content: "\e6bb"; +} + +.uniui-arrow-left:before { + content: "\e6bc"; +} + +.uniui-arrowthinleft:before { + content: "\e6bc"; +} + +.uniui-arrow-up:before { + content: "\e6bd"; +} + +.uniui-arrowthinup:before { + content: "\e6bd"; +} + +.uniui-arrow-down:before { + content: "\e6be"; +} + +.uniui-arrowthindown:before { + content: "\e6be"; +} + +.uniui-bottom:before { + content: "\e6b8"; +} + +.uniui-arrowdown:before { + content: "\e6b8"; +} + +.uniui-right:before { + content: "\e6b5"; +} + +.uniui-arrowright:before { + content: "\e6b5"; +} + +.uniui-top:before { + content: "\e6b6"; +} + +.uniui-arrowup:before { + content: "\e6b6"; +} + +.uniui-left:before { + content: "\e6b7"; +} + +.uniui-arrowleft:before { + content: "\e6b7"; +} + +.uniui-eye:before { + content: "\e651"; +} + +.uniui-eye-filled:before { + content: "\e66a"; +} + +.uniui-eye-slash:before { + content: "\e6b3"; +} + +.uniui-eye-slash-filled:before { + content: "\e6b4"; +} + +.uniui-info-filled:before { + content: "\e649"; +} + +.uniui-reload:before { + content: "\e6b2"; +} + +.uniui-micoff-filled:before { + content: "\e6b0"; +} + +.uniui-map-pin-ellipse:before { + content: "\e6ac"; +} + +.uniui-map-pin:before { + content: "\e6ad"; +} + +.uniui-location:before { + content: "\e6ae"; +} + +.uniui-starhalf:before { + content: "\e683"; +} + +.uniui-star:before { + content: "\e688"; +} + +.uniui-star-filled:before { + content: "\e68f"; +} + +.uniui-calendar:before { + content: "\e6a0"; +} + +.uniui-fire:before { + content: "\e6a1"; +} + +.uniui-medal:before { + content: "\e6a2"; +} + +.uniui-font:before { + content: "\e6a3"; +} + +.uniui-gift:before { + content: "\e6a4"; +} + +.uniui-link:before { + content: "\e6a5"; +} + +.uniui-notification:before { + content: "\e6a6"; +} + +.uniui-staff:before { + content: "\e6a7"; +} + +.uniui-vip:before { + content: "\e6a8"; +} + +.uniui-folder-add:before { + content: "\e6a9"; +} + +.uniui-tune:before { + content: "\e6aa"; +} + +.uniui-auth:before { + content: "\e6ab"; +} + +.uniui-person:before { + content: "\e699"; +} + +.uniui-email-filled:before { + content: "\e69a"; +} + +.uniui-phone-filled:before { + content: "\e69b"; +} + +.uniui-phone:before { + content: "\e69c"; +} + +.uniui-email:before { + content: "\e69e"; +} + +.uniui-personadd:before { + content: "\e69f"; +} + +.uniui-chatboxes-filled:before { + content: "\e692"; +} + +.uniui-contact:before { + content: "\e693"; +} + +.uniui-chatbubble-filled:before { + content: "\e694"; +} + +.uniui-contact-filled:before { + content: "\e695"; +} + +.uniui-chatboxes:before { + content: "\e696"; +} + +.uniui-chatbubble:before { + content: "\e697"; +} + +.uniui-upload-filled:before { + content: "\e68e"; +} + +.uniui-upload:before { + content: "\e690"; +} + +.uniui-weixin:before { + content: "\e691"; +} + +.uniui-compose:before { + content: "\e67f"; +} + +.uniui-qq:before { + content: "\e680"; +} + +.uniui-download-filled:before { + content: "\e681"; +} + +.uniui-pyq:before { + content: "\e682"; +} + +.uniui-sound:before { + content: "\e684"; +} + +.uniui-trash-filled:before { + content: "\e685"; +} + +.uniui-sound-filled:before { + content: "\e686"; +} + +.uniui-trash:before { + content: "\e687"; +} + +.uniui-videocam-filled:before { + content: "\e689"; +} + +.uniui-spinner-cycle:before { + content: "\e68a"; +} + +.uniui-weibo:before { + content: "\e68b"; +} + +.uniui-videocam:before { + content: "\e68c"; +} + +.uniui-download:before { + content: "\e68d"; +} + +.uniui-help:before { + content: "\e679"; +} + +.uniui-navigate-filled:before { + content: "\e67a"; +} + +.uniui-plusempty:before { + content: "\e67b"; +} + +.uniui-smallcircle:before { + content: "\e67c"; +} + +.uniui-minus-filled:before { + content: "\e67d"; +} + +.uniui-micoff:before { + content: "\e67e"; +} + +.uniui-closeempty:before { + content: "\e66c"; +} + +.uniui-clear:before { + content: "\e66d"; +} + +.uniui-navigate:before { + content: "\e66e"; +} + +.uniui-minus:before { + content: "\e66f"; +} + +.uniui-image:before { + content: "\e670"; +} + +.uniui-mic:before { + content: "\e671"; +} + +.uniui-paperplane:before { + content: "\e672"; +} + +.uniui-close:before { + content: "\e673"; +} + +.uniui-help-filled:before { + content: "\e674"; +} + +.uniui-paperplane-filled:before { + content: "\e675"; +} + +.uniui-plus:before { + content: "\e676"; +} + +.uniui-mic-filled:before { + content: "\e677"; +} + +.uniui-image-filled:before { + content: "\e678"; +} + +.uniui-locked-filled:before { + content: "\e668"; +} + +.uniui-info:before { + content: "\e669"; +} + +.uniui-locked:before { + content: "\e66b"; +} + +.uniui-camera-filled:before { + content: "\e658"; +} + +.uniui-chat-filled:before { + content: "\e659"; +} + +.uniui-camera:before { + content: "\e65a"; +} + +.uniui-circle:before { + content: "\e65b"; +} + +.uniui-checkmarkempty:before { + content: "\e65c"; +} + +.uniui-chat:before { + content: "\e65d"; +} + +.uniui-circle-filled:before { + content: "\e65e"; +} + +.uniui-flag:before { + content: "\e65f"; +} + +.uniui-flag-filled:before { + content: "\e660"; +} + +.uniui-gear-filled:before { + content: "\e661"; +} + +.uniui-home:before { + content: "\e662"; +} + +.uniui-home-filled:before { + content: "\e663"; +} + +.uniui-gear:before { + content: "\e664"; +} + +.uniui-smallcircle-filled:before { + content: "\e665"; +} + +.uniui-map-filled:before { + content: "\e666"; +} + +.uniui-map:before { + content: "\e667"; +} + +.uniui-refresh-filled:before { + content: "\e656"; +} + +.uniui-refresh:before { + content: "\e657"; +} + +.uniui-cloud-upload:before { + content: "\e645"; +} + +.uniui-cloud-download-filled:before { + content: "\e646"; +} + +.uniui-cloud-download:before { + content: "\e647"; +} + +.uniui-cloud-upload-filled:before { + content: "\e648"; +} + +.uniui-redo:before { + content: "\e64a"; +} + +.uniui-images-filled:before { + content: "\e64b"; +} + +.uniui-undo-filled:before { + content: "\e64c"; +} + +.uniui-more:before { + content: "\e64d"; +} + +.uniui-more-filled:before { + content: "\e64e"; +} + +.uniui-undo:before { + content: "\e64f"; +} + +.uniui-images:before { + content: "\e650"; +} + +.uniui-paperclip:before { + content: "\e652"; +} + +.uniui-settings:before { + content: "\e653"; +} + +.uniui-search:before { + content: "\e654"; +} + +.uniui-redo-filled:before { + content: "\e655"; +} + +.uniui-list:before { + content: "\e644"; +} + +.uniui-mail-open-filled:before { + content: "\e63a"; +} + +.uniui-hand-down-filled:before { + content: "\e63c"; +} + +.uniui-hand-down:before { + content: "\e63d"; +} + +.uniui-hand-up-filled:before { + content: "\e63e"; +} + +.uniui-hand-up:before { + content: "\e63f"; +} + +.uniui-heart-filled:before { + content: "\e641"; +} + +.uniui-mail-open:before { + content: "\e643"; +} + +.uniui-heart:before { + content: "\e639"; +} + +.uniui-loop:before { + content: "\e633"; +} + +.uniui-pulldown:before { + content: "\e632"; +} + +.uniui-scan:before { + content: "\e62a"; +} + +.uniui-bars:before { + content: "\e627"; +} + +.uniui-cart-filled:before { + content: "\e629"; +} + +.uniui-checkbox:before { + content: "\e62b"; +} + +.uniui-checkbox-filled:before { + content: "\e62c"; +} + +.uniui-shop:before { + content: "\e62f"; +} + +.uniui-headphones:before { + content: "\e630"; +} + +.uniui-cart:before { + content: "\e631"; +} diff --git a/uni_modules/uni-icons/components/uni-icons/uniicons.ttf b/uni_modules/uni-icons/components/uni-icons/uniicons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..835f33bc9411461b8b9046b3fec742e921d6ce3a GIT binary patch literal 35760 zcmeFacbp?vl{Q?rN>WLsSXIigCAC7gI!S6tox^m`be^1}CwPJ>yxZ{uSzi{WC_=LI+*Wx!<-H!v})21fuKMZQ#fB2Fs zuEGwU_ZyDmuR3&e_s&PS@Be}0T=(JF$l;w=9Als0-iQ4lE^0cm^YDeWhnK#G<4!$@ z>-QZydhsP6Kl0Pv9Cw|EbP-?YO$@C;`+ zuKnR1zxV)MXnddfv56Dn_-W<%#_jZ^d%1f!hyI(6O8C!lXY}93nl=3f9^gzbYS03Jm0vJ;T)Z1IKntfUtypB#zx`e6wG3 zC5AhB&Me^QdH${3yL1otSUp#NN^cKN_yKnkm%XqxczWUgrT^Oo|6lL`SPy&+DZ_DX z1{?B^82rf|!cpSXHhg1*;kZecHy+MI*MqCu>g9T0eYieaf9edzAC9!tJL|pm0UQ~l zBQN;JaG!_sb8)VT%i=%By_I_#_ZIFh?(N(=xVtf?-^|^~y@`7RcMEqbcN=#*_eSmx z?)BVjxU0EqFm9T;Q`~9pTJAdTdhWH{>+qBtxEr~fxSP3Gb60T(xkKDx?g)33JH{R7 zPH-1465x0fg%5CGeb33>TxSiZCZa24wyO7(&Q z>$wfwMs5?gnVaOMxM^;NYvpFSIc_<(f-7(s&u0CxL#u8VbF$klItIryQ@x|5W z48lm`>dOtnnB(dz48rK+>MISxIOOW948n-y>Z=XH*yQSK48kbo>T3axcUVKK~8Y>od!W-aP?gVL3VKU-3CF5aP>U~L7s5+3k`x~;p%%0f{fwn z`wW7#;p+Phg52Ti2MmG);_4R}1X;w@scs-hC9Y0&13^AJNK#+l4o$3aH zH00`3HxT3^SEssxAR)Or)eQt$$+z7tkWDxWPSHIIBXb!IaW`m$ZxcXZRf;QpmZ#4*d zg{!~KAZQq_ewRVeHC+Ae20`m^^>-Kq{lnGoHVB%CtKVY~bP`v;*C1#ou700E&{JIf zeuJQ~xcWN{g6`t#?=lEljH|!fAm}r${tpI0vvKtY41$j1>hCcK+K#I~Xb|)sSAVZT z(12Y1eFi}na`pEc1g*%`|Ir}mN3Q+>gPp}tAE%avLosrF^GJG z`bQ0dZsqD9GYDFitAE@e=v%J-34@?{x%wv!f)3{DpE3yAn5#cz5cD!v|Fl8S&|Lj9 z20>SI_0JjvtVjlpxwFpV+N5QQ~$g{(D+>a3kE^= zbM-G81S^26f5{-&16=*f2Ej7m>R&MkHUd}wszKz<)E_qpb^}-cnn7g6)t@j3wggxI zxp1QBm2=klxXa|a&TVx+;Qp=WwVt{>D}O~9QXW)O>O0h5db_-@^8Ud$^pPT-1=NS-v_4k2r|_kM*0!vaW9xyNll~`AaKH zuPQxR4wv6t{%QC2?wh**v$DGKU?rS_5?F|crGafkiL7dNk-%Y_E4VmkSn6>Hb;SUukEx3l0# zej=BS$yT%Av8Uc*J`xpdRw>aQ5n{34Scli{%@0hjo|#!%t;CXMOO1~vM@By$$wu(0 z7+*JsbCF0c%-{dHFL+pQI~s3&zjaOf89{d%!`6o3fsCO(`6

PqiNa$~E4XJ#a8s%?nsx`&SiQ7Wz{CE9c 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 literal 0 HcmV?d00001 diff --git a/uni_modules/uni-icons/package.json b/uni_modules/uni-icons/package.json new file mode 100644 index 0000000..d1c4e77 --- /dev/null +++ b/uni_modules/uni-icons/package.json @@ -0,0 +1,86 @@ +{ + "id": "uni-icons", + "displayName": "uni-icons 图标", + "version": "1.3.5", + "description": "图标组件,用于展示移动端常见的图标,可自定义颜色、大小。", + "keywords": [ + "uni-ui", + "uniui", + "icon", + "图标" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "^3.2.14" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-icons/readme.md b/uni_modules/uni-icons/readme.md new file mode 100644 index 0000000..86234ba --- /dev/null +++ b/uni_modules/uni-icons/readme.md @@ -0,0 +1,8 @@ +## Icons 图标 +> **组件名:uni-icons** +> 代码块: `uIcons` + +用于展示 icons 图标 。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-icons) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 diff --git a/uni_modules/uni-indexed-list/changelog.md b/uni_modules/uni-indexed-list/changelog.md new file mode 100644 index 0000000..08fa71c --- /dev/null +++ b/uni_modules/uni-indexed-list/changelog.md @@ -0,0 +1,17 @@ +## 1.2.1(2021-11-22) +- 修复 vue3中某些scss变量无法找到的问题 +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-indexed-list](https://uniapp.dcloud.io/component/uniui/uni-indexed-list) +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.11(2021-05-12) +- 新增 组件示例地址 +## 1.0.10(2021-04-21) +- 优化 添加依赖 uni-icons, 导入后自动下载依赖 +## 1.0.9(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 + +## 1.0.8(2021-02-05) +- 调整为uni_modules目录规范 +- 新增 支持 PC 端 diff --git a/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue b/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue new file mode 100644 index 0000000..2f13bae --- /dev/null +++ b/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue @@ -0,0 +1,144 @@ + + + + + diff --git a/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue b/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue new file mode 100644 index 0000000..35e168c --- /dev/null +++ b/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue @@ -0,0 +1,367 @@ + + + diff --git a/uni_modules/uni-indexed-list/package.json b/uni_modules/uni-indexed-list/package.json new file mode 100644 index 0000000..125c0e7 --- /dev/null +++ b/uni_modules/uni-indexed-list/package.json @@ -0,0 +1,89 @@ +{ + "id": "uni-indexed-list", + "displayName": "uni-indexed-list 索引列表", + "version": "1.2.1", + "description": "索引列表组件,右侧带索引的列表,方便快速定位到具体内容,通常用于城市/机场选择等场景", + "keywords": [ + "uni-ui", + "索引列表", + "索引", + "列表" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-indexed-list/readme.md b/uni_modules/uni-indexed-list/readme.md new file mode 100644 index 0000000..44ad84b --- /dev/null +++ b/uni_modules/uni-indexed-list/readme.md @@ -0,0 +1,11 @@ + + +## IndexedList 索引列表 +> **组件名:uni-indexed-list** +> 代码块: `uIndexedList` + + +用于展示索引列表。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-indexed-list) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 diff --git a/uni_modules/uni-link/changelog.md b/uni_modules/uni-link/changelog.md new file mode 100644 index 0000000..2cfbf59 --- /dev/null +++ b/uni_modules/uni-link/changelog.md @@ -0,0 +1,17 @@ +## 1.0.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-link](https://uniapp.dcloud.io/component/uniui/uni-link) +## 1.1.7(2021-11-08) +## 0.0.7(2021-09-03) +- 修复 在 nvue 下不显示的 bug +## 0.0.6(2021-07-30) +- 新增 支持自定义插槽 +## 0.0.5(2021-06-21) +- 新增 download 属性,H5平台下载文件名 +## 0.0.4(2021-05-12) +- 新增 组件示例地址 +## 0.0.3(2021-03-09) +- 新增 href 属性支持 tel:|mailto: + +## 0.0.2(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-link/components/uni-link/uni-link.vue b/uni_modules/uni-link/components/uni-link/uni-link.vue new file mode 100644 index 0000000..27c5468 --- /dev/null +++ b/uni_modules/uni-link/components/uni-link/uni-link.vue @@ -0,0 +1,128 @@ + + + + + diff --git a/uni_modules/uni-link/package.json b/uni_modules/uni-link/package.json new file mode 100644 index 0000000..77b1986 --- /dev/null +++ b/uni_modules/uni-link/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-link", + "displayName": "uni-link 超链接", + "version": "1.0.0", + "description": "uni-link是一个外部网页超链接组件,在小程序内复制url,在app内打开外部浏览器,在h5端打", + "keywords": [ + "uni-ui", + "uniui", + "link", + "超链接", + "" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-link/readme.md b/uni_modules/uni-link/readme.md new file mode 100644 index 0000000..7f09e94 --- /dev/null +++ b/uni_modules/uni-link/readme.md @@ -0,0 +1,11 @@ + + +## Link 链接 +> **组件名:uni-link** +> 代码块: `uLink` + + +uni-link是一个外部网页超链接组件,在小程序内复制url,在app内打开外部浏览器,在h5端打开新网页。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-link) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-list/changelog.md b/uni_modules/uni-list/changelog.md new file mode 100644 index 0000000..6aa6e4e --- /dev/null +++ b/uni_modules/uni-list/changelog.md @@ -0,0 +1,20 @@ +## 1.2.1(2022-03-30) +- 删除无用文件 +## 1.2.0(2021-11-23) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-list](https://uniapp.dcloud.io/component/uniui/uni-list) +## 1.1.3(2021-08-30) +- 修复 在vue3中to属性在发行应用的时候报错的bug +## 1.1.2(2021-07-30) +- 优化 vue3下事件警告的问题 +## 1.1.1(2021-07-21) +- 修复 与其他组件嵌套使用时,点击失效的Bug +## 1.1.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.17(2021-05-12) +- 新增 组件示例地址 +## 1.0.16(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 +## 1.0.15(2021-02-05) +- 调整为uni_modules目录规范 +- 修复 uni-list-chat 角标显示不正常的问题 diff --git a/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue b/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue new file mode 100644 index 0000000..b9349c2 --- /dev/null +++ b/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue @@ -0,0 +1,107 @@ + + + + + diff --git a/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss b/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss new file mode 100644 index 0000000..311f8d9 --- /dev/null +++ b/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss @@ -0,0 +1,58 @@ +/** + * 这里是 uni-list 组件内置的常用样式变量 + * 如果需要覆盖样式,这里提供了基本的组件样式变量,您可以尝试修改这里的变量,去完成样式替换,而不用去修改源码 + * + */ + +// 背景色 +$background-color : #fff; +// 分割线颜色 +$divide-line-color : #e5e5e5; + +// 默认头像大小,如需要修改此值,注意同步修改 js 中的值 const avatarWidth = xx ,目前只支持方形头像 +// nvue 页面不支持修改头像大小 +$avatar-width : 45px ; + +// 头像边框 +$avatar-border-radius: 5px; +$avatar-border-color: #eee; +$avatar-border-width: 1px; + +// 标题文字样式 +$title-size : 16px; +$title-color : #3b4144; +$title-weight : normal; + +// 描述文字样式 +$note-size : 12px; +$note-color : #999; +$note-weight : normal; + +// 右侧额外内容默认样式 +$right-text-size : 12px; +$right-text-color : #999; +$right-text-weight : normal; + +// 角标样式 +// nvue 页面不支持修改圆点位置以及大小 +// 角标在左侧时,角标的位置,默认为 0 ,负数左/下移动,正数右/上移动 +$badge-left: 0px; +$badge-top: 0px; + +// 显示圆点时,圆点大小 +$dot-width: 10px; +$dot-height: 10px; + +// 显示角标时,角标大小和字体大小 +$badge-size : 18px; +$badge-font : 12px; +// 显示角标时,角标前景色 +$badge-color : #fff; +// 显示角标时,角标背景色 +$badge-background-color : #ff5a5f; +// 显示角标时,角标左右间距 +$badge-space : 6px; + +// 状态样式 +// 选中颜色 +$hover : #f5f5f5; diff --git a/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue b/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue new file mode 100644 index 0000000..2b31008 --- /dev/null +++ b/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue @@ -0,0 +1,538 @@ + + + + + diff --git a/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue b/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue new file mode 100644 index 0000000..2c7d9ea --- /dev/null +++ b/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue @@ -0,0 +1,454 @@ + + + + + diff --git a/uni_modules/uni-list/components/uni-list/uni-list.vue b/uni_modules/uni-list/components/uni-list/uni-list.vue new file mode 100644 index 0000000..ecda676 --- /dev/null +++ b/uni_modules/uni-list/components/uni-list/uni-list.vue @@ -0,0 +1,108 @@ + + + + diff --git a/uni_modules/uni-list/components/uni-list/uni-refresh.vue b/uni_modules/uni-list/components/uni-list/uni-refresh.vue new file mode 100644 index 0000000..3b4c5a2 --- /dev/null +++ b/uni_modules/uni-list/components/uni-list/uni-refresh.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/uni_modules/uni-list/components/uni-list/uni-refresh.wxs b/uni_modules/uni-list/components/uni-list/uni-refresh.wxs new file mode 100644 index 0000000..818a6b7 --- /dev/null +++ b/uni_modules/uni-list/components/uni-list/uni-refresh.wxs @@ -0,0 +1,87 @@ +var pullDown = { + threshold: 95, + maxHeight: 200, + callRefresh: 'onrefresh', + callPullingDown: 'onpullingdown', + refreshSelector: '.uni-refresh' +}; + +function ready(newValue, oldValue, ownerInstance, instance) { + var state = instance.getState() + state.canPullDown = newValue; + // console.log(newValue); +} + +function touchStart(e, instance) { + var state = instance.getState(); + state.refreshInstance = instance.selectComponent(pullDown.refreshSelector); + state.canPullDown = (state.refreshInstance != null && state.refreshInstance != undefined); + if (!state.canPullDown) { + return + } + + // console.log("touchStart"); + + state.height = 0; + state.touchStartY = e.touches[0].pageY || e.changedTouches[0].pageY; + state.refreshInstance.setStyle({ + 'height': 0 + }); + state.refreshInstance.callMethod("onchange", true); +} + +function touchMove(e, ownerInstance) { + var instance = e.instance; + var state = instance.getState(); + if (!state.canPullDown) { + return + } + + var oldHeight = state.height; + var endY = e.touches[0].pageY || e.changedTouches[0].pageY; + var height = endY - state.touchStartY; + if (height > pullDown.maxHeight) { + return; + } + + var refreshInstance = state.refreshInstance; + refreshInstance.setStyle({ + 'height': height + 'px' + }); + + height = height < pullDown.maxHeight ? height : pullDown.maxHeight; + state.height = height; + refreshInstance.callMethod(pullDown.callPullingDown, { + height: height + }); +} + +function touchEnd(e, ownerInstance) { + var state = e.instance.getState(); + if (!state.canPullDown) { + return + } + + state.refreshInstance.callMethod("onchange", false); + + var refreshInstance = state.refreshInstance; + if (state.height > pullDown.threshold) { + refreshInstance.callMethod(pullDown.callRefresh); + return; + } + + refreshInstance.setStyle({ + 'height': 0 + }); +} + +function propObserver(newValue, oldValue, instance) { + pullDown = newValue; +} + +module.exports = { + touchmove: touchMove, + touchstart: touchStart, + touchend: touchEnd, + propObserver: propObserver +} diff --git a/uni_modules/uni-list/package.json b/uni_modules/uni-list/package.json new file mode 100644 index 0000000..66e8bef --- /dev/null +++ b/uni_modules/uni-list/package.json @@ -0,0 +1,91 @@ +{ + "id": "uni-list", + "displayName": "uni-list 列表", + "version": "1.2.1", + "description": "List 组件 ,帮助使用者快速构建列表。", + "keywords": [ + "", + "uni-ui", + "uniui", + "列表", + "", + "list" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-badge", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-list/readme.md b/uni_modules/uni-list/readme.md new file mode 100644 index 0000000..32c2865 --- /dev/null +++ b/uni_modules/uni-list/readme.md @@ -0,0 +1,346 @@ +## List 列表 +> **组件名:uni-list** +> 代码块: `uList`、`uListItem` +> 关联组件:`uni-list-item`、`uni-badge`、`uni-icons`、`uni-list-chat`、`uni-list-ad` + + +List 列表组件,包含基本列表样式、可扩展插槽机制、长列表性能优化、多端兼容。 + +在vue页面里,它默认使用页面级滚动。在app-nvue页面里,它默认使用原生list组件滚动。这样的长列表,在滚动出屏幕外后,系统会回收不可见区域的渲染内存资源,不会造成滚动越长手机越卡的问题。 + +uni-list组件是父容器,里面的核心是uni-list-item子组件,它代表列表中的一个可重复行,子组件可以无限循环。 + +uni-list-item有很多风格,uni-list-item组件通过内置的属性,满足一些常用的场景。当内置属性不满足需求时,可以通过扩展插槽来自定义列表内容。 + +内置属性可以覆盖的场景包括:导航列表、设置列表、小图标列表、通信录列表、聊天记录列表。 + +涉及很多大图或丰富内容的列表,比如类今日头条的新闻列表、类淘宝的电商列表,需要通过扩展插槽实现。 + +下文均有样例给出。 + +uni-list不包含下拉刷新和上拉翻页。上拉翻页另见组件:[uni-load-more](https://ext.dcloud.net.cn/plugin?id=29) + + +### 安装方式 + +本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。 + +如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55) + +> **注意事项** +> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。 +> - 组件需要依赖 `sass` 插件 ,请自行手动安装 +> - 组件内部依赖 `'uni-icons'` 、`uni-badge` 组件 +> - `uni-list` 和 `uni-list-item` 需要配套使用,暂不支持单独使用 `uni-list-item` +> - 只有开启点击反馈后,会有点击选中效果 +> - 使用插槽时,可以完全自定义内容 +> - note 、rightText 属性暂时没做限制,不支持文字溢出隐藏,使用时应该控制长度显示或通过默认插槽自行扩展 +> - 支付宝小程序平台需要在支付宝小程序开发者工具里开启 component2 编译模式,开启方式: 详情 --> 项目配置 --> 启用 component2 编译 +> - 如果需要修改 `switch`、`badge` 样式,请使用插槽自定义 +> - 在 `HBuilderX` 低版本中,可能会出现组件显示 `undefined` 的问题,请升级最新的 `HBuilderX` 或者 `cli` +> - 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + +### 基本用法 + +- 设置 `title` 属性,可以显示列表标题 +- 设置 `disabled` 属性,可以禁用当前项 + +```html + + + + + +``` + +### 多行内容显示 + +- 设置 `note` 属性 ,可以在第二行显示描述文本信息 + +```html + + + + + +``` + +### 右侧显示角标、switch + +- 设置 `show-badge` 属性 ,可以显示角标内容 +- 设置 `show-switch` 属性,可以显示 switch 开关 + +```html + + + + + +``` + +### 左侧显示略缩图、图标 + +- 设置 `thumb` 属性 ,可以在列表左侧显示略缩图 +- 设置 `show-extra-icon` 属性,并指定 `extra-icon` 可以在左侧显示图标 + +```html + + + + +``` + +### 开启点击反馈和右侧箭头 +- 设置 `clickable` 为 `true` ,则表示这是一个可点击的列表,会默认给一个点击效果,并可以监听 `click` 事件 +- 设置 `link` 属性,会自动开启点击反馈,并给列表右侧添加一个箭头 +- 设置 `to` 属性,可以跳转页面,`link` 的值表示跳转方式,如果不指定,默认为 `navigateTo` + +```html + + + + + + + +``` + + +### 聊天列表示例 +- 设置 `clickable` 为 `true` ,则表示这是一个可点击的列表,会默认给一个点击效果,并可以监听 `click` 事件 +- 设置 `link` 属性,会自动开启点击反馈,`link` 的值表示跳转方式,如果不指定,默认为 `navigateTo` +- 设置 `to` 属性,可以跳转页面 +- `time` 属性,通常会设置成时间显示,但是这个属性不仅仅可以设置时间,你可以传入任何文本,注意文本长度可能会影响显示 +- `avatar` 和 `avatarList` 属性同时只会有一个生效,同时设置的话,`avatarList` 属性的长度大于1 ,`avatar` 属性将失效 +- 可以通过默认插槽自定义列表右侧内容 + +```html + + + + + + + + + + + + + + + + + 刚刚 + + + + + + + +``` + +```javascript + +export default { + components: {}, + data() { + return { + avatarList: [{ + url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png' + }, { + url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png' + }, { + url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png' + }] + } + } +} + +``` + + +```css + +.chat-custom-right { + flex: 1; + /* #ifndef APP-NVUE */ + display: flex; + /* #endif */ + flex-direction: column; + justify-content: space-between; + align-items: flex-end; +} + +.chat-custom-text { + font-size: 12px; + color: #999; +} + +``` + +## API + +### List Props + +属性名 |类型 |默认值 | 说明 +:-: |:-: |:-: | :-: +border |Boolean |true | 是否显示边框 + + +### ListItem Props + +属性名 |类型 |默认值 | 说明 +:-: |:-: |:-: | :-: +title |String |- | 标题 +note |String |- | 描述 +ellipsis |Number |0 | title 是否溢出隐藏,可选值,0:默认; 1:显示一行; 2:显示两行;【nvue 暂不支持】 +thumb |String |- | 左侧缩略图,若thumb有值,则不会显示扩展图标 +thumbSize |String |medium | 略缩图尺寸,可选值,lg:大图; medium:一般; sm:小图; +showBadge |Boolean |false | 是否显示数字角标 +badgeText |String |- | 数字角标内容 +badgeType |String |- | 数字角标类型,参考[uni-icons](https://ext.dcloud.net.cn/plugin?id=21) +badgeStyle |Object |- | 数字角标样式,使用uni-badge的custom-style参数 +rightText |String |- | 右侧文字内容 +disabled |Boolean |false | 是否禁用 +showArrow |Boolean |true | 是否显示箭头图标 +link |String |navigateTo | 新页面跳转方式,可选值见下表 +to |String |- | 新页面跳转地址,如填写此属性,click 会返回页面是否跳转成功 +clickable |Boolean |false | 是否开启点击反馈 +showSwitch |Boolean |false | 是否显示Switch +switchChecked |Boolean |false | Switch是否被选中 +showExtraIcon |Boolean |false | 左侧是否显示扩展图标 +extraIcon |Object |- | 扩展图标参数,格式为 ``{color: '#4cd964',size: '22',type: 'spinner'}``,参考 [uni-icons](https://ext.dcloud.net.cn/plugin?id=28) +direction | String |row | 排版方向,可选值,row:水平排列; column:垂直排列; 3个插槽是水平排还是垂直排,也受此属性控制 + + +#### Link Options + +属性名 | 说明 +:-: | :-: +navigateTo | 同 uni.navigateTo() +redirectTo | 同 uni.reLaunch() +reLaunch | 同 uni.reLaunch() +switchTab | 同 uni.switchTab() + +### ListItem Events + +事件称名 |说明 |返回参数 +:-: |:-: |:-: +click |点击 uniListItem 触发事件,需开启点击反馈 |- +switchChange |点击切换 Switch 时触发,需显示 switch |e={value:checked} + + + +### ListItem Slots + +名称 | 说明 +:-: | :-: +header | 左/上内容插槽,可完全自定义默认显示 +body | 中间内容插槽,可完全自定义中间内容 +footer | 右/下内容插槽,可完全自定义右侧内容 + + +> **通过插槽扩展** +> 需要注意的是当使用插槽时,内置样式将会失效,只保留排版样式,此时的样式需要开发者自己实现 +> 如果 `uni-list-item` 组件内置属性样式无法满足需求,可以使用插槽来自定义uni-list-item里的内容。 +> uni-list-item提供了3个可扩展的插槽:`header`、`body`、`footer` +> - 当 `direction` 属性为 `row` 时表示水平排列,此时 `header` 表示列表的左边部分,`body` 表示列表的中间部分,`footer` 表示列表的右边部分 +> - 当 `direction` 属性为 `column` 时表示垂直排列,此时 `header` 表示列表的上边部分,`body` 表示列表的中间部分,`footer` 表示列表的下边部分 +> 开发者可以只用1个插槽,也可以3个一起使用。在插槽中可自主编写view标签,实现自己所需的效果。 + + +**示例** + +```html + + + + + + + + + 自定义插槽 + + + + +``` + + + + + +### ListItemChat Props + +属性名 |类型 |默认值 | 说明 +:-: |:-: |:-: | :-: +title |String |- | 标题 +note |String |- | 描述 +clickable |Boolean |false | 是否开启点击反馈 +badgeText |String |- | 数字角标内容,设置为 `dot` 将显示圆点 +badgePositon |String |right | 角标位置 +link |String |navigateTo | 是否展示右侧箭头并开启点击反馈,可选值见下表 +clickable |Boolean |false | 是否开启点击反馈 +to |String |- | 跳转页面地址,如填写此属性,click 会返回页面是否跳转成功 +time |String |- | 右侧时间显示 +avatarCircle |Boolean |false | 是否显示圆形头像 +avatar |String |- | 头像地址,avatarCircle 不填时生效 +avatarList |Array |- | 头像组,格式为 [{url:''}] + +#### Link Options + +属性名 | 说明 +:-: | :-: +navigateTo | 同 uni.navigateTo() +redirectTo | 同 uni.reLaunch() +reLaunch | 同 uni.reLaunch() +switchTab | 同 uni.switchTab() + +### ListItemChat Slots + +名称 | 说明 +:- | :- +default | 自定义列表右侧内容(包括时间和角标显示) + +### ListItemChat Events +事件称名 | 说明 | 返回参数 +:-: | :-: | :-: +@click | 点击 uniListChat 触发事件 | {data:{}} ,如有 to 属性,会返回页面跳转信息 + + + + + + +## 基于uni-list扩展的页面模板 + +通过扩展插槽,可实现多种常见样式的列表 + +**新闻列表类** + +1. 云端一体混合布局:[https://ext.dcloud.net.cn/plugin?id=2546](https://ext.dcloud.net.cn/plugin?id=2546) +2. 云端一体垂直布局,大图模式:[https://ext.dcloud.net.cn/plugin?id=2583](https://ext.dcloud.net.cn/plugin?id=2583) +3. 云端一体垂直布局,多行图文混排:[https://ext.dcloud.net.cn/plugin?id=2584](https://ext.dcloud.net.cn/plugin?id=2584) +4. 云端一体垂直布局,多图模式:[https://ext.dcloud.net.cn/plugin?id=2585](https://ext.dcloud.net.cn/plugin?id=2585) +5. 云端一体水平布局,左图右文:[https://ext.dcloud.net.cn/plugin?id=2586](https://ext.dcloud.net.cn/plugin?id=2586) +6. 云端一体水平布局,左文右图:[https://ext.dcloud.net.cn/plugin?id=2587](https://ext.dcloud.net.cn/plugin?id=2587) +7. 云端一体垂直布局,无图模式,主标题+副标题:[https://ext.dcloud.net.cn/plugin?id=2588](https://ext.dcloud.net.cn/plugin?id=2588) + +**商品列表类** + +1. 云端一体列表/宫格视图互切:[https://ext.dcloud.net.cn/plugin?id=2651](https://ext.dcloud.net.cn/plugin?id=2651) +2. 云端一体列表(宫格模式):[https://ext.dcloud.net.cn/plugin?id=2671](https://ext.dcloud.net.cn/plugin?id=2671) +3. 云端一体列表(列表模式):[https://ext.dcloud.net.cn/plugin?id=2672](https://ext.dcloud.net.cn/plugin?id=2672) + +## 组件示例 + +点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/list/list](https://hellouniapp.dcloud.net.cn/pages/extUI/list/list) \ No newline at end of file diff --git a/uni_modules/uni-load-more/changelog.md b/uni_modules/uni-load-more/changelog.md new file mode 100644 index 0000000..8f03f1d --- /dev/null +++ b/uni_modules/uni-load-more/changelog.md @@ -0,0 +1,19 @@ +## 1.3.3(2022-01-20) +- 新增 showText属性 ,是否显示文本 +## 1.3.2(2022-01-19) +- 修复 nvue 平台下不显示文本的bug +## 1.3.1(2022-01-19) +- 修复 微信小程序平台样式选择器报警告的问题 +## 1.3.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-load-more](https://uniapp.dcloud.io/component/uniui/uni-load-more) +## 1.2.1(2021-08-24) +- 新增 支持国际化 +## 1.2.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.1.8(2021-05-12) +- 新增 组件示例地址 +## 1.1.7(2021-03-30) +- 修复 uni-load-more 在首页使用时,h5 平台报 'uni is not defined' 的 bug +## 1.1.6(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json b/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json new file mode 100644 index 0000000..a4f14a5 --- /dev/null +++ b/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json @@ -0,0 +1,5 @@ +{ + "uni-load-more.contentdown": "Pull up to show more", + "uni-load-more.contentrefresh": "loading...", + "uni-load-more.contentnomore": "No more data" +} diff --git a/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js b/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js new file mode 100644 index 0000000..de7509c --- /dev/null +++ b/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js @@ -0,0 +1,8 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json b/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json new file mode 100644 index 0000000..f15d510 --- /dev/null +++ b/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json @@ -0,0 +1,5 @@ +{ + "uni-load-more.contentdown": "上拉显示更多", + "uni-load-more.contentrefresh": "正在加载...", + "uni-load-more.contentnomore": "没有更多数据了" +} diff --git a/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json b/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json new file mode 100644 index 0000000..a255c6d --- /dev/null +++ b/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json @@ -0,0 +1,5 @@ +{ + "uni-load-more.contentdown": "上拉顯示更多", + "uni-load-more.contentrefresh": "正在加載...", + "uni-load-more.contentnomore": "沒有更多數據了" +} diff --git a/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue b/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue new file mode 100644 index 0000000..e5eff4d --- /dev/null +++ b/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue @@ -0,0 +1,399 @@ + + + + + diff --git a/uni_modules/uni-load-more/package.json b/uni_modules/uni-load-more/package.json new file mode 100644 index 0000000..2fa6f04 --- /dev/null +++ b/uni_modules/uni-load-more/package.json @@ -0,0 +1,86 @@ +{ + "id": "uni-load-more", + "displayName": "uni-load-more 加载更多", + "version": "1.3.3", + "description": "LoadMore 组件,常用在列表里面,做滚动加载使用。", + "keywords": [ + "uni-ui", + "uniui", + "加载更多", + "load-more" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-load-more/readme.md b/uni_modules/uni-load-more/readme.md new file mode 100644 index 0000000..54dc1fa --- /dev/null +++ b/uni_modules/uni-load-more/readme.md @@ -0,0 +1,14 @@ + + +### LoadMore 加载更多 +> **组件名:uni-load-more** +> 代码块: `uLoadMore` + + +用于列表中,做滚动加载使用,展示 loading 的各种状态。 + + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-load-more) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/uni_modules/uni-nav-bar/changelog.md b/uni_modules/uni-nav-bar/changelog.md new file mode 100644 index 0000000..fbacca4 --- /dev/null +++ b/uni_modules/uni-nav-bar/changelog.md @@ -0,0 +1,37 @@ +## 1.3.4(2022-01-24) +- 更新 组件示例 +## 1.3.3(2022-01-24) +- 新增 left-width/right-width属性 ,可修改左右两侧的宽度 +## 1.3.2(2022-01-18) +- 修复 在vue下,标题不垂直居中的bug +## 1.3.1(2022-01-18) +- 修复 height 属性类型错误 +## 1.3.0(2022-01-18) +- 新增 height 属性,可修改组件高度 +- 新增 dark 属性可可开启暗黑模式 +- 优化 标题字数过多显示省略号 +- 优化 插槽,插入内容可完全覆盖 +## 1.2.1(2022-01-10) +- 修复 color 属性不生效的bug +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-nav-bar](https://uniapp.dcloud.io/component/uniui/uni-nav-bar) +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.11(2021-05-12) +- 新增 组件示例地址 +## 1.0.10(2021-04-30) +- 修复 在nvue下fixed为true,宽度不能撑满的Bug +## 1.0.9(2021-04-21) +- 优化 添加依赖 uni-icons, 导入后自动下载依赖 +## 1.0.8(2021-04-14) +- uni-ui 修复 uni-nav-bar 当 fixed 属性为 true 时铺不满屏幕的 bug + +## 1.0.7(2021-02-25) +- 修复 easycom 下,找不到 uni-status-bar 的bug + +## 1.0.6(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 + +## 1.0.5(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue b/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue new file mode 100644 index 0000000..08712ab --- /dev/null +++ b/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue @@ -0,0 +1,343 @@ + + + + + diff --git a/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue b/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue new file mode 100644 index 0000000..6a68874 --- /dev/null +++ b/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue @@ -0,0 +1,27 @@ + + + + + diff --git a/uni_modules/uni-nav-bar/package.json b/uni_modules/uni-nav-bar/package.json new file mode 100644 index 0000000..e1473ca --- /dev/null +++ b/uni_modules/uni-nav-bar/package.json @@ -0,0 +1,89 @@ +{ + "id": "uni-nav-bar", + "displayName": "uni-nav-bar 自定义导航栏", + "version": "1.3.4", + "description": "自定义导航栏组件,主要用于头部导航。", + "keywords": [ + "uni-ui", + "导航", + "导航栏", + "自定义导航栏" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-nav-bar/readme.md b/uni_modules/uni-nav-bar/readme.md new file mode 100644 index 0000000..3934b32 --- /dev/null +++ b/uni_modules/uni-nav-bar/readme.md @@ -0,0 +1,15 @@ + + +## NavBar 导航栏 +> **组件名:uni-nav-bar** +> 代码块: `uNavBar` + +导航栏组件,主要用于头部导航。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-nav-bar) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + + + + diff --git a/uni_modules/uni-notice-bar/changelog.md b/uni_modules/uni-notice-bar/changelog.md new file mode 100644 index 0000000..9ee75a0 --- /dev/null +++ b/uni_modules/uni-notice-bar/changelog.md @@ -0,0 +1,16 @@ +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-notice-bar](https://uniapp.dcloud.io/component/uniui/uni-notice-bar) +## 1.1.1(2021-11-09) +- 新增 提供组件设计资源,组件样式调整 +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.9(2021-05-12) +- 新增 组件示例地址 +## 1.0.8(2021-04-21) +- 优化 添加依赖 uni-icons, 导入后自动下载依赖 +## 1.0.7(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 + +## 1.0.6(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue b/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue new file mode 100644 index 0000000..1d2ac1d --- /dev/null +++ b/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue @@ -0,0 +1,395 @@ + + + + + diff --git a/uni_modules/uni-notice-bar/package.json b/uni_modules/uni-notice-bar/package.json new file mode 100644 index 0000000..97719a0 --- /dev/null +++ b/uni_modules/uni-notice-bar/package.json @@ -0,0 +1,90 @@ +{ + "id": "uni-notice-bar", + "displayName": "uni-notice-bar 通告栏", + "version": "1.2.0", + "description": "NoticeBar 通告栏组件,常用于展示公告信息,可设为滚动公告", + "keywords": [ + "uni-ui", + "uniui", + "通告栏", + "公告", + "跑马灯" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-notice-bar/readme.md b/uni_modules/uni-notice-bar/readme.md new file mode 100644 index 0000000..fb2ede2 --- /dev/null +++ b/uni_modules/uni-notice-bar/readme.md @@ -0,0 +1,13 @@ + + +## NoticeBar 通告栏 +> **组件名:uni-notice-bar** +> 代码块: `uNoticeBar` + + +通告栏组件 。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-notice-bar) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/uni_modules/uni-number-box/changelog.md b/uni_modules/uni-number-box/changelog.md new file mode 100644 index 0000000..5925c32 --- /dev/null +++ b/uni_modules/uni-number-box/changelog.md @@ -0,0 +1,25 @@ +## 1.2.1(2021-11-22) +- 修复 vue3中某些scss变量无法找到的问题 +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-number-box](https://uniapp.dcloud.io/component/uniui/uni-number-box) +## 1.1.2(2021-11-09) +- 新增 提供组件设计资源,组件样式调整 +## 1.1.1(2021-07-30) +- 优化 vue3下事件警告的问题 +## 1.1.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.7(2021-05-12) +- 新增 组件示例地址 +## 1.0.6(2021-04-20) +- 修复 uni-number-box 浮点数运算不精确的 bug +- 修复 uni-number-box change 事件触发不正确的 bug +- 新增 uni-number-box v-model 双向绑定 +## 1.0.5(2021-02-05) +- 调整为uni_modules目录规范 + +## 1.0.7(2021-02-05) +- 调整为uni_modules目录规范 +- 新增 支持 v-model +- 新增 支持 focus、blur 事件 +- 新增 支持 PC 端 diff --git a/uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue b/uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue new file mode 100644 index 0000000..e91c032 --- /dev/null +++ b/uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue @@ -0,0 +1,221 @@ + + + diff --git a/uni_modules/uni-number-box/package.json b/uni_modules/uni-number-box/package.json new file mode 100644 index 0000000..ad82336 --- /dev/null +++ b/uni_modules/uni-number-box/package.json @@ -0,0 +1,85 @@ +{ + "id": "uni-number-box", + "displayName": "uni-number-box 数字输入框", + "version": "1.2.1", + "description": "NumberBox 带加减按钮的数字输入框组件,用户可以控制每次点击增加的数值,支持小数。", + "keywords": [ + "uni-ui", + "uniui", + "数字输入框" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-number-box/readme.md b/uni_modules/uni-number-box/readme.md new file mode 100644 index 0000000..affc56f --- /dev/null +++ b/uni_modules/uni-number-box/readme.md @@ -0,0 +1,13 @@ + + +## NumberBox 数字输入框 +> **组件名:uni-number-box** +> 代码块: `uNumberBox` + + +带加减按钮的数字输入框。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-number-box) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/uni_modules/uni-pagination/changelog.md b/uni_modules/uni-pagination/changelog.md new file mode 100644 index 0000000..336c2ba --- /dev/null +++ b/uni_modules/uni-pagination/changelog.md @@ -0,0 +1,20 @@ +## 1.2.1(2021-11-22) +- 修复 vue3中某些scss变量无法找到的问题 +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-pagination](https://uniapp.dcloud.io/component/uniui/uni-pagination) +## 1.1.2(2021-10-08) +- 修复 current 、value 属性未监听,导致高亮样式失效的 bug +## 1.1.1(2021-08-20) +- 新增 支持国际化 +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.7(2021-05-12) +- 新增 组件示例地址 +## 1.0.6(2021-04-12) +- 新增 PC 和 移动端适配不同的 ui +## 1.0.5(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 + +## 1.0.4(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-pagination/components/uni-pagination/i18n/en.json b/uni_modules/uni-pagination/components/uni-pagination/i18n/en.json new file mode 100644 index 0000000..a57becd --- /dev/null +++ b/uni_modules/uni-pagination/components/uni-pagination/i18n/en.json @@ -0,0 +1,4 @@ +{ + "uni-pagination.prevText": "prev", + "uni-pagination.nextText": "next" +} diff --git a/uni_modules/uni-pagination/components/uni-pagination/i18n/es.json b/uni_modules/uni-pagination/components/uni-pagination/i18n/es.json new file mode 100644 index 0000000..ccbba2f --- /dev/null +++ b/uni_modules/uni-pagination/components/uni-pagination/i18n/es.json @@ -0,0 +1,4 @@ +{ + "uni-pagination.prevText": "anterior", + "uni-pagination.nextText": "próxima" +} diff --git a/uni_modules/uni-pagination/components/uni-pagination/i18n/fr.json b/uni_modules/uni-pagination/components/uni-pagination/i18n/fr.json new file mode 100644 index 0000000..9b5f2d9 --- /dev/null +++ b/uni_modules/uni-pagination/components/uni-pagination/i18n/fr.json @@ -0,0 +1,4 @@ +{ + "uni-pagination.prevText": "précédente", + "uni-pagination.nextText": "suivante" +} diff --git a/uni_modules/uni-pagination/components/uni-pagination/i18n/index.js b/uni_modules/uni-pagination/components/uni-pagination/i18n/index.js new file mode 100644 index 0000000..2469dd0 --- /dev/null +++ b/uni_modules/uni-pagination/components/uni-pagination/i18n/index.js @@ -0,0 +1,12 @@ +import en from './en.json' +import es from './es.json' +import fr from './fr.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + es, + fr, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hans.json b/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hans.json new file mode 100644 index 0000000..fedbe82 --- /dev/null +++ b/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hans.json @@ -0,0 +1,4 @@ +{ + "uni-pagination.prevText": "上一页", + "uni-pagination.nextText": "下一页" +} diff --git a/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hant.json b/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hant.json new file mode 100644 index 0000000..133b340 --- /dev/null +++ b/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hant.json @@ -0,0 +1,4 @@ +{ + "uni-pagination.prevText": "上一頁", + "uni-pagination.nextText": "下一頁" +} diff --git a/uni_modules/uni-pagination/components/uni-pagination/uni-pagination.vue b/uni_modules/uni-pagination/components/uni-pagination/uni-pagination.vue new file mode 100644 index 0000000..79db4b8 --- /dev/null +++ b/uni_modules/uni-pagination/components/uni-pagination/uni-pagination.vue @@ -0,0 +1,409 @@ + + + + + diff --git a/uni_modules/uni-pagination/package.json b/uni_modules/uni-pagination/package.json new file mode 100644 index 0000000..adce670 --- /dev/null +++ b/uni_modules/uni-pagination/package.json @@ -0,0 +1,86 @@ +{ + "id": "uni-pagination", + "displayName": "uni-pagination 分页器", + "version": "1.2.1", + "description": "Pagination 分页器组件,用于展示页码、请求数据等。", + "keywords": [ + "uni-ui", + "uniui", + "分页器", + "页码" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss","uni-icons"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-pagination/readme.md b/uni_modules/uni-pagination/readme.md new file mode 100644 index 0000000..eefa263 --- /dev/null +++ b/uni_modules/uni-pagination/readme.md @@ -0,0 +1,13 @@ + + +## Pagination 分页器 +> **组件名:uni-pagination** +> 代码块: `uPagination` + + +分页器组件,用于展示页码、请求数据等。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-pagination) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/uni_modules/uni-popup/changelog.md b/uni_modules/uni-popup/changelog.md new file mode 100644 index 0000000..a9e2d66 --- /dev/null +++ b/uni_modules/uni-popup/changelog.md @@ -0,0 +1,60 @@ +## 1.7.9(2022-04-02) +- 修复 弹出层内部无法滚动的bug +## 1.7.8(2022-03-28) +- 修复 小程序中高度错误的bug +## 1.7.7(2022-03-17) +- 修复 快速调用open出现问题的Bug +## 1.7.6(2022-02-14) +- 修复 safeArea 属性不能设置为false的bug +## 1.7.5(2022-01-19) +- 修复 isMaskClick 失效的bug +## 1.7.4(2022-01-19) +- 新增 cancelText \ confirmText 属性 ,可自定义文本 +- 新增 maskBackgroundColor 属性 ,可以修改蒙版颜色 +- 优化 maskClick属性 更新为 isMaskClick ,解决微信小程序警告的问题 +## 1.7.3(2022-01-13) +- 修复 设置 safeArea 属性不生效的bug +## 1.7.2(2021-11-26) +- 优化 组件示例 +## 1.7.1(2021-11-26) +- 修复 vuedoc 文字错误 +## 1.7.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-popup](https://uniapp.dcloud.io/component/uniui/uni-popup) +## 1.6.2(2021-08-24) +- 新增 支持国际化 +## 1.6.1(2021-07-30) +- 优化 vue3下事件警告的问题 +## 1.6.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.5.0(2021-06-23) +- 新增 mask-click 遮罩层点击事件 +## 1.4.5(2021-06-22) +- 修复 nvue 平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug +## 1.4.4(2021-06-18) +- 修复 H5平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug +## 1.4.3(2021-06-08) +- 修复 错误的 watch 字段 +- 修复 safeArea 属性不生效的问题 +- 修复 点击内容,再点击遮罩无法关闭的Bug +## 1.4.2(2021-05-12) +- 新增 组件示例地址 +## 1.4.1(2021-04-29) +- 修复 组件内放置 input 、textarea 组件,无法聚焦的问题 +## 1.4.0 (2021-04-29) +- 新增 type 属性的 left\right 值,支持左右弹出 +- 新增 open(String:type) 方法参数 ,可以省略 type 属性 ,直接传入类型打开指定弹窗 +- 新增 backgroundColor 属性,可定义主窗口背景色,默认不显示背景色 +- 新增 safeArea 属性,是否适配底部安全区 +- 修复 App\h5\微信小程序底部安全区占位不对的Bug +- 修复 App 端弹出等待的Bug +- 优化 提升低配设备性能,优化动画卡顿问题 +- 优化 更简单的组件自定义方式 +## 1.2.9(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 +## 1.2.8(2021-02-05) +- 调整为uni_modules目录规范 +## 1.2.7(2021-02-05) +- 调整为uni_modules目录规范 +- 新增 支持 PC 端 +- 新增 uni-popup-message 、uni-popup-dialog扩展组件支持 PC 端 diff --git a/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js b/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js new file mode 100644 index 0000000..6ef26a2 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js @@ -0,0 +1,45 @@ +// #ifdef H5 +export default { + name: 'Keypress', + props: { + disable: { + type: Boolean, + default: false + } + }, + mounted () { + const keyNames = { + esc: ['Esc', 'Escape'], + tab: 'Tab', + enter: 'Enter', + space: [' ', 'Spacebar'], + up: ['Up', 'ArrowUp'], + left: ['Left', 'ArrowLeft'], + right: ['Right', 'ArrowRight'], + down: ['Down', 'ArrowDown'], + delete: ['Backspace', 'Delete', 'Del'] + } + const listener = ($event) => { + if (this.disable) { + return + } + const keyName = Object.keys(keyNames).find(key => { + const keyName = $event.key + const value = keyNames[key] + return value === keyName || (Array.isArray(value) && value.includes(keyName)) + }) + if (keyName) { + // 避免和其他按键事件冲突 + setTimeout(() => { + this.$emit(keyName, {}) + }, 0) + } + } + document.addEventListener('keyup', listener) + this.$once('hook:beforeDestroy', () => { + document.removeEventListener('keyup', listener) + }) + }, + render: () => {} +} +// #endif diff --git a/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue b/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue new file mode 100644 index 0000000..a5d0f2a --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue @@ -0,0 +1,271 @@ + + + + + diff --git a/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue b/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue new file mode 100644 index 0000000..91370a8 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue @@ -0,0 +1,143 @@ + + + + diff --git a/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue b/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue new file mode 100644 index 0000000..5be7624 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue @@ -0,0 +1,187 @@ + + + + diff --git a/uni_modules/uni-popup/components/uni-popup/i18n/en.json b/uni_modules/uni-popup/components/uni-popup/i18n/en.json new file mode 100644 index 0000000..7f1bd06 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/i18n/en.json @@ -0,0 +1,7 @@ +{ + "uni-popup.cancel": "cancel", + "uni-popup.ok": "ok", + "uni-popup.placeholder": "pleace enter", + "uni-popup.title": "Hint", + "uni-popup.shareTitle": "Share to" +} diff --git a/uni_modules/uni-popup/components/uni-popup/i18n/index.js b/uni_modules/uni-popup/components/uni-popup/i18n/index.js new file mode 100644 index 0000000..de7509c --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/i18n/index.js @@ -0,0 +1,8 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json b/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json new file mode 100644 index 0000000..5e3003c --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json @@ -0,0 +1,7 @@ +{ + "uni-popup.cancel": "取消", + "uni-popup.ok": "确定", + "uni-popup.placeholder": "请输入", + "uni-popup.title": "提示", + "uni-popup.shareTitle": "分享到" +} diff --git a/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json b/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json new file mode 100644 index 0000000..13e39eb --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json @@ -0,0 +1,7 @@ +{ + "uni-popup.cancel": "取消", + "uni-popup.ok": "確定", + "uni-popup.placeholder": "請輸入", + "uni-popup.title": "提示", + "uni-popup.shareTitle": "分享到" +} diff --git a/uni_modules/uni-popup/components/uni-popup/keypress.js b/uni_modules/uni-popup/components/uni-popup/keypress.js new file mode 100644 index 0000000..62dda46 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/keypress.js @@ -0,0 +1,45 @@ +// #ifdef H5 +export default { + name: 'Keypress', + props: { + disable: { + type: Boolean, + default: false + } + }, + mounted () { + const keyNames = { + esc: ['Esc', 'Escape'], + tab: 'Tab', + enter: 'Enter', + space: [' ', 'Spacebar'], + up: ['Up', 'ArrowUp'], + left: ['Left', 'ArrowLeft'], + right: ['Right', 'ArrowRight'], + down: ['Down', 'ArrowDown'], + delete: ['Backspace', 'Delete', 'Del'] + } + const listener = ($event) => { + if (this.disable) { + return + } + const keyName = Object.keys(keyNames).find(key => { + const keyName = $event.key + const value = keyNames[key] + return value === keyName || (Array.isArray(value) && value.includes(keyName)) + }) + if (keyName) { + // 避免和其他按键事件冲突 + setTimeout(() => { + this.$emit(keyName, {}) + }, 0) + } + } + document.addEventListener('keyup', listener) + // this.$once('hook:beforeDestroy', () => { + // document.removeEventListener('keyup', listener) + // }) + }, + render: () => {} +} +// #endif diff --git a/uni_modules/uni-popup/components/uni-popup/popup.js b/uni_modules/uni-popup/components/uni-popup/popup.js new file mode 100644 index 0000000..c4e5781 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/popup.js @@ -0,0 +1,26 @@ + +export default { + data() { + return { + + } + }, + created(){ + this.popup = this.getParent() + }, + methods:{ + /** + * 获取父元素实例 + */ + getParent(name = 'uniPopup') { + let parent = this.$parent; + let parentName = parent.$options.name; + while (parentName !== name) { + parent = parent.$parent; + if (!parent) return false + parentName = parent.$options.name; + } + return parent; + }, + } +} diff --git a/uni_modules/uni-popup/components/uni-popup/uni-popup.vue b/uni_modules/uni-popup/components/uni-popup/uni-popup.vue new file mode 100644 index 0000000..db90c59 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/uni-popup.vue @@ -0,0 +1,474 @@ + + + + diff --git a/uni_modules/uni-popup/package.json b/uni_modules/uni-popup/package.json new file mode 100644 index 0000000..069e9ce --- /dev/null +++ b/uni_modules/uni-popup/package.json @@ -0,0 +1,90 @@ +{ + "id": "uni-popup", + "displayName": "uni-popup 弹出层", + "version": "1.7.9", + "description": " Popup 组件,提供常用的弹层", + "keywords": [ + "uni-ui", + "弹出层", + "弹窗", + "popup", + "弹框" + ], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-transition" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-popup/readme.md b/uni_modules/uni-popup/readme.md new file mode 100644 index 0000000..fdad4b3 --- /dev/null +++ b/uni_modules/uni-popup/readme.md @@ -0,0 +1,17 @@ + + +## Popup 弹出层 +> **组件名:uni-popup** +> 代码块: `uPopup` +> 关联组件:`uni-transition` + + +弹出层组件,在应用中弹出一个消息提示窗口、提示框等 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-popup) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + + + + diff --git a/uni_modules/uni-rate/changelog.md b/uni_modules/uni-rate/changelog.md new file mode 100644 index 0000000..8a98a61 --- /dev/null +++ b/uni_modules/uni-rate/changelog.md @@ -0,0 +1,25 @@ +## 1.3.1(2022-02-25) +- 修复 条件判断 `NaN` 错误的 bug +## 1.3.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-rate](https://uniapp.dcloud.io/component/uniui/uni-rate) +## 1.2.2(2021-09-10) +- 优化 默认值修改为 0 颗星 +## 1.2.1(2021-07-30) +- 优化 vue3下事件警告的问题 +## 1.2.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.1.2(2021-05-12) +- 新增 组件示例地址 +## 1.1.1(2021-04-21) +- 修复 布局变化后 uni-rate 星星计算不准确的 bug +- 优化 添加依赖 uni-icons, 导入 uni-rate 自动下载依赖 +## 1.1.0(2021-04-16) +- 修复 uni-rate 属性 margin 值为 string 组件失效的 bug + +## 1.0.9(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 + +## 1.0.8(2021-02-05) +- 调整为uni_modules目录规范 +- 支持 pc 端 diff --git a/uni_modules/uni-rate/components/uni-rate/uni-rate.vue b/uni_modules/uni-rate/components/uni-rate/uni-rate.vue new file mode 100644 index 0000000..857f5f9 --- /dev/null +++ b/uni_modules/uni-rate/components/uni-rate/uni-rate.vue @@ -0,0 +1,361 @@ + + + + + diff --git a/uni_modules/uni-rate/package.json b/uni_modules/uni-rate/package.json new file mode 100644 index 0000000..64e8e33 --- /dev/null +++ b/uni_modules/uni-rate/package.json @@ -0,0 +1,88 @@ +{ + "id": "uni-rate", + "displayName": "uni-rate 评分", + "version": "1.3.1", + "description": "Rate 评分组件,可自定义评分星星图标的大小、间隔、评分数。", + "keywords": [ + "uni-ui", + "uniui", + "评分" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-rate/readme.md b/uni_modules/uni-rate/readme.md new file mode 100644 index 0000000..eae7b5c --- /dev/null +++ b/uni_modules/uni-rate/readme.md @@ -0,0 +1,12 @@ + + +## Rate 评分 +> **组件名:uni-rate** +> 代码块: `uRate` +> 关联组件:`uni-icons` + + +评分组件,多用于购买商品后,对商品进行评价等场景 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-rate) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-row/changelog.md b/uni_modules/uni-row/changelog.md new file mode 100644 index 0000000..5b465bc --- /dev/null +++ b/uni_modules/uni-row/changelog.md @@ -0,0 +1,10 @@ +## 1.0.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-row](https://uniapp.dcloud.io/component/uniui/uni-row) +## 0.1.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 0.0.4(2021-05-12) +- 新增 组件示例地址 +## 0.0.3(2021-02-05) +- 调整为uni_modules目录规范 +- 新增uni-row组件 diff --git a/uni_modules/uni-row/components/uni-col/uni-col.vue b/uni_modules/uni-row/components/uni-col/uni-col.vue new file mode 100644 index 0000000..d5f3728 --- /dev/null +++ b/uni_modules/uni-row/components/uni-col/uni-col.vue @@ -0,0 +1,317 @@ + + + + + diff --git a/uni_modules/uni-row/components/uni-row/uni-row.vue b/uni_modules/uni-row/components/uni-row/uni-row.vue new file mode 100644 index 0000000..c7d9370 --- /dev/null +++ b/uni_modules/uni-row/components/uni-row/uni-row.vue @@ -0,0 +1,190 @@ + + + + + diff --git a/uni_modules/uni-row/package.json b/uni_modules/uni-row/package.json new file mode 100644 index 0000000..3f52fa6 --- /dev/null +++ b/uni_modules/uni-row/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-row", + "displayName": "uni-row 布局-行", + "version": "1.0.0", + "description": "流式栅格系统,随着屏幕或视口分为 24 份,可以迅速简便地创建布局。", + "keywords": [ + "uni-ui", + "uniui", + "栅格", + "布局", + "layout" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-row/readme.md b/uni_modules/uni-row/readme.md new file mode 100644 index 0000000..3c9c8b9 --- /dev/null +++ b/uni_modules/uni-row/readme.md @@ -0,0 +1,10 @@ +## Layout 布局 + +> **组件名 uni-row、uni-col** +> 代码块: `uRow`、`uCol` + + +流式栅格系统,随着屏幕或视口分为 24 份,可以迅速简便地创建布局。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-row) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-scss/changelog.md b/uni_modules/uni-scss/changelog.md new file mode 100644 index 0000000..b863bb0 --- /dev/null +++ b/uni_modules/uni-scss/changelog.md @@ -0,0 +1,8 @@ +## 1.0.3(2022-01-21) +- 优化 组件示例 +## 1.0.2(2021-11-22) +- 修复 / 符号在 vue 不同版本兼容问题引起的报错问题 +## 1.0.1(2021-11-22) +- 修复 vue3中scss语法兼容问题 +## 1.0.0(2021-11-18) +- init diff --git a/uni_modules/uni-scss/index.scss b/uni_modules/uni-scss/index.scss new file mode 100644 index 0000000..1744a5f --- /dev/null +++ b/uni_modules/uni-scss/index.scss @@ -0,0 +1 @@ +@import './styles/index.scss'; diff --git a/uni_modules/uni-scss/package.json b/uni_modules/uni-scss/package.json new file mode 100644 index 0000000..7cc0ccb --- /dev/null +++ b/uni_modules/uni-scss/package.json @@ -0,0 +1,82 @@ +{ + "id": "uni-scss", + "displayName": "uni-scss 辅助样式", + "version": "1.0.3", + "description": "uni-sass是uni-ui提供的一套全局样式 ,通过一些简单的类名和sass变量,实现简单的页面布局操作,比如颜色、边距、圆角等。", + "keywords": [ + "uni-scss", + "uni-ui", + "辅助样式" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "^3.1.0" + }, + "dcloudext": { + "category": [ + "JS SDK", + "通用 SDK" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "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", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "n", + "联盟": "n" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-scss/readme.md b/uni_modules/uni-scss/readme.md new file mode 100644 index 0000000..b7d1c25 --- /dev/null +++ b/uni_modules/uni-scss/readme.md @@ -0,0 +1,4 @@ +`uni-sass` 是 `uni-ui`提供的一套全局样式 ,通过一些简单的类名和`sass`变量,实现简单的页面布局操作,比如颜色、边距、圆角等。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-sass) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-scss/styles/index.scss b/uni_modules/uni-scss/styles/index.scss new file mode 100644 index 0000000..ffac4fe --- /dev/null +++ b/uni_modules/uni-scss/styles/index.scss @@ -0,0 +1,7 @@ +@import './setting/_variables.scss'; +@import './setting/_border.scss'; +@import './setting/_color.scss'; +@import './setting/_space.scss'; +@import './setting/_radius.scss'; +@import './setting/_text.scss'; +@import './setting/_styles.scss'; diff --git a/uni_modules/uni-scss/styles/setting/_border.scss b/uni_modules/uni-scss/styles/setting/_border.scss new file mode 100644 index 0000000..12a11c3 --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_border.scss @@ -0,0 +1,3 @@ +.uni-border { + border: 1px $uni-border-1 solid; +} \ No newline at end of file diff --git a/uni_modules/uni-scss/styles/setting/_color.scss b/uni_modules/uni-scss/styles/setting/_color.scss new file mode 100644 index 0000000..1ededd9 --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_color.scss @@ -0,0 +1,66 @@ + +// TODO 暂时不需要 class ,需要用户使用变量实现 ,如果使用类名其实并不推荐 +// @mixin get-styles($k,$c) { +// @if $k == size or $k == weight{ +// font-#{$k}:#{$c} +// }@else{ +// #{$k}:#{$c} +// } +// } +$uni-ui-color:( + // 主色 + primary: $uni-primary, + primary-disable: $uni-primary-disable, + primary-light: $uni-primary-light, + // 辅助色 + success: $uni-success, + success-disable: $uni-success-disable, + success-light: $uni-success-light, + warning: $uni-warning, + warning-disable: $uni-warning-disable, + warning-light: $uni-warning-light, + error: $uni-error, + error-disable: $uni-error-disable, + error-light: $uni-error-light, + info: $uni-info, + info-disable: $uni-info-disable, + info-light: $uni-info-light, + // 中性色 + main-color: $uni-main-color, + base-color: $uni-base-color, + secondary-color: $uni-secondary-color, + extra-color: $uni-extra-color, + // 背景色 + bg-color: $uni-bg-color, + // 边框颜色 + border-1: $uni-border-1, + border-2: $uni-border-2, + border-3: $uni-border-3, + border-4: $uni-border-4, + // 黑色 + black:$uni-black, + // 白色 + white:$uni-white, + // 透明 + transparent:$uni-transparent +) !default; +@each $key, $child in $uni-ui-color { + .uni-#{"" + $key} { + color: $child; + } + .uni-#{"" + $key}-bg { + background-color: $child; + } +} +.uni-shadow-sm { + box-shadow: $uni-shadow-sm; +} +.uni-shadow-base { + box-shadow: $uni-shadow-base; +} +.uni-shadow-lg { + box-shadow: $uni-shadow-lg; +} +.uni-mask { + background-color:$uni-mask; +} diff --git a/uni_modules/uni-scss/styles/setting/_radius.scss b/uni_modules/uni-scss/styles/setting/_radius.scss new file mode 100644 index 0000000..9a0428b --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_radius.scss @@ -0,0 +1,55 @@ +@mixin radius($r,$d:null ,$important: false){ + $radius-value:map-get($uni-radius, $r) if($important, !important, null); + // Key exists within the $uni-radius variable + @if (map-has-key($uni-radius, $r) and $d){ + @if $d == t { + border-top-left-radius:$radius-value; + border-top-right-radius:$radius-value; + }@else if $d == r { + border-top-right-radius:$radius-value; + border-bottom-right-radius:$radius-value; + }@else if $d == b { + border-bottom-left-radius:$radius-value; + border-bottom-right-radius:$radius-value; + }@else if $d == l { + border-top-left-radius:$radius-value; + border-bottom-left-radius:$radius-value; + }@else if $d == tl { + border-top-left-radius:$radius-value; + }@else if $d == tr { + border-top-right-radius:$radius-value; + }@else if $d == br { + border-bottom-right-radius:$radius-value; + }@else if $d == bl { + border-bottom-left-radius:$radius-value; + } + }@else{ + border-radius:$radius-value; + } +} + +@each $key, $child in $uni-radius { + @if($key){ + .uni-radius-#{"" + $key} { + @include radius($key) + } + }@else{ + .uni-radius { + @include radius($key) + } + } +} + +@each $direction in t, r, b, l,tl, tr, br, bl { + @each $key, $child in $uni-radius { + @if($key){ + .uni-radius-#{"" + $direction}-#{"" + $key} { + @include radius($key,$direction,false) + } + }@else{ + .uni-radius-#{$direction} { + @include radius($key,$direction,false) + } + } + } +} diff --git a/uni_modules/uni-scss/styles/setting/_space.scss b/uni_modules/uni-scss/styles/setting/_space.scss new file mode 100644 index 0000000..3c89528 --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_space.scss @@ -0,0 +1,56 @@ + +@mixin fn($space,$direction,$size,$n) { + @if $n { + #{$space}-#{$direction}: #{$size*$uni-space-root}px + } @else { + #{$space}-#{$direction}: #{-$size*$uni-space-root}px + } +} +@mixin get-styles($direction,$i,$space,$n){ + @if $direction == t { + @include fn($space, top,$i,$n); + } + @if $direction == r { + @include fn($space, right,$i,$n); + } + @if $direction == b { + @include fn($space, bottom,$i,$n); + } + @if $direction == l { + @include fn($space, left,$i,$n); + } + @if $direction == x { + @include fn($space, left,$i,$n); + @include fn($space, right,$i,$n); + } + @if $direction == y { + @include fn($space, top,$i,$n); + @include fn($space, bottom,$i,$n); + } + @if $direction == a { + @if $n { + #{$space}:#{$i*$uni-space-root}px; + } @else { + #{$space}:#{-$i*$uni-space-root}px; + } + } +} + +@each $orientation in m,p { + $space: margin; + @if $orientation == m { + $space: margin; + } @else { + $space: padding; + } + @for $i from 0 through 16 { + @each $direction in t, r, b, l, x, y, a { + .uni-#{$orientation}#{$direction}-#{$i} { + @include get-styles($direction,$i,$space,true); + } + .uni-#{$orientation}#{$direction}-n#{$i} { + @include get-styles($direction,$i,$space,false); + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-scss/styles/setting/_styles.scss b/uni_modules/uni-scss/styles/setting/_styles.scss new file mode 100644 index 0000000..689afec --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_styles.scss @@ -0,0 +1,167 @@ +/* #ifndef APP-NVUE */ + +$-color-white:#fff; +$-color-black:#000; +@mixin base-style($color) { + color: #fff; + background-color: $color; + border-color: mix($-color-black, $color, 8%); + &:not([hover-class]):active { + background: mix($-color-black, $color, 10%); + border-color: mix($-color-black, $color, 20%); + color: $-color-white; + outline: none; + } +} +@mixin is-color($color) { + @include base-style($color); + &[loading] { + @include base-style($color); + &::before { + margin-right:5px; + } + } + &[disabled] { + &, + &[loading], + &:not([hover-class]):active { + color: $-color-white; + border-color: mix(darken($color,10%), $-color-white); + background-color: mix($color, $-color-white); + } + } + +} +@mixin base-plain-style($color) { + color:$color; + background-color: mix($-color-white, $color, 90%); + border-color: mix($-color-white, $color, 70%); + &:not([hover-class]):active { + background: mix($-color-white, $color, 80%); + color: $color; + outline: none; + border-color: mix($-color-white, $color, 50%); + } +} +@mixin is-plain($color){ + &[plain] { + @include base-plain-style($color); + &[loading] { + @include base-plain-style($color); + &::before { + margin-right:5px; + } + } + &[disabled] { + &, + &:active { + color: mix($-color-white, $color, 40%); + background-color: mix($-color-white, $color, 90%); + border-color: mix($-color-white, $color, 80%); + } + } + } +} + + +.uni-btn { + margin: 5px; + color: #393939; + border:1px solid #ccc; + font-size: 16px; + font-weight: 200; + background-color: #F9F9F9; + // TODO 暂时处理边框隐藏一边的问题 + overflow: visible; + &::after{ + border: none; + } + + &:not([type]),&[type=default] { + color: #999; + &[loading] { + background: none; + &::before { + margin-right:5px; + } + } + + + + &[disabled]{ + color: mix($-color-white, #999, 60%); + &, + &[loading], + &:active { + color: mix($-color-white, #999, 60%); + background-color: mix($-color-white,$-color-black , 98%); + border-color: mix($-color-white, #999, 85%); + } + } + + &[plain] { + color: #999; + background: none; + border-color: $uni-border-1; + &:not([hover-class]):active { + background: none; + color: mix($-color-white, $-color-black, 80%); + border-color: mix($-color-white, $-color-black, 90%); + outline: none; + } + &[disabled]{ + &, + &[loading], + &:active { + background: none; + color: mix($-color-white, #999, 60%); + border-color: mix($-color-white, #999, 85%); + } + } + } + } + + &:not([hover-class]):active { + color: mix($-color-white, $-color-black, 50%); + } + + &[size=mini] { + font-size: 16px; + font-weight: 200; + border-radius: 8px; + } + + + + &.uni-btn-small { + font-size: 14px; + } + &.uni-btn-mini { + font-size: 12px; + } + + &.uni-btn-radius { + border-radius: 999px; + } + &[type=primary] { + @include is-color($uni-primary); + @include is-plain($uni-primary) + } + &[type=success] { + @include is-color($uni-success); + @include is-plain($uni-success) + } + &[type=error] { + @include is-color($uni-error); + @include is-plain($uni-error) + } + &[type=warning] { + @include is-color($uni-warning); + @include is-plain($uni-warning) + } + &[type=info] { + @include is-color($uni-info); + @include is-plain($uni-info) + } +} +/* #endif */ diff --git a/uni_modules/uni-scss/styles/setting/_text.scss b/uni_modules/uni-scss/styles/setting/_text.scss new file mode 100644 index 0000000..a34d08f --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_text.scss @@ -0,0 +1,24 @@ +@mixin get-styles($k,$c) { + @if $k == size or $k == weight{ + font-#{$k}:#{$c} + }@else{ + #{$k}:#{$c} + } +} + +@each $key, $child in $uni-headings { + /* #ifndef APP-NVUE */ + .uni-#{$key} { + @each $k, $c in $child { + @include get-styles($k,$c) + } + } + /* #endif */ + /* #ifdef APP-NVUE */ + .container .uni-#{$key} { + @each $k, $c in $child { + @include get-styles($k,$c) + } + } + /* #endif */ +} diff --git a/uni_modules/uni-scss/styles/setting/_variables.scss b/uni_modules/uni-scss/styles/setting/_variables.scss new file mode 100644 index 0000000..557d3d7 --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_variables.scss @@ -0,0 +1,146 @@ +// @use "sass:math"; +@import '../tools/functions.scss'; +// 间距基础倍数 +$uni-space-root: 2 !default; +// 边框半径默认值 +$uni-radius-root:5px !default; +$uni-radius: () !default; +// 边框半径断点 +$uni-radius: map-deep-merge( + ( + 0: 0, + // TODO 当前版本暂时不支持 sm 属性 + // 'sm': math.div($uni-radius-root, 2), + null: $uni-radius-root, + 'lg': $uni-radius-root * 2, + 'xl': $uni-radius-root * 6, + 'pill': 9999px, + 'circle': 50% + ), + $uni-radius +); +// 字体家族 +$body-font-family: 'Roboto', sans-serif !default; +// 文本 +$heading-font-family: $body-font-family !default; +$uni-headings: () !default; +$letterSpacing: -0.01562em; +$uni-headings: map-deep-merge( + ( + 'h1': ( + size: 32px, + weight: 300, + line-height: 50px, + // letter-spacing:-0.01562em + ), + 'h2': ( + size: 28px, + weight: 300, + line-height: 40px, + // letter-spacing: -0.00833em + ), + 'h3': ( + size: 24px, + weight: 400, + line-height: 32px, + // letter-spacing: normal + ), + 'h4': ( + size: 20px, + weight: 400, + line-height: 30px, + // letter-spacing: 0.00735em + ), + 'h5': ( + size: 16px, + weight: 400, + line-height: 24px, + // letter-spacing: normal + ), + 'h6': ( + size: 14px, + weight: 500, + line-height: 18px, + // letter-spacing: 0.0125em + ), + 'subtitle': ( + size: 12px, + weight: 400, + line-height: 20px, + // letter-spacing: 0.00937em + ), + 'body': ( + font-size: 14px, + font-weight: 400, + line-height: 22px, + // letter-spacing: 0.03125em + ), + 'caption': ( + 'size': 12px, + 'weight': 400, + 'line-height': 20px, + // 'letter-spacing': 0.03333em, + // 'text-transform': false + ) + ), + $uni-headings +); + + + +// 主色 +$uni-primary: #2979ff !default; +$uni-primary-disable:lighten($uni-primary,20%) !default; +$uni-primary-light: lighten($uni-primary,25%) !default; + +// 辅助色 +// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。 +$uni-success: #18bc37 !default; +$uni-success-disable:lighten($uni-success,20%) !default; +$uni-success-light: lighten($uni-success,25%) !default; + +$uni-warning: #f3a73f !default; +$uni-warning-disable:lighten($uni-warning,20%) !default; +$uni-warning-light: lighten($uni-warning,25%) !default; + +$uni-error: #e43d33 !default; +$uni-error-disable:lighten($uni-error,20%) !default; +$uni-error-light: lighten($uni-error,25%) !default; + +$uni-info: #8f939c !default; +$uni-info-disable:lighten($uni-info,20%) !default; +$uni-info-light: lighten($uni-info,25%) !default; + +// 中性色 +// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。 +$uni-main-color: #3a3a3a !default; // 主要文字 +$uni-base-color: #6a6a6a !default; // 常规文字 +$uni-secondary-color: #909399 !default; // 次要文字 +$uni-extra-color: #c7c7c7 !default; // 辅助说明 + +// 边框颜色 +$uni-border-1: #F0F0F0 !default; +$uni-border-2: #EDEDED !default; +$uni-border-3: #DCDCDC !default; +$uni-border-4: #B9B9B9 !default; + +// 常规色 +$uni-black: #000000 !default; +$uni-white: #ffffff !default; +$uni-transparent: rgba($color: #000000, $alpha: 0) !default; + +// 背景色 +$uni-bg-color: #f7f7f7 !default; + +/* 水平间距 */ +$uni-spacing-sm: 8px !default; +$uni-spacing-base: 15px !default; +$uni-spacing-lg: 30px !default; + +// 阴影 +$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5) !default; +$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default; +$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5) !default; + +// 蒙版 +$uni-mask: rgba($color: #000000, $alpha: 0.4) !default; diff --git a/uni_modules/uni-scss/styles/tools/functions.scss b/uni_modules/uni-scss/styles/tools/functions.scss new file mode 100644 index 0000000..ac6f63e --- /dev/null +++ b/uni_modules/uni-scss/styles/tools/functions.scss @@ -0,0 +1,19 @@ +// 合并 map +@function map-deep-merge($parent-map, $child-map){ + $result: $parent-map; + @each $key, $child in $child-map { + $parent-has-key: map-has-key($result, $key); + $parent-value: map-get($result, $key); + $parent-type: type-of($parent-value); + $child-type: type-of($child); + $parent-is-map: $parent-type == map; + $child-is-map: $child-type == map; + + @if (not $parent-has-key) or ($parent-type != $child-type) or (not ($parent-is-map and $child-is-map)){ + $result: map-merge($result, ( $key: $child )); + }@else { + $result: map-merge($result, ( $key: map-deep-merge($parent-value, $child) )); + } + } + @return $result; +}; diff --git a/uni_modules/uni-scss/theme.scss b/uni_modules/uni-scss/theme.scss new file mode 100644 index 0000000..80ee62f --- /dev/null +++ b/uni_modules/uni-scss/theme.scss @@ -0,0 +1,31 @@ +// 间距基础倍数 +$uni-space-root: 2; +// 边框半径默认值 +$uni-radius-root:5px; +// 主色 +$uni-primary: #2979ff; +// 辅助色 +$uni-success: #4cd964; +// 警告色 +$uni-warning: #f0ad4e; +// 错误色 +$uni-error: #dd524d; +// 描述色 +$uni-info: #909399; +// 中性色 +$uni-main-color: #303133; +$uni-base-color: #606266; +$uni-secondary-color: #909399; +$uni-extra-color: #C0C4CC; +// 背景色 +$uni-bg-color: #f5f5f5; +// 边框颜色 +$uni-border-1: #DCDFE6; +$uni-border-2: #E4E7ED; +$uni-border-3: #EBEEF5; +$uni-border-4: #F2F6FC; + +// 常规色 +$uni-black: #000000; +$uni-white: #ffffff; +$uni-transparent: rgba($color: #000000, $alpha: 0); diff --git a/uni_modules/uni-scss/variables.scss b/uni_modules/uni-scss/variables.scss new file mode 100644 index 0000000..1c062d4 --- /dev/null +++ b/uni_modules/uni-scss/variables.scss @@ -0,0 +1,62 @@ +@import './styles/setting/_variables.scss'; +// 间距基础倍数 +$uni-space-root: 2; +// 边框半径默认值 +$uni-radius-root:5px; + +// 主色 +$uni-primary: #2979ff; +$uni-primary-disable:mix(#fff,$uni-primary,50%); +$uni-primary-light: mix(#fff,$uni-primary,80%); + +// 辅助色 +// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。 +$uni-success: #18bc37; +$uni-success-disable:mix(#fff,$uni-success,50%); +$uni-success-light: mix(#fff,$uni-success,80%); + +$uni-warning: #f3a73f; +$uni-warning-disable:mix(#fff,$uni-warning,50%); +$uni-warning-light: mix(#fff,$uni-warning,80%); + +$uni-error: #e43d33; +$uni-error-disable:mix(#fff,$uni-error,50%); +$uni-error-light: mix(#fff,$uni-error,80%); + +$uni-info: #8f939c; +$uni-info-disable:mix(#fff,$uni-info,50%); +$uni-info-light: mix(#fff,$uni-info,80%); + +// 中性色 +// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。 +$uni-main-color: #3a3a3a; // 主要文字 +$uni-base-color: #6a6a6a; // 常规文字 +$uni-secondary-color: #909399; // 次要文字 +$uni-extra-color: #c7c7c7; // 辅助说明 + +// 边框颜色 +$uni-border-1: #F0F0F0; +$uni-border-2: #EDEDED; +$uni-border-3: #DCDCDC; +$uni-border-4: #B9B9B9; + +// 常规色 +$uni-black: #000000; +$uni-white: #ffffff; +$uni-transparent: rgba($color: #000000, $alpha: 0); + +// 背景色 +$uni-bg-color: #f7f7f7; + +/* 水平间距 */ +$uni-spacing-sm: 8px; +$uni-spacing-base: 15px; +$uni-spacing-lg: 30px; + +// 阴影 +$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5); +$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2); +$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5); + +// 蒙版 +$uni-mask: rgba($color: #000000, $alpha: 0.4); diff --git a/uni_modules/uni-search-bar/changelog.md b/uni_modules/uni-search-bar/changelog.md new file mode 100644 index 0000000..0cd8972 --- /dev/null +++ b/uni_modules/uni-search-bar/changelog.md @@ -0,0 +1,27 @@ +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-search-bar](https://uniapp.dcloud.io/component/uniui/uni-search-bar) +## 1.1.2(2021-08-30) +- 修复 value 属性与 modelValue 属性不兼容的Bug +## 1.1.1(2021-08-24) +- 新增 支持国际化 +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.9(2021-05-12) +- 新增 项目示例地址 +## 1.0.8(2021-04-21) +- 优化 添加依赖 uni-icons, 导入后自动下载依赖 +## 1.0.7(2021-04-15) +- uni-ui 新增 uni-search-bar 的 focus 事件 + +## 1.0.6(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 + +## 1.0.5(2021-02-05) +- 调整为uni_modules目录规范 +- 新增 支持双向绑定 +- 更改 input 事件的返回值,e={value:Number} --> e=value +- 新增 支持图标插槽 +- 新增 支持 clear、blur 事件 +- 新增 支持 focus 属性 +- 去掉组件背景色 diff --git a/uni_modules/uni-search-bar/components/uni-search-bar/i18n/en.json b/uni_modules/uni-search-bar/components/uni-search-bar/i18n/en.json new file mode 100644 index 0000000..dd083a5 --- /dev/null +++ b/uni_modules/uni-search-bar/components/uni-search-bar/i18n/en.json @@ -0,0 +1,4 @@ +{ + "uni-search-bar.cancel": "cancel", + "uni-search-bar.placeholder": "Search enter content" +} \ No newline at end of file diff --git a/uni_modules/uni-search-bar/components/uni-search-bar/i18n/index.js b/uni_modules/uni-search-bar/components/uni-search-bar/i18n/index.js new file mode 100644 index 0000000..de7509c --- /dev/null +++ b/uni_modules/uni-search-bar/components/uni-search-bar/i18n/index.js @@ -0,0 +1,8 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json b/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json new file mode 100644 index 0000000..d4e5c12 --- /dev/null +++ b/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json @@ -0,0 +1,4 @@ +{ + "uni-search-bar.cancel": "cancel", + "uni-search-bar.placeholder": "请输入搜索内容" +} diff --git a/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json b/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json new file mode 100644 index 0000000..318b6ef --- /dev/null +++ b/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json @@ -0,0 +1,4 @@ +{ + "uni-search-bar.cancel": "cancel", + "uni-search-bar.placeholder": "請輸入搜索內容" +} diff --git a/uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue b/uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue new file mode 100644 index 0000000..2bf4a74 --- /dev/null +++ b/uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue @@ -0,0 +1,287 @@ +s + + + + diff --git a/uni_modules/uni-search-bar/package.json b/uni_modules/uni-search-bar/package.json new file mode 100644 index 0000000..d76d8b3 --- /dev/null +++ b/uni_modules/uni-search-bar/package.json @@ -0,0 +1,89 @@ +{ + "id": "uni-search-bar", + "displayName": "uni-search-bar 搜索栏", + "version": "1.2.0", + "description": "搜索栏组件,通常用于搜索商品、文章等", + "keywords": [ + "uni-ui", + "uniui", + "搜索框", + "搜索栏" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-search-bar/readme.md b/uni_modules/uni-search-bar/readme.md new file mode 100644 index 0000000..253092f --- /dev/null +++ b/uni_modules/uni-search-bar/readme.md @@ -0,0 +1,14 @@ + + +## SearchBar 搜索栏 + +> **组件名:uni-search-bar** +> 代码块: `uSearchBar` + + +搜索栏组件 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-search-bar) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/uni_modules/uni-segmented-control/changelog.md b/uni_modules/uni-segmented-control/changelog.md new file mode 100644 index 0000000..a44385d --- /dev/null +++ b/uni_modules/uni-segmented-control/changelog.md @@ -0,0 +1,9 @@ +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-segmented-control](https://uniapp.dcloud.io/component/uniui/uni-segmented-control) +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.5(2021-05-12) +- 新增 项目示例地址 +## 1.0.4(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue b/uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue new file mode 100644 index 0000000..ddbcf88 --- /dev/null +++ b/uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue @@ -0,0 +1,145 @@ + + + + + diff --git a/uni_modules/uni-segmented-control/package.json b/uni_modules/uni-segmented-control/package.json new file mode 100644 index 0000000..6cae41d --- /dev/null +++ b/uni_modules/uni-segmented-control/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-segmented-control", + "displayName": "uni-segmented-control 分段器", + "version": "1.2.0", + "description": "分段器由至少 2 个分段控件组成,用作不同视图的显示", + "keywords": [ + "uni-ui", + "uniui", + "分段器", + "segement", + "顶部选择" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-segmented-control/readme.md b/uni_modules/uni-segmented-control/readme.md new file mode 100644 index 0000000..3527b03 --- /dev/null +++ b/uni_modules/uni-segmented-control/readme.md @@ -0,0 +1,13 @@ + + +## SegmentedControl 分段器 +> **组件名:uni-segmented-control** +> 代码块: `uSegmentedControl` + + +用作不同视图的显示 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-segmented-control) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/uni_modules/uni-steps/changelog.md b/uni_modules/uni-steps/changelog.md new file mode 100644 index 0000000..cb9d367 --- /dev/null +++ b/uni_modules/uni-steps/changelog.md @@ -0,0 +1,16 @@ +## 1.1.1(2021-11-22) +- 修复 vue3中某些scss变量无法找到的问题 +## 1.1.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-steps](https://uniapp.dcloud.io/component/uniui/uni-steps) +## 1.0.8(2021-05-12) +- 新增 项目示例地址 +## 1.0.7(2021-05-06) +- 修复 uni-steps 横向布局时,多行文字高度不合理的 bug +## 1.0.6(2021-04-21) +- 优化 添加依赖 uni-icons, 导入后自动下载依赖 +## 1.0.5(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 + +## 1.0.4(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-steps/components/uni-steps/uni-steps.vue b/uni_modules/uni-steps/components/uni-steps/uni-steps.vue new file mode 100644 index 0000000..a6c8f28 --- /dev/null +++ b/uni_modules/uni-steps/components/uni-steps/uni-steps.vue @@ -0,0 +1,269 @@ + + + + + diff --git a/uni_modules/uni-steps/package.json b/uni_modules/uni-steps/package.json new file mode 100644 index 0000000..c687b40 --- /dev/null +++ b/uni_modules/uni-steps/package.json @@ -0,0 +1,89 @@ +{ + "id": "uni-steps", + "displayName": "uni-steps 步骤条", + "version": "1.1.1", + "description": "步骤条组件,提供横向和纵向两种布局格式。", + "keywords": [ + "uni-ui", + "uniui", + "步骤条", + "时间轴" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-steps/readme.md b/uni_modules/uni-steps/readme.md new file mode 100644 index 0000000..da7a4bf --- /dev/null +++ b/uni_modules/uni-steps/readme.md @@ -0,0 +1,13 @@ + + +## Steps 步骤条 +> **组件名:uni-steps** +> 代码块: `uSteps` + + +步骤条,常用于显示进度 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-steps) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/uni_modules/uni-swipe-action/changelog.md b/uni_modules/uni-swipe-action/changelog.md new file mode 100644 index 0000000..0ab2085 --- /dev/null +++ b/uni_modules/uni-swipe-action/changelog.md @@ -0,0 +1,33 @@ +## 1.3.3(2022-03-31) +- 修复 按钮字体大小不能设置的bug +## 1.3.2(2022-03-16) +- 修复 h5和app端下报el错误的bug +## 1.3.1(2022-03-07) +- 修复 HBuilderX 1.4.X 版本中,h5和app端下报错的bug +## 1.3.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-swipe-action](https://uniapp.dcloud.io/component/uniui/uni-swipe-action) +## 1.2.4(2021-08-20) +- 优化 close-all 方法 +## 1.2.3(2021-08-20) +- 新增 close-all 方法,关闭所有已打开的组件 +## 1.2.2(2021-08-17) +- 新增 resize() 方法,在非微信小程序、h5、app-vue端出现不能滑动的问题的时候,重置组件 +- 修复 app 端偶尔出现类似 Page[x][-x,xx;-x,xx,x,x-x] 的问题 +- 优化 微信小程序、h5、app-vue 滑动逻辑,避免出现动态新增组件后不能滑动的问题 +## 1.2.1(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +- 修复 跨页面修改组件数据 ,导致不能滑动的问题 +## 1.1.10(2021-06-17) +- 修复 按钮点击执行两次的bug +## 1.1.9(2021-05-12) +- 新增 项目示例地址 +## 1.1.8(2021-03-26) +- 修复 微信小程序 nv_navigator is not defined 报错的bug +## 1.1.7(2021-02-05) +- 调整为uni_modules目录规范 +- 新增 左侧滑动 +- 新增 插槽使用方式 +- 新增 threshold 属性,可以控制滑动缺省值 +- 优化 长列表滚动性能 +- 修复 滚动页面时触发组件滑动的Bug diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js new file mode 100644 index 0000000..5b15f7f --- /dev/null +++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js @@ -0,0 +1,300 @@ +let bindIngXMixins = {} + +// #ifdef APP-NVUE +const BindingX = uni.requireNativePlugin('bindingx'); +const dom = uni.requireNativePlugin('dom'); +const animation = uni.requireNativePlugin('animation'); + +bindIngXMixins = { + data() { + return {} + }, + + watch: { + show(newVal) { + if (this.autoClose) return + if (this.stop) return + this.stop = true + if (newVal) { + this.open(newVal) + } else { + this.close() + } + }, + leftOptions() { + this.getSelectorQuery() + this.init() + }, + rightOptions(newVal) { + this.init() + } + }, + created() { + this.swipeaction = this.getSwipeAction() + if (this.swipeaction.children !== undefined) { + this.swipeaction.children.push(this) + } + }, + mounted() { + this.box = this.getEl(this.$refs['selector-box--hock']) + this.selector = this.getEl(this.$refs['selector-content--hock']); + this.leftButton = this.getEl(this.$refs['selector-left-button--hock']); + this.rightButton = this.getEl(this.$refs['selector-right-button--hock']); + this.init() + }, + // beforeDestroy() { + // this.swipeaction.children.forEach((item, index) => { + // if (item === this) { + // this.swipeaction.children.splice(index, 1) + // } + // }) + // }, + methods: { + init() { + this.$nextTick(() => { + this.x = 0 + this.button = { + show: false + } + setTimeout(() => { + this.getSelectorQuery() + }, 200) + }) + }, + onClick(index, item, position) { + this.$emit('click', { + content: item, + index, + position + }) + }, + touchstart(e) { + // 每次只触发一次,避免多次监听造成闪烁 + if (this.stop) return + this.stop = true + if (this.autoClose) { + this.swipeaction.closeOther(this) + } + + const leftWidth = this.button.left.width + const rightWidth = this.button.right.width + let expression = this.range(this.x, -rightWidth, leftWidth) + let leftExpression = this.range(this.x - leftWidth, -leftWidth, 0) + let rightExpression = this.range(this.x + rightWidth, 0, rightWidth) + + this.eventpan = BindingX.bind({ + anchor: this.box, + eventType: 'pan', + props: [{ + element: this.selector, + property: 'transform.translateX', + expression + }, { + element: this.leftButton, + property: 'transform.translateX', + expression: leftExpression + }, { + element: this.rightButton, + property: 'transform.translateX', + expression: rightExpression + }, ] + }, (e) => { + // nope + if (e.state === 'end') { + this.x = e.deltaX + this.x; + this.isclick = true + this.bindTiming(e.deltaX) + } + }); + }, + touchend(e) { + if (this.isopen !== 'none' && !this.isclick) { + this.open('none') + } + }, + bindTiming(x) { + const left = this.x + const leftWidth = this.button.left.width + const rightWidth = this.button.right.width + const threshold = this.threshold + if (!this.isopen || this.isopen === 'none') { + if (left > threshold) { + this.open('left') + } else if (left < -threshold) { + this.open('right') + } else { + this.open('none') + } + } else { + if ((x > -leftWidth && x < 0) || x > rightWidth) { + if ((x > -threshold && x < 0) || (x - rightWidth > threshold)) { + this.open('left') + } else { + this.open('none') + } + } else { + if ((x < threshold && x > 0) || (x + leftWidth < -threshold)) { + this.open('right') + } else { + this.open('none') + } + } + } + }, + + /** + * 移动范围 + * @param {Object} num + * @param {Object} mix + * @param {Object} max + */ + range(num, mix, max) { + return `min(max(x+${num}, ${mix}), ${max})` + }, + + /** + * 开启swipe + */ + open(type) { + this.animation(type) + }, + + /** + * 关闭swipe + */ + close() { + this.animation('none') + }, + + /** + * 开启关闭动画 + * @param {Object} type + */ + animation(type) { + const time = 300 + const leftWidth = this.button.left.width + const rightWidth = this.button.right.width + if (this.eventpan && this.eventpan.token) { + BindingX.unbind({ + token: this.eventpan.token, + eventType: 'pan' + }) + } + + switch (type) { + case 'left': + Promise.all([ + this.move(this.selector, leftWidth), + this.move(this.leftButton, 0), + this.move(this.rightButton, rightWidth * 2) + ]).then(() => { + this.setEmit(leftWidth, type) + }) + break + case 'right': + Promise.all([ + this.move(this.selector, -rightWidth), + this.move(this.leftButton, -leftWidth * 2), + this.move(this.rightButton, 0) + ]).then(() => { + this.setEmit(-rightWidth, type) + }) + break + default: + Promise.all([ + this.move(this.selector, 0), + this.move(this.leftButton, -leftWidth), + this.move(this.rightButton, rightWidth) + ]).then(() => { + this.setEmit(0, type) + }) + + } + }, + setEmit(x, type) { + const leftWidth = this.button.left.width + const rightWidth = this.button.right.width + this.isopen = this.isopen || 'none' + this.stop = false + this.isclick = false + // 只有状态不一致才会返回结果 + if (this.isopen !== type && this.x !== x) { + if (type === 'left' && leftWidth > 0) { + this.$emit('change', 'left') + } + if (type === 'right' && rightWidth > 0) { + this.$emit('change', 'right') + } + if (type === 'none') { + this.$emit('change', 'none') + } + } + this.x = x + this.isopen = type + }, + move(ref, value) { + return new Promise((resolve, reject) => { + animation.transition(ref, { + styles: { + transform: `translateX(${value})`, + }, + duration: 150, //ms + timingFunction: 'linear', + needLayout: false, + delay: 0 //ms + }, function(res) { + resolve(res) + }) + }) + + }, + + /** + * 获取ref + * @param {Object} el + */ + getEl(el) { + return el.ref + }, + /** + * 获取节点信息 + */ + getSelectorQuery() { + Promise.all([ + this.getDom('left'), + this.getDom('right'), + ]).then((data) => { + let show = 'none' + if (this.autoClose) { + show = 'none' + } else { + show = this.show + } + + if (show === 'none') { + // this.close() + } else { + this.open(show) + } + + }) + + }, + getDom(str) { + return new Promise((resolve, reject) => { + dom.getComponentRect(this.$refs[`selector-${str}-button--hock`], (data) => { + if (data) { + this.button[str] = data.size + resolve(data) + } else { + reject() + } + }) + }) + } + } +} + +// #endif + +export default bindIngXMixins diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js new file mode 100644 index 0000000..9a10ece --- /dev/null +++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js @@ -0,0 +1,12 @@ +export function isPC() { + var userAgentInfo = navigator.userAgent; + var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"]; + var flag = true; + for (let v = 0; v < Agents.length - 1; v++) { + if (userAgentInfo.indexOf(Agents[v]) > 0) { + flag = false; + break; + } + } + return flag; +} \ No newline at end of file diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js new file mode 100644 index 0000000..1a68ef8 --- /dev/null +++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js @@ -0,0 +1,193 @@ +export default { + data() { + return { + x: 0, + transition: false, + width: 0, + viewWidth: 0, + swipeShow: 0 + } + }, + watch: { + show(newVal) { + if (this.autoClose) return + if (newVal && newVal !== 'none' ) { + this.transition = true + this.open(newVal) + } else { + this.close() + } + } + }, + created() { + this.swipeaction = this.getSwipeAction() + if (this.swipeaction.children !== undefined) { + this.swipeaction.children.push(this) + } + }, + mounted() { + this.isopen = false + setTimeout(() => { + this.getQuerySelect() + }, 50) + }, + methods: { + appTouchStart(e) { + const { + clientX + } = e.changedTouches[0] + this.clientX = clientX + this.timestamp = new Date().getTime() + }, + appTouchEnd(e, index, item, position) { + const { + clientX + } = e.changedTouches[0] + // fixed by xxxx 模拟点击事件,解决 ios 13 点击区域错位的问题 + let diff = Math.abs(this.clientX - clientX) + let time = (new Date().getTime()) - this.timestamp + if (diff < 40 && time < 300) { + this.$emit('click', { + content: item, + index, + position + }) + } + }, + /** + * 移动触发 + * @param {Object} e + */ + onChange(e) { + this.moveX = e.detail.x + this.isclose = false + }, + touchstart(e) { + this.transition = false + this.isclose = true + this.autoClose && this.swipeaction.closeOther(this) + }, + touchmove(e) {}, + touchend(e) { + // 0的位置什么都不执行 + if (this.isclose && this.isopen === 'none') return + if (this.isclose && this.isopen !== 'none') { + this.transition = true + this.close() + } else { + this.move(this.moveX + this.leftWidth) + } + }, + + /** + * 移动 + * @param {Object} moveX + */ + move(moveX) { + // 打开关闭的处理逻辑不太一样 + this.transition = true + // 未打开状态 + if (!this.isopen || this.isopen === 'none') { + if (moveX > this.threshold) { + this.open('left') + } else if (moveX < -this.threshold) { + this.open('right') + } else { + this.close() + } + } else { + if (moveX < 0 && moveX < this.rightWidth) { + const rightX = this.rightWidth + moveX + if (rightX < this.threshold) { + this.open('right') + } else { + this.close() + } + } else if (moveX > 0 && moveX < this.leftWidth) { + const leftX = this.leftWidth - moveX + if (leftX < this.threshold) { + this.open('left') + } else { + this.close() + } + } + + } + + }, + + /** + * 打开 + */ + open(type) { + this.x = this.moveX + this.animation(type) + }, + + /** + * 关闭 + */ + close() { + this.x = this.moveX + // TODO 解决 x 值不更新的问题,所以会多触发一次 nextTick ,待优化 + this.$nextTick(() => { + this.x = -this.leftWidth + if(this.isopen!=='none'){ + this.$emit('change', 'none') + } + this.isopen = 'none' + }) + }, + + /** + * 执行结束动画 + * @param {Object} type + */ + animation(type) { + this.$nextTick(() => { + if (type === 'left') { + this.x = 0 + } else { + this.x = -this.rightWidth - this.leftWidth + } + + if(this.isopen!==type){ + this.$emit('change', type) + } + this.isopen = type + }) + + }, + getSlide(x) {}, + getQuerySelect() { + const query = uni.createSelectorQuery().in(this); + query.selectAll('.movable-view--hock').boundingClientRect(data => { + this.leftWidth = data[1].width + this.rightWidth = data[2].width + this.width = data[0].width + this.viewWidth = this.width + this.rightWidth + this.leftWidth + if (this.leftWidth === 0) { + // TODO 疑似bug ,初始化的时候如果x 是0,会导致移动位置错误,所以让元素超出一点 + this.x = -0.1 + } else { + this.x = -this.leftWidth + } + this.moveX = this.x + this.$nextTick(() => { + this.swipeShow = 1 + }) + + if (!this.buttonWidth) { + this.disabledView = true + } + + if (this.autoClose) return + if (this.show !== 'none') { + this.transition = true + this.open(this.shows) + } + }).exec(); + + } + } +} diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js new file mode 100644 index 0000000..c44adfd --- /dev/null +++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js @@ -0,0 +1,257 @@ +let otherMixins = {} + +// #ifndef APP-PLUS|| MP-WEIXIN || H5 +const MIN_DISTANCE = 10; +otherMixins = { + data() { + // TODO 随机生生元素ID,解决百度小程序获取同一个元素位置信息的bug + const elClass = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}` + return { + uniShow: false, + left: 0, + buttonShow: 'none', + ani: false, + moveLeft:'', + elClass + } + }, + watch: { + show(newVal) { + if (this.autoClose) return + this.openState(newVal) + }, + left(){ + this.moveLeft = `translateX(${this.left}px)` + }, + buttonShow(newVal){ + if (this.autoClose) return + this.openState(newVal) + }, + leftOptions() { + this.init() + }, + rightOptions() { + this.init() + } + }, + mounted() { + this.swipeaction = this.getSwipeAction() + if (this.swipeaction.children !== undefined) { + this.swipeaction.children.push(this) + } + this.init() + }, + methods: { + init(){ + clearTimeout(this.timer) + this.timer = setTimeout(() => { + this.getSelectorQuery() + }, 100) + // 移动距离 + this.left = 0 + this.x = 0 + }, + + closeSwipe(e) { + if (!this.autoClose) return + this.swipeaction.closeOther(this) + }, + appTouchStart(e) { + const { + clientX + } = e.changedTouches[0] + this.clientX = clientX + this.timestamp = new Date().getTime() + }, + appTouchEnd(e, index, item, position) { + const { + clientX + } = e.changedTouches[0] + // fixed by xxxx 模拟点击事件,解决 ios 13 点击区域错位的问题 + let diff = Math.abs(this.clientX - clientX) + let time = (new Date().getTime()) - this.timestamp + if (diff < 40 && time < 300) { + this.$emit('click', { + content: item, + index, + position + }) + } + }, + touchstart(e) { + if (this.disabled) return + this.ani = false + this.x = this.left || 0 + this.stopTouchStart(e) + this.autoClose && this.closeSwipe() + }, + touchmove(e) { + if (this.disabled) return + // 是否可以滑动页面 + this.stopTouchMove(e); + if (this.direction !== 'horizontal') { + return; + } + this.move(this.x + this.deltaX) + return false + }, + touchend() { + if (this.disabled) return + this.moveDirection(this.left) + }, + /** + * 设置移动距离 + * @param {Object} value + */ + move(value) { + value = value || 0 + const leftWidth = this.leftWidth + const rightWidth = this.rightWidth + // 获取可滑动范围 + this.left = this.range(value, -rightWidth, leftWidth); + }, + + /** + * 获取范围 + * @param {Object} num + * @param {Object} min + * @param {Object} max + */ + range(num, min, max) { + return Math.min(Math.max(num, min), max); + }, + /** + * 移动方向判断 + * @param {Object} left + * @param {Object} value + */ + moveDirection(left) { + const threshold = this.threshold + const isopen = this.isopen || 'none' + const leftWidth = this.leftWidth + const rightWidth = this.rightWidth + if (this.deltaX === 0) { + this.openState('none') + return + } + if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth > 0 && rightWidth + + left < threshold)) { + // right + this.openState('right') + } else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth > 0 && + leftWidth - left < threshold)) { + // left + this.openState('left') + } else { + // default + this.openState('none') + } + }, + + /** + * 开启状态 + * @param {Boolean} type + */ + openState(type) { + const leftWidth = this.leftWidth + const rightWidth = this.rightWidth + let left = '' + this.isopen = this.isopen ? this.isopen : 'none' + switch (type) { + case "left": + left = leftWidth + break + case "right": + left = -rightWidth + break + default: + left = 0 + } + + + if (this.isopen !== type) { + this.throttle = true + this.$emit('change', type) + } + + this.isopen = type + // 添加动画类 + this.ani = true + this.$nextTick(() => { + this.move(left) + }) + // 设置最终移动位置,理论上只要进入到这个函数,肯定是要打开的 + }, + close() { + this.openState('none') + }, + getDirection(x, y) { + if (x > y && x > MIN_DISTANCE) { + return 'horizontal'; + } + if (y > x && y > MIN_DISTANCE) { + return 'vertical'; + } + return ''; + }, + + /** + * 重置滑动状态 + * @param {Object} event + */ + resetTouchStatus() { + this.direction = ''; + this.deltaX = 0; + this.deltaY = 0; + this.offsetX = 0; + this.offsetY = 0; + }, + + /** + * 设置滑动开始位置 + * @param {Object} event + */ + stopTouchStart(event) { + this.resetTouchStatus(); + const touch = event.touches[0]; + this.startX = touch.clientX; + this.startY = touch.clientY; + }, + + /** + * 滑动中,是否禁止打开 + * @param {Object} event + */ + stopTouchMove(event) { + const touch = event.touches[0]; + this.deltaX = touch.clientX - this.startX; + this.deltaY = touch.clientY - this.startY; + this.offsetX = Math.abs(this.deltaX); + this.offsetY = Math.abs(this.deltaY); + this.direction = this.direction || this.getDirection(this.offsetX, this.offsetY); + }, + + getSelectorQuery() { + const views = uni.createSelectorQuery().in(this) + views + .selectAll('.'+this.elClass) + .boundingClientRect(data => { + if(data.length === 0) return + let show = 'none' + if (this.autoClose) { + show = 'none' + } else { + show = this.show + } + this.leftWidth = data[0].width || 0 + this.rightWidth = data[1].width || 0 + this.buttonShow = show + }) + .exec() + } + } +} + +// #endif + +export default otherMixins diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js new file mode 100644 index 0000000..e5e30bb --- /dev/null +++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js @@ -0,0 +1,82 @@ +let mpMixins = {} +// #ifdef APP-VUE|| MP-WEIXIN || H5 +import { + isPC +} from "./isPC" +mpMixins = { + data() { + return { + is_show: 'none' + } + }, + watch: { + show(newVal) { + this.is_show = this.show + } + }, + created() { + this.swipeaction = this.getSwipeAction() + if (this.swipeaction.children !== undefined) { + this.swipeaction.children.push(this) + } + }, + mounted() { + this.is_show = this.show + }, + methods: { + // wxs 中调用 + closeSwipe(e) { + if (!this.autoClose) return + this.swipeaction.closeOther(this) + }, + + change(e) { + this.$emit('change', e.open) + if (this.is_show !== e.open) { + this.is_show = e.open + } + }, + + appTouchStart(e) { + // #ifdef H5 + if (isPC()) return + // #endif + const { + clientX + } = e.changedTouches[0] + this.clientX = clientX + this.timestamp = new Date().getTime() + }, + appTouchEnd(e, index, item, position) { + // #ifdef H5 + if (isPC()) return + // #endif + const { + clientX + } = e.changedTouches[0] + // fixed by xxxx 模拟点击事件,解决 ios 13 点击区域错位的问题 + let diff = Math.abs(this.clientX - clientX) + let time = (new Date().getTime()) - this.timestamp + if (diff < 40 && time < 300) { + this.$emit('click', { + content: item, + index, + position + }) + } + }, + onClickForPC(index, item, position) { + // #ifdef H5 + if (!isPC()) return + this.$emit('click', { + content: item, + index, + position + }) + // #endif + } + } +} + +// #endif +export default mpMixins diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js new file mode 100644 index 0000000..ed42f1b --- /dev/null +++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js @@ -0,0 +1,270 @@ +const MIN_DISTANCE = 10; +export default { + showWatch(newVal, oldVal, ownerInstance, instance,self) { + var state = self.state + var $el = ownerInstance.$el || ownerInstance.$vm && ownerInstance.$vm.$el + if(!$el) return + this.getDom(instance, ownerInstance,self) + if (newVal && newVal !== 'none') { + this.openState(newVal, instance, ownerInstance,self) + return + } + + if (state.left) { + this.openState('none', instance, ownerInstance,self) + } + this.resetTouchStatus(instance,self) + }, + + /** + * 开始触摸操作 + * @param {Object} e + * @param {Object} ins + */ + touchstart(e, ownerInstance, self) { + let instance = e.instance; + let disabled = instance.getDataset().disabled + let state = self.state; + this.getDom(instance, ownerInstance, self) + // fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复 + disabled = this.getDisabledType(disabled) + if (disabled) return + // 开始触摸时移除动画类 + instance.requestAnimationFrame(function() { + instance.removeClass('ani'); + ownerInstance.callMethod('closeSwipe'); + }) + + // 记录上次的位置 + state.x = state.left || 0 + // 计算滑动开始位置 + this.stopTouchStart(e, ownerInstance, self) + }, + + /** + * 开始滑动操作 + * @param {Object} e + * @param {Object} ownerInstance + */ + touchmove(e, ownerInstance, self) { + let instance = e.instance; + // 删除之后已经那不到实例了 + if(!instance) return; + let disabled = instance.getDataset().disabled + let state = self.state + // fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复 + disabled = this.getDisabledType(disabled) + if (disabled) return + // 是否可以滑动页面 + this.stopTouchMove(e, self); + if (state.direction !== 'horizontal') { + return; + } + if (e.preventDefault) { + // 阻止页面滚动 + e.preventDefault() + } + let x = state.x + state.deltaX + this.move(x, instance, ownerInstance, self) + }, + + /** + * 结束触摸操作 + * @param {Object} e + * @param {Object} ownerInstance + */ + touchend(e, ownerInstance, self) { + let instance = e.instance; + let disabled = instance.getDataset().disabled + let state = self.state + // fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复 + disabled = this.getDisabledType(disabled) + + if (disabled) return + // 滑动过程中触摸结束,通过阙值判断是开启还是关闭 + // fixed by mehaotian 定时器解决点击按钮,touchend 触发比 click 事件时机早的问题 ,主要是 ios13 + this.moveDirection(state.left, instance, ownerInstance, self) + + }, + + /** + * 设置移动距离 + * @param {Object} value + * @param {Object} instance + * @param {Object} ownerInstance + */ + move(value, instance, ownerInstance, self) { + value = value || 0 + let state = self.state + let leftWidth = state.leftWidth + let rightWidth = state.rightWidth + // 获取可滑动范围 + state.left = this.range(value, -rightWidth, leftWidth); + instance.requestAnimationFrame(function() { + instance.setStyle({ + transform: 'translateX(' + state.left + 'px)', + '-webkit-transform': 'translateX(' + state.left + 'px)' + }) + }) + + }, + + /** + * 获取元素信息 + * @param {Object} instance + * @param {Object} ownerInstance + */ + getDom(instance, ownerInstance, self) { + var state = self.state + var $el = ownerInstance.$el || ownerInstance.$vm && ownerInstance.$vm.$el + var leftDom = $el.querySelector('.button-group--left') + var rightDom = $el.querySelector('.button-group--right') + + state.leftWidth = leftDom.offsetWidth || 0 + state.rightWidth = rightDom.offsetWidth || 0 + state.threshold = instance.getDataset().threshold + }, + + getDisabledType(value) { + return (typeof(value) === 'string' ? JSON.parse(value) : value) || false; + }, + + /** + * 获取范围 + * @param {Object} num + * @param {Object} min + * @param {Object} max + */ + range(num, min, max) { + return Math.min(Math.max(num, min), max); + }, + + + /** + * 移动方向判断 + * @param {Object} left + * @param {Object} value + * @param {Object} ownerInstance + * @param {Object} ins + */ + moveDirection(left, ins, ownerInstance, self) { + var state = self.state + var threshold = state.threshold + var position = state.position + var isopen = state.isopen || 'none' + var leftWidth = state.leftWidth + var rightWidth = state.rightWidth + if (state.deltaX === 0) { + this.openState('none', ins, ownerInstance, self) + return + } + if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth > 0 && + rightWidth + + left < threshold)) { + // right + this.openState('right', ins, ownerInstance, self) + } else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth > 0 && + leftWidth - left < threshold)) { + // left + this.openState('left', ins, ownerInstance, self) + } else { + // default + this.openState('none', ins, ownerInstance, self) + } + }, + + + /** + * 开启状态 + * @param {Boolean} type + * @param {Object} ins + * @param {Object} ownerInstance + */ + openState(type, ins, ownerInstance, self) { + let state = self.state + let leftWidth = state.leftWidth + let rightWidth = state.rightWidth + let left = '' + state.isopen = state.isopen ? state.isopen : 'none' + switch (type) { + case "left": + left = leftWidth + break + case "right": + left = -rightWidth + break + default: + left = 0 + } + + // && !state.throttle + + if (state.isopen !== type) { + state.throttle = true + ownerInstance.callMethod('change', { + open: type + }) + + } + + state.isopen = type + // 添加动画类 + ins.requestAnimationFrame(()=> { + ins.addClass('ani'); + this.move(left, ins, ownerInstance, self) + }) + }, + + + getDirection(x, y) { + if (x > y && x > MIN_DISTANCE) { + return 'horizontal'; + } + if (y > x && y > MIN_DISTANCE) { + return 'vertical'; + } + return ''; + }, + + /** + * 重置滑动状态 + * @param {Object} event + */ + resetTouchStatus(instance, self) { + let state = self.state; + state.direction = ''; + state.deltaX = 0; + state.deltaY = 0; + state.offsetX = 0; + state.offsetY = 0; + }, + + /** + * 设置滑动开始位置 + * @param {Object} event + */ + stopTouchStart(event, ownerInstance, self) { + let instance = event.instance; + let state = self.state + this.resetTouchStatus(instance, self); + var touch = event.touches[0]; + state.startX = touch.clientX; + state.startY = touch.clientY; + }, + + /** + * 滑动中,是否禁止打开 + * @param {Object} event + */ + stopTouchMove(event, self) { + let instance = event.instance; + let state = self.state; + let touch = event.touches[0]; + + state.deltaX = touch.clientX - state.startX; + state.deltaY = touch.clientY - state.startY; + state.offsetY = Math.abs(state.deltaY); + state.offsetX = Math.abs(state.deltaX); + state.direction = state.direction || this.getDirection(state.offsetX, state.offsetY); + } +} diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue new file mode 100644 index 0000000..f633c9c --- /dev/null +++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue @@ -0,0 +1,344 @@ + + + + + + diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs new file mode 100644 index 0000000..b394244 --- /dev/null +++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs @@ -0,0 +1,341 @@ +var MIN_DISTANCE = 10; + +/** + * 判断当前是否为H5、app-vue + */ +var IS_HTML5 = false +if (typeof window === 'object') IS_HTML5 = true + +/** + * 监听页面内值的变化,主要用于动态开关swipe-action + * @param {Object} newValue + * @param {Object} oldValue + * @param {Object} ownerInstance + * @param {Object} instance + */ +function showWatch(newVal, oldVal, ownerInstance, instance) { + var state = instance.getState() + getDom(instance, ownerInstance) + if (newVal && newVal !== 'none') { + openState(newVal, instance, ownerInstance) + return + } + + if (state.left) { + openState('none', instance, ownerInstance) + } + resetTouchStatus(instance) +} + +/** + * 开始触摸操作 + * @param {Object} e + * @param {Object} ins + */ +function touchstart(e, ownerInstance) { + var instance = e.instance; + var disabled = instance.getDataset().disabled + var state = instance.getState(); + getDom(instance, ownerInstance) + // fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复 + disabled = (typeof(disabled) === 'string' ? JSON.parse(disabled) : disabled) || false; + if (disabled) return + // 开始触摸时移除动画类 + instance.requestAnimationFrame(function() { + instance.removeClass('ani'); + ownerInstance.callMethod('closeSwipe'); + }) + + // 记录上次的位置 + state.x = state.left || 0 + // 计算滑动开始位置 + stopTouchStart(e, ownerInstance) +} + +/** + * 开始滑动操作 + * @param {Object} e + * @param {Object} ownerInstance + */ +function touchmove(e, ownerInstance) { + var instance = e.instance; + var disabled = instance.getDataset().disabled + var state = instance.getState() + // fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复 + disabled = (typeof(disabled) === 'string' ? JSON.parse(disabled) : disabled) || false; + if (disabled) return + // 是否可以滑动页面 + stopTouchMove(e); + if (state.direction !== 'horizontal') { + return; + } + + if (e.preventDefault) { + // 阻止页面滚动 + e.preventDefault() + } + + move(state.x + state.deltaX, instance, ownerInstance) +} + +/** + * 结束触摸操作 + * @param {Object} e + * @param {Object} ownerInstance + */ +function touchend(e, ownerInstance) { + var instance = e.instance; + var disabled = instance.getDataset().disabled + var state = instance.getState() + // fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复 + disabled = (typeof(disabled) === 'string' ? JSON.parse(disabled) : disabled) || false; + + if (disabled) return + // 滑动过程中触摸结束,通过阙值判断是开启还是关闭 + // fixed by mehaotian 定时器解决点击按钮,touchend 触发比 click 事件时机早的问题 ,主要是 ios13 + moveDirection(state.left, instance, ownerInstance) + +} + +/** + * 设置移动距离 + * @param {Object} value + * @param {Object} instance + * @param {Object} ownerInstance + */ +function move(value, instance, ownerInstance) { + value = value || 0 + var state = instance.getState() + var leftWidth = state.leftWidth + var rightWidth = state.rightWidth + // 获取可滑动范围 + state.left = range(value, -rightWidth, leftWidth); + instance.requestAnimationFrame(function() { + instance.setStyle({ + transform: 'translateX(' + state.left + 'px)', + '-webkit-transform': 'translateX(' + state.left + 'px)' + }) + }) + +} + +/** + * 获取元素信息 + * @param {Object} instance + * @param {Object} ownerInstance + */ +function getDom(instance, ownerInstance) { + var state = instance.getState() + var leftDom = ownerInstance.selectComponent('.button-group--left') + var rightDom = ownerInstance.selectComponent('.button-group--right') + var leftStyles = { + width: 0 + } + var rightStyles = { + width: 0 + } + leftStyles = leftDom.getBoundingClientRect() + rightStyles = rightDom.getBoundingClientRect() + + state.leftWidth = leftStyles.width || 0 + state.rightWidth = rightStyles.width || 0 + state.threshold = instance.getDataset().threshold +} + +/** + * 获取范围 + * @param {Object} num + * @param {Object} min + * @param {Object} max + */ +function range(num, min, max) { + return Math.min(Math.max(num, min), max); +} + + +/** + * 移动方向判断 + * @param {Object} left + * @param {Object} value + * @param {Object} ownerInstance + * @param {Object} ins + */ +function moveDirection(left, ins, ownerInstance) { + var state = ins.getState() + var threshold = state.threshold + var position = state.position + var isopen = state.isopen || 'none' + var leftWidth = state.leftWidth + var rightWidth = state.rightWidth + if (state.deltaX === 0) { + openState('none', ins, ownerInstance) + return + } + if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth > 0 && + rightWidth + + left < threshold)) { + // right + openState('right', ins, ownerInstance) + } else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth > 0 && + leftWidth - left < threshold)) { + // left + openState('left', ins, ownerInstance) + } else { + // default + openState('none', ins, ownerInstance) + } +} + + +/** + * 开启状态 + * @param {Boolean} type + * @param {Object} ins + * @param {Object} ownerInstance + */ +function openState(type, ins, ownerInstance) { + var state = ins.getState() + var leftWidth = state.leftWidth + var rightWidth = state.rightWidth + var left = '' + state.isopen = state.isopen ? state.isopen : 'none' + switch (type) { + case "left": + left = leftWidth + break + case "right": + left = -rightWidth + break + default: + left = 0 + } + + // && !state.throttle + + if (state.isopen !== type) { + state.throttle = true + ownerInstance.callMethod('change', { + open: type + }) + + } + + state.isopen = type + // 添加动画类 + ins.requestAnimationFrame(function() { + ins.addClass('ani'); + move(left, ins, ownerInstance) + }) + // 设置最终移动位置,理论上只要进入到这个函数,肯定是要打开的 +} + + +function getDirection(x, y) { + if (x > y && x > MIN_DISTANCE) { + return 'horizontal'; + } + if (y > x && y > MIN_DISTANCE) { + return 'vertical'; + } + return ''; +} + +/** + * 重置滑动状态 + * @param {Object} event + */ +function resetTouchStatus(instance) { + var state = instance.getState(); + state.direction = ''; + state.deltaX = 0; + state.deltaY = 0; + state.offsetX = 0; + state.offsetY = 0; +} + +/** + * 设置滑动开始位置 + * @param {Object} event + */ +function stopTouchStart(event) { + var instance = event.instance; + var state = instance.getState(); + resetTouchStatus(instance); + var touch = event.touches[0]; + if (IS_HTML5 && isPC()) { + touch = event; + } + state.startX = touch.clientX; + state.startY = touch.clientY; +} + +/** + * 滑动中,是否禁止打开 + * @param {Object} event + */ +function stopTouchMove(event) { + var instance = event.instance; + var state = instance.getState(); + var touch = event.touches[0]; + if (IS_HTML5 && isPC()) { + touch = event; + } + state.deltaX = touch.clientX - state.startX; + state.deltaY = touch.clientY - state.startY; + state.offsetY = Math.abs(state.deltaY); + state.offsetX = Math.abs(state.deltaX); + state.direction = state.direction || getDirection(state.offsetX, state.offsetY); +} + +function isPC() { + var userAgentInfo = navigator.userAgent; + var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"]; + var flag = true; + for (var v = 0; v < Agents.length - 1; v++) { + if (userAgentInfo.indexOf(Agents[v]) > 0) { + flag = false; + break; + } + } + return flag; +} + +var movable = false + +function mousedown(e, ins) { + if (!IS_HTML5) return + if (!isPC()) return + touchstart(e, ins) + movable = true +} + +function mousemove(e, ins) { + if (!IS_HTML5) return + if (!isPC()) return + if (!movable) return + touchmove(e, ins) +} + +function mouseup(e, ins) { + if (!IS_HTML5) return + if (!isPC()) return + touchend(e, ins) + movable = false +} + +function mouseleave(e, ins) { + if (!IS_HTML5) return + if (!isPC()) return + movable = false +} + +module.exports = { + showWatch: showWatch, + touchstart: touchstart, + touchmove: touchmove, + touchend: touchend, + mousedown: mousedown, + mousemove: mousemove, + mouseup: mouseup, + mouseleave: mouseleave +} diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue b/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue new file mode 100644 index 0000000..4971782 --- /dev/null +++ b/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue @@ -0,0 +1,60 @@ + + + + + diff --git a/uni_modules/uni-swipe-action/package.json b/uni_modules/uni-swipe-action/package.json new file mode 100644 index 0000000..7938097 --- /dev/null +++ b/uni_modules/uni-swipe-action/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-swipe-action", + "displayName": "uni-swipe-action 滑动操作", + "version": "1.3.3", + "description": "SwipeAction 滑动操作操作组件", + "keywords": [ + "", + "uni-ui", + "uniui", + "滑动删除", + "侧滑删除" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-swipe-action/readme.md b/uni_modules/uni-swipe-action/readme.md new file mode 100644 index 0000000..93a5cac --- /dev/null +++ b/uni_modules/uni-swipe-action/readme.md @@ -0,0 +1,11 @@ + + +## SwipeAction 滑动操作 +> **组件名:uni-swipe-action** +> 代码块: `uSwipeAction`、`uSwipeActionItem` + + +通过滑动触发选项的容器 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-swipe-action) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-swiper-dot/changelog.md b/uni_modules/uni-swiper-dot/changelog.md new file mode 100644 index 0000000..85cf54d --- /dev/null +++ b/uni_modules/uni-swiper-dot/changelog.md @@ -0,0 +1,12 @@ +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-swiper-dot](https://uniapp.dcloud.io/component/uniui/uni-swiper-dot) +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.6(2021-05-12) +- 新增 示例地址 +- 修复 示例项目缺少组件的Bug +## 1.0.5(2021-02-05) +- 调整为uni_modules目录规范 +- 新增 clickItem 事件,支持指示点控制轮播 +- 新增 支持 pc 可用 diff --git a/uni_modules/uni-swiper-dot/components/uni-swiper-dot/uni-swiper-dot.vue b/uni_modules/uni-swiper-dot/components/uni-swiper-dot/uni-swiper-dot.vue new file mode 100644 index 0000000..46eb8c1 --- /dev/null +++ b/uni_modules/uni-swiper-dot/components/uni-swiper-dot/uni-swiper-dot.vue @@ -0,0 +1,218 @@ + + + + + diff --git a/uni_modules/uni-swiper-dot/package.json b/uni_modules/uni-swiper-dot/package.json new file mode 100644 index 0000000..f2dd8d2 --- /dev/null +++ b/uni_modules/uni-swiper-dot/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-swiper-dot", + "displayName": "uni-swiper-dot 轮播图指示点", + "version": "1.2.0", + "description": "自定义轮播图指示点组件", + "keywords": [ + "uni-ui", + "uniui", + "轮播图指示点", + "dot", + "swiper" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-swiper-dot/readme.md b/uni_modules/uni-swiper-dot/readme.md new file mode 100644 index 0000000..7d397e2 --- /dev/null +++ b/uni_modules/uni-swiper-dot/readme.md @@ -0,0 +1,11 @@ + + +## SwiperDot 轮播图指示点 +> **组件名:uni-swiper-dot** +> 代码块: `uSwiperDot` + + +自定义轮播图指示点 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-swiper-dot) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-table/changelog.md b/uni_modules/uni-table/changelog.md new file mode 100644 index 0000000..b7aada3 --- /dev/null +++ b/uni_modules/uni-table/changelog.md @@ -0,0 +1,21 @@ +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-table](https://uniapp.dcloud.io/component/uniui/uni-table) +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.7(2021-07-08) +- 新增 uni-th 支持 date 日期筛选范围 +## 1.0.6(2021-07-05) +- 新增 uni-th 支持 range 筛选范围 +## 1.0.5(2021-06-28) +- 新增 uni-th 筛选功能 +## 1.0.4(2021-05-12) +- 新增 示例地址 +- 修复 示例项目缺少组件的Bug +## 1.0.3(2021-04-16) +- 新增 sortable 属性,是否开启单列排序 +- 优化 表格多选逻辑 +## 1.0.2(2021-03-22) +- uni-tr 添加 disabled 属性,用于 type=selection 时,设置某行是否可由全选按钮控制 +## 1.0.1(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-table/components/uni-table/uni-table.vue b/uni_modules/uni-table/components/uni-table/uni-table.vue new file mode 100644 index 0000000..91b74fa --- /dev/null +++ b/uni_modules/uni-table/components/uni-table/uni-table.vue @@ -0,0 +1,455 @@ + + + + + diff --git a/uni_modules/uni-table/components/uni-tbody/uni-tbody.vue b/uni_modules/uni-table/components/uni-tbody/uni-tbody.vue new file mode 100644 index 0000000..fbe1bdc --- /dev/null +++ b/uni_modules/uni-table/components/uni-tbody/uni-tbody.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/uni_modules/uni-table/components/uni-td/uni-td.vue b/uni_modules/uni-table/components/uni-td/uni-td.vue new file mode 100644 index 0000000..9ce93e9 --- /dev/null +++ b/uni_modules/uni-table/components/uni-td/uni-td.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/uni_modules/uni-table/components/uni-th/filter-dropdown.vue b/uni_modules/uni-table/components/uni-th/filter-dropdown.vue new file mode 100644 index 0000000..bc9a0e3 --- /dev/null +++ b/uni_modules/uni-table/components/uni-th/filter-dropdown.vue @@ -0,0 +1,503 @@ + + + + + diff --git a/uni_modules/uni-table/components/uni-th/uni-th.vue b/uni_modules/uni-table/components/uni-th/uni-th.vue new file mode 100644 index 0000000..65856c5 --- /dev/null +++ b/uni_modules/uni-table/components/uni-th/uni-th.vue @@ -0,0 +1,274 @@ + + + + + diff --git a/uni_modules/uni-table/components/uni-thead/uni-thead.vue b/uni_modules/uni-table/components/uni-thead/uni-thead.vue new file mode 100644 index 0000000..0dd18cd --- /dev/null +++ b/uni_modules/uni-table/components/uni-thead/uni-thead.vue @@ -0,0 +1,129 @@ + + + + + diff --git a/uni_modules/uni-table/components/uni-tr/table-checkbox.vue b/uni_modules/uni-table/components/uni-tr/table-checkbox.vue new file mode 100644 index 0000000..158f3ff --- /dev/null +++ b/uni_modules/uni-table/components/uni-tr/table-checkbox.vue @@ -0,0 +1,179 @@ + + + + + diff --git a/uni_modules/uni-table/components/uni-tr/uni-tr.vue b/uni_modules/uni-table/components/uni-tr/uni-tr.vue new file mode 100644 index 0000000..f9b9671 --- /dev/null +++ b/uni_modules/uni-table/components/uni-tr/uni-tr.vue @@ -0,0 +1,171 @@ + + + + + diff --git a/uni_modules/uni-table/i18n/en.json b/uni_modules/uni-table/i18n/en.json new file mode 100644 index 0000000..e32023c --- /dev/null +++ b/uni_modules/uni-table/i18n/en.json @@ -0,0 +1,9 @@ +{ + "filter-dropdown.reset": "Reset", + "filter-dropdown.search": "Search", + "filter-dropdown.submit": "Submit", + "filter-dropdown.filter": "Filter", + "filter-dropdown.gt": "Greater or equal to", + "filter-dropdown.lt": "Less than or equal to", + "filter-dropdown.date": "Date" +} diff --git a/uni_modules/uni-table/i18n/es.json b/uni_modules/uni-table/i18n/es.json new file mode 100644 index 0000000..9afd04b --- /dev/null +++ b/uni_modules/uni-table/i18n/es.json @@ -0,0 +1,9 @@ +{ + "filter-dropdown.reset": "Reiniciar", + "filter-dropdown.search": "Búsqueda", + "filter-dropdown.submit": "Entregar", + "filter-dropdown.filter": "Filtrar", + "filter-dropdown.gt": "Mayor o igual a", + "filter-dropdown.lt": "Menos que o igual a", + "filter-dropdown.date": "Fecha" +} diff --git a/uni_modules/uni-table/i18n/fr.json b/uni_modules/uni-table/i18n/fr.json new file mode 100644 index 0000000..b006237 --- /dev/null +++ b/uni_modules/uni-table/i18n/fr.json @@ -0,0 +1,9 @@ +{ + "filter-dropdown.reset": "Réinitialiser", + "filter-dropdown.search": "Chercher", + "filter-dropdown.submit": "Soumettre", + "filter-dropdown.filter": "Filtre", + "filter-dropdown.gt": "Supérieur ou égal à", + "filter-dropdown.lt": "Inférieur ou égal à", + "filter-dropdown.date": "Date" +} diff --git a/uni_modules/uni-table/i18n/index.js b/uni_modules/uni-table/i18n/index.js new file mode 100644 index 0000000..2469dd0 --- /dev/null +++ b/uni_modules/uni-table/i18n/index.js @@ -0,0 +1,12 @@ +import en from './en.json' +import es from './es.json' +import fr from './fr.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + es, + fr, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/uni_modules/uni-table/i18n/zh-Hans.json b/uni_modules/uni-table/i18n/zh-Hans.json new file mode 100644 index 0000000..862af17 --- /dev/null +++ b/uni_modules/uni-table/i18n/zh-Hans.json @@ -0,0 +1,9 @@ +{ + "filter-dropdown.reset": "重置", + "filter-dropdown.search": "搜索", + "filter-dropdown.submit": "确定", + "filter-dropdown.filter": "筛选", + "filter-dropdown.gt": "大于等于", + "filter-dropdown.lt": "小于等于", + "filter-dropdown.date": "日期范围" +} diff --git a/uni_modules/uni-table/i18n/zh-Hant.json b/uni_modules/uni-table/i18n/zh-Hant.json new file mode 100644 index 0000000..64f8061 --- /dev/null +++ b/uni_modules/uni-table/i18n/zh-Hant.json @@ -0,0 +1,9 @@ +{ + "filter-dropdown.reset": "重置", + "filter-dropdown.search": "搜索", + "filter-dropdown.submit": "確定", + "filter-dropdown.filter": "篩選", + "filter-dropdown.gt": "大於等於", + "filter-dropdown.lt": "小於等於", + "filter-dropdown.date": "日期範圍" +} diff --git a/uni_modules/uni-table/package.json b/uni_modules/uni-table/package.json new file mode 100644 index 0000000..754e753 --- /dev/null +++ b/uni_modules/uni-table/package.json @@ -0,0 +1,86 @@ +{ + "id": "uni-table", + "displayName": "uni-table 表格", + "version": "1.2.0", + "description": "表格组件,多用于展示多条结构类似的数据,如", + "keywords": [ + "uni-ui", + "uniui", + "table", + "表格" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss","uni-datetime-picker"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "n" + }, + "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", + "字节跳动": "n", + "QQ": "y" + }, + "快应用": { + "华为": "n", + "联盟": "n" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-table/readme.md b/uni_modules/uni-table/readme.md new file mode 100644 index 0000000..bb08c79 --- /dev/null +++ b/uni_modules/uni-table/readme.md @@ -0,0 +1,13 @@ + + +## Table 表单 +> 组件名:``uni-table``,代码块: `uTable`。 + +用于展示多条结构类似的数据 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-table) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + + + diff --git a/uni_modules/uni-tag/changelog.md b/uni_modules/uni-tag/changelog.md new file mode 100644 index 0000000..c0c5839 --- /dev/null +++ b/uni_modules/uni-tag/changelog.md @@ -0,0 +1,21 @@ +## 2.1.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-tag](https://uniapp.dcloud.io/component/uniui/uni-tag) +## 2.0.0(2021-11-09) +- 新增 提供组件设计资源,组件样式调整 +- 移除 插槽 +- 移除 type 属性的 royal 选项 +## 1.1.1(2021-08-11) +- type 不是 default 时,size 为 small 字体大小显示不正确 +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.7(2021-06-18) +- 修复 uni-tag 在字节跳动小程序上 css 类名编译错误的 bug +## 1.0.6(2021-06-04) +- 修复 未定义 sass 变量 "$uni-color-royal" 的bug +## 1.0.5(2021-05-10) +- 修复 royal 类型无效的bug +- 修复 uni-tag 宽度不自适应的bug +- 新增 uni-tag 支持属性 custom-style 自定义样式 +## 1.0.4(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-tag/components/uni-tag/uni-tag.vue b/uni_modules/uni-tag/components/uni-tag/uni-tag.vue new file mode 100644 index 0000000..6378a0b --- /dev/null +++ b/uni_modules/uni-tag/components/uni-tag/uni-tag.vue @@ -0,0 +1,252 @@ + + + + + diff --git a/uni_modules/uni-tag/package.json b/uni_modules/uni-tag/package.json new file mode 100644 index 0000000..1878088 --- /dev/null +++ b/uni_modules/uni-tag/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-tag", + "displayName": "uni-tag 标签", + "version": "2.1.0", + "description": "Tag 组件,用于展示1个或多个文字标签,可点击切换选中、不选中的状态。", + "keywords": [ + "uni-ui", + "uniui", + "", + "tag", + "标签" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-tag/readme.md b/uni_modules/uni-tag/readme.md new file mode 100644 index 0000000..6e78ff5 --- /dev/null +++ b/uni_modules/uni-tag/readme.md @@ -0,0 +1,13 @@ + + +## Tag 标签 +> **组件名:uni-tag** +> 代码块: `uTag` + + +用于展示1个或多个文字标签,可点击切换选中、不选中的状态 。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-tag) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/uni_modules/uni-test/changelog.md b/uni_modules/uni-test/changelog.md new file mode 100644 index 0000000..2f3b102 --- /dev/null +++ b/uni_modules/uni-test/changelog.md @@ -0,0 +1,39 @@ +## 2.0.13(2021-11-18) +邱 +## 2.0.12(2021-11-18) +123123 +## 2.0.11(2021-11-18) +0000 +## 2.0.10(2021-11-18) +111234 +## 2.0.9(2021-11-18) +3333 +## 2.0.8(2021-11-18) +=== +## 2.0.7(2021-11-18) +111 +## 2.0.6(2021-05-26) +- test +## 0.0.37(2021-03-23) +- uni-forms 更新 校验器 +- uni-forms 修复 表单规则设置类型为 number 的情况下,值为0校验失败的Bug + + +## 0.0.36(2021-03-23) +- uni-forms 更新 校验器 +- uni-forms 修复 表单规则设置类型为 number 的情况下,值为0校验失败的Bug + + +## 0.0.35(2021-03-23) +- uni-forms 更新 校验器 +- uni-forms 修复 表单规则设置类型为 number 的情况下,值为0校验失败的Bug + + +## 0.0.34(2021-03-23) +- 测试新同步插件 +## 0.0.33(2021-03-09) +- test +## 0.0.32(2021-02-24) +- 更新 read 2 +## 0.0.31(2021-02-24) +- 同步 readme.md diff --git a/uni_modules/uni-test/components/uni-test/uni-test.vue b/uni_modules/uni-test/components/uni-test/uni-test.vue new file mode 100644 index 0000000..9ea8aaf --- /dev/null +++ b/uni_modules/uni-test/components/uni-test/uni-test.vue @@ -0,0 +1,26 @@ + + + + + diff --git a/uni_modules/uni-test/package.json b/uni_modules/uni-test/package.json new file mode 100644 index 0000000..9a3c4c4 --- /dev/null +++ b/uni_modules/uni-test/package.json @@ -0,0 +1,83 @@ +{ + "id": "uni-test", + "displayName": "Test 测试插件", + "version": "2.0.13", + "description": "测试插件 ", + "keywords": [ + "test" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "^3.1.3" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-test/readme.md b/uni_modules/uni-test/readme.md new file mode 100644 index 0000000..ddb24c6 --- /dev/null +++ b/uni_modules/uni-test/readme.md @@ -0,0 +1,10 @@ + + +## DataCheckbox 数据驱动的单选复选框 +> **组件名:uni-data-checkbox** +> 代码块: `uDataCheckbox` + + +本组件是基于uni-app基础组件checkbox的封装。本组件要解决问题包括: + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-card) \ No newline at end of file diff --git a/uni_modules/uni-title/changelog.md b/uni_modules/uni-title/changelog.md new file mode 100644 index 0000000..f0f1d67 --- /dev/null +++ b/uni_modules/uni-title/changelog.md @@ -0,0 +1,8 @@ +## 1.1.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-title](https://uniapp.dcloud.io/component/uniui/uni-title) +## 1.0.2(2021-05-12) +- 新增 示例地址 +- 修复 示例项目缺少组件的Bug +## 1.0.1(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-title/components/uni-title/uni-title.vue b/uni_modules/uni-title/components/uni-title/uni-title.vue new file mode 100644 index 0000000..1f3a91a --- /dev/null +++ b/uni_modules/uni-title/components/uni-title/uni-title.vue @@ -0,0 +1,171 @@ + + + + + diff --git a/uni_modules/uni-title/package.json b/uni_modules/uni-title/package.json new file mode 100644 index 0000000..3b37082 --- /dev/null +++ b/uni_modules/uni-title/package.json @@ -0,0 +1,88 @@ +{ + "id": "uni-title", + "displayName": "uni-title 章节标题", + "version": "1.1.0", + "description": "章节标题,通常用于记录页面标题,使用当前组件,uni-app 如果开启统计,将会自动统计页面标题", + "keywords": [ + "uni-ui", + "uniui", + "标题", + "章节", + "章节标题", + "" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-title/readme.md b/uni_modules/uni-title/readme.md new file mode 100644 index 0000000..ad1b4bf --- /dev/null +++ b/uni_modules/uni-title/readme.md @@ -0,0 +1,14 @@ + + +## Title 章节标题 +> **组件名:uni-title** +> 代码块: `uTitle` + + +章节标题,通常用于记录页面标题,使用当前组件,uni-app 如果开启统计,将会自动统计页面标题 。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-title) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + + diff --git a/uni_modules/uni-transition/changelog.md b/uni_modules/uni-transition/changelog.md new file mode 100644 index 0000000..b1a824b --- /dev/null +++ b/uni_modules/uni-transition/changelog.md @@ -0,0 +1,20 @@ +## 1.3.1(2021-11-23) +- 修复 init 方法初始化问题 +## 1.3.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-transition](https://uniapp.dcloud.io/component/uniui/uni-transition) +## 1.2.1(2021-09-27) +- 修复 init 方法不生效的 Bug +## 1.2.0(2021-07-30) +- 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.1.1(2021-05-12) +- 新增 示例地址 +- 修复 示例项目缺少组件的 Bug +## 1.1.0(2021-04-22) +- 新增 通过方法自定义动画 +- 新增 custom-class 非 NVUE 平台支持自定义 class 定制样式 +- 优化 动画触发逻辑,使动画更流畅 +- 优化 支持单独的动画类型 +- 优化 文档示例 +## 1.0.2(2021-02-05) +- 调整为 uni_modules 目录规范 diff --git a/uni_modules/uni-transition/components/uni-transition/createAnimation.js b/uni_modules/uni-transition/components/uni-transition/createAnimation.js new file mode 100644 index 0000000..5f54365 --- /dev/null +++ b/uni_modules/uni-transition/components/uni-transition/createAnimation.js @@ -0,0 +1,128 @@ +// const defaultOption = { +// duration: 300, +// timingFunction: 'linear', +// delay: 0, +// transformOrigin: '50% 50% 0' +// } +// #ifdef APP-NVUE +const nvueAnimation = uni.requireNativePlugin('animation') +// #endif +class MPAnimation { + constructor(options, _this) { + this.options = options + this.animation = uni.createAnimation(options) + this.currentStepAnimates = {} + this.next = 0 + this.$ = _this + + } + + _nvuePushAnimates(type, args) { + let aniObj = this.currentStepAnimates[this.next] + let styles = {} + if (!aniObj) { + styles = { + styles: {}, + config: {} + } + } else { + styles = aniObj + } + if (animateTypes1.includes(type)) { + if (!styles.styles.transform) { + styles.styles.transform = '' + } + let unit = '' + if(type === 'rotate'){ + unit = 'deg' + } + styles.styles.transform += `${type}(${args+unit}) ` + } else { + styles.styles[type] = `${args}` + } + this.currentStepAnimates[this.next] = styles + } + _animateRun(styles = {}, config = {}) { + let ref = this.$.$refs['ani'].ref + if (!ref) return + return new Promise((resolve, reject) => { + nvueAnimation.transition(ref, { + styles, + ...config + }, res => { + resolve() + }) + }) + } + + _nvueNextAnimate(animates, step = 0, fn) { + let obj = animates[step] + if (obj) { + let { + styles, + config + } = obj + this._animateRun(styles, config).then(() => { + step += 1 + this._nvueNextAnimate(animates, step, fn) + }) + } else { + this.currentStepAnimates = {} + typeof fn === 'function' && fn() + this.isEnd = true + } + } + + step(config = {}) { + // #ifndef APP-NVUE + this.animation.step(config) + // #endif + // #ifdef APP-NVUE + this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config) + this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin + this.next++ + // #endif + return this + } + + run(fn) { + // #ifndef APP-NVUE + this.$.animationData = this.animation.export() + this.$.timer = setTimeout(() => { + typeof fn === 'function' && fn() + }, this.$.durationTime) + // #endif + // #ifdef APP-NVUE + this.isEnd = false + let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref + if(!ref) return + this._nvueNextAnimate(this.currentStepAnimates, 0, fn) + this.next = 0 + // #endif + } +} + + +const animateTypes1 = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d', + 'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY', + 'translateZ' +] +const animateTypes2 = ['opacity', 'backgroundColor'] +const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom'] +animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => { + MPAnimation.prototype[type] = function(...args) { + // #ifndef APP-NVUE + this.animation[type](...args) + // #endif + // #ifdef APP-NVUE + this._nvuePushAnimates(type, args) + // #endif + return this + } +}) + +export function createAnimation(option, _this) { + if(!_this) return + clearTimeout(_this.timer) + return new MPAnimation(option, _this) +} diff --git a/uni_modules/uni-transition/components/uni-transition/uni-transition.vue b/uni_modules/uni-transition/components/uni-transition/uni-transition.vue new file mode 100644 index 0000000..0d739bd --- /dev/null +++ b/uni_modules/uni-transition/components/uni-transition/uni-transition.vue @@ -0,0 +1,277 @@ + + + + + diff --git a/uni_modules/uni-transition/package.json b/uni_modules/uni-transition/package.json new file mode 100644 index 0000000..d15fdf0 --- /dev/null +++ b/uni_modules/uni-transition/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-transition", + "displayName": "uni-transition 过渡动画", + "version": "1.3.1", + "description": "元素的简单过渡动画", + "keywords": [ + "uni-ui", + "uniui", + "动画", + "过渡", + "过渡动画" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-transition/readme.md b/uni_modules/uni-transition/readme.md new file mode 100644 index 0000000..2f8a77e --- /dev/null +++ b/uni_modules/uni-transition/readme.md @@ -0,0 +1,11 @@ + + +## Transition 过渡动画 +> **组件名:uni-transition** +> 代码块: `uTransition` + + +元素过渡动画 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-transition) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-ui/changelog.md b/uni_modules/uni-ui/changelog.md new file mode 100644 index 0000000..1446368 --- /dev/null +++ b/uni_modules/uni-ui/changelog.md @@ -0,0 +1,383 @@ +## 1.4.14(2022-04-18) +- uni-datetime-picker 修复 Vue3 下动态赋值,单选类型未响应的 bug +- uni-easyinput 修复 默认值不生效的bug +## 1.4.13(2022-04-02) +- uni-calendar 修复 条件编译 nvue 不支持的 css 样式 +- uni-calendar 修复 startDate、 endDate 属性失效的 bug +- uni-data-picker 修复 nvue 不支持的 v-show 的 bug +- uni-data-picker 修复 条件编译 nvue 不支持的 css 样式 +- uni-datetime-picker 修复 Vue3 下动态赋值未响应的 bug +- uni-easyinput 修复 value不能为0的bug +- uni-popup 修复 弹出层内部无法滚动的bug +- uni-popup 修复 小程序中高度错误的bug +- uni-popup 修复 快速调用open出现问题的Bug +- uni-rate 修复 条件判断 `NaN` 错误的 bug +- uni-swipe-action 修复 按钮字体大小不能设置的bug +- uni-swipe-action 修复 h5和app端下报el错误的bug +- uni-swipe-action 修复 HBuilderX 1.4.X 版本中,h5和app端下报错的bug +## 1.4.12(2022-02-19) +- uni-collapse 修复 初始化的时候 ,open 属性失效的bug +- uni-data-checkbox 修复 multiple 为 true 时,v-model 的值为 null 报错的 bug +- uni-icons 优化 size 属性可以传入不带单位的字符串数值 +- uni-icons 优化 size 支持其他单位 +- uni-nav-bar 新增 left-width/right-width属性 ,可修改左右两侧的宽度 +- uni-popup 修复 safeArea 属性不能设置为false的bug +## 1.4.11(2022-01-21) +- uni-collapse 修复 微信小程序resize后组件收起的bug +- uni-countdown 修复 在微信小程序中样式不生效的bug +- uni-countdown 新增 update 方法 ,在动态更新时间后,刷新组件 +- uni-load-more 新增 showText属性 ,是否显示文本 +- uni-load-more 修复 nvue 平台下不显示文本的bug +- uni-load-more 修复 微信小程序平台样式选择器报警告的问题 +- uni-nav-bar 修复 在vue下,标题不垂直居中的bug +- uni-nav-bar 修复 height 属性类型错误 +- uni-nav-bar 新增 height 属性,可修改组件高度 +- uni-nav-bar 新增 dark 属性可可开启暗黑模式 +- uni-nav-bar 优化 标题字数过多显示省略号 +- uni-nav-bar 优化 插槽,插入内容可完全覆盖 +- uni-popup 修复 isMaskClick 失效的bug +- uni-popup 新增 cancelText \ confirmText 属性 ,可自定义文本 +- uni-popup 新增 maskBackgroundColor 属性 ,可以修改蒙版颜色 +- uni-popup 优化 maskClick属性 更新为 isMaskClick ,解决微信小程序警告的问题 + +## 1.4.10(2022-01-17) +- uni-card 修复 在vue页面下略缩图显示不正常的bug +- uni-datetime-picker 修复 clear-icon 属性在小程序平台不生效的 bug +- uni-datetime-picker 修复 日期范围选在小程序平台,必须多点击一次才能取消选中状态的 bug +- uni-fab 更新 组件依赖 +- +- uni-icons 修复 nvue 有些图标不显示的bug,兼容老版本图标 +- uni-icons 优化 示例可复制图标名称 +- uni-nav-bar 修复 color 属性不生效的bug +- uni-popup 修复 设置 safeArea 属性不生效的bug +- uni-popup 优化 组件示例 +- uni-popup 修复 vuedoc 文字错误 +## 1.4.9(2021-11-23) +- uni-ui 修复 vue3中某些scss变量无法找到的问题 +- uni-combox 优化 label、label-width 属性 +- uni-data-picker 修复 由上个版本引发的map、v-model等属性不生效的bug +- uni-file-picker 修复 参数为对象的情况下,url在某些情况显示错误的bug +- uni-icons 优化 兼容旧组件 type 值 +- uni-list 修复 在vue3中to属性在发行应用的时候报错的bug +- uni-scss 修复 vue3中scss语法兼容问题 +- uni-transition 修复 init 方法初始化问题 +## 1.4.8(2021-11-19) +- uni-fab 修复 阴影颜色不正确的bug +## 1.4.7(2021-11-19) +- uni-ui 新增 支持国际化 +- uni-ui 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- uni-ui 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-ui](https://uniapp.dcloud.io/component/uniui/uni-ui) +- uni-badge 修改 size 属性默认值调整为 small +- uni-badge 修改 type 属性,默认值调整为 error,info 替换 default +- uni-badge 修复 在字节小程序上样式不生效的 bug +- uni-calendar 修复 弹出层被 tabbar 遮盖 bug +- uni-card 重构插槽的用法 ,header 替换为 title +- uni-card 新增 actions 插槽 +- uni-card 新增 cover 封面图属性和插槽 +- uni-card 新增 padding 内容默认内边距离 +- uni-card 新增 margin 卡片默认外边距离 +- uni-card 新增 spacing 卡片默认内边距 +- uni-card 新增 shadow 卡片阴影属性 +- uni-card 取消 mode 属性,可使用组合插槽代替 +- uni-card 取消 note 属性 ,使用actions插槽代替 +- uni-collapse 优化 show-arrow 属性默认为true +- uni-collapse 新增 show-arrow 属性,控制是否显示右侧箭头 +- uni-countdown 新增 font-size 支持自定义字体大小 +- uni-data-checkbox 修复 在uni-forms中 modelValue 中不存在当前字段,当前字段必填写也不参与校验的问题 +- uni-data-checkbox 修复 单选 list 模式下 ,icon 为 left 时,选中图标不显示的问题 +- uni-data-checkbox 修复 在 uni-forms 中重置表单,错误信息无法清除的问题 +- uni-dateformat 优化 默认时间不再是当前时间,而是显示'-'字符 +- uni-datetime-picker 修复 hide-second 在移动端的 bug +- uni-datetime-picker 修复 单选赋默认值时,赋值日期未高亮的 bug +- uni-datetime-picker 修复 赋默认值时,移动端未正确显示时间的 bug +- uni-datetime-picker 新增 hide-second 属性,支持只使用时分,隐藏秒 +- uni-datetime-picker 优化 取消选中时(范围选)直接开始下一次选择, 避免多点一次 +- uni-datetime-picker 优化 移动端支持清除按钮,同时支持通过 ref 调用组件的 clear 方法 +- uni-datetime-picker 优化 调整字号大小,美化日历界面 +- uni-datetime-picker 优化 范围选择器在 pc 端过宽的问题 +- uni-datetime-picker 新增 支持作为 uni-forms 子组件相关功能 +- uni-datetime-picker 修复 在 uni-forms 中使用时,选择时间报 NAN 错误的 bug +- uni-datetime-picker 修复 type 属性动态赋值无效的 bug +- uni-datetime-picker 修复 ‘确认’按钮被 tabbar 遮盖 bug +- uni-datetime-picker 修复 组件未赋值时范围选左、右日历相同的 bug +- uni-datetime-picker 修复 范围选未正确显示当前值的 bug +- uni-datetime-picker 修复 h5 平台(移动端)报错 'cale' of undefined 的 bug +- uni-easyinput 修复 在 uni-forms 的动态表单中默认值校验不通过的 bug +- uni-easyinput 修复 在 uni-forms 中重置表单,错误信息无法清除的问题 +- uni-file-picker 新增 参数中返回 fileID 字段 +- uni-file-picker 修复 腾讯云传入fileID 不能回显的bug +- uni-file-picker 修复 选择图片后,不能放大的问题 +- uni-file-picker 修复 由于 0.2.11 版本引起的不能回显图片的Bug +- uni-file-picker 新增 clearFiles(index) 方法,可以手动删除指定文件 +- uni-file-picker 修复 v-model 值设为 null 报错的Bug +- uni-file-picker 修复 return-type="object" 时,无法删除文件的Bug +- uni-file-picker 修复 auto-upload 属性失效的Bug +- uni-forms 修复 label 插槽不生效的bug +- uni-forms 修复 没有添加校验规则的字段依然报错的Bug +- uni-forms 修复 重置表单错误信息无法清除的问题 +- uni-forms 修复 表单验证只生效一次的问题 +- uni-icons 新增 更多图标 +- uni-icons 优化 自定义图标使用方式 +- uni-link 修复 在 nvue 下不显示的 bug +- uni-pagination 修复 current 、value 属性未监听,导致高亮样式失效的 bug +- uni-rate 优化 默认值修改为 0 颗星 +- uni-search-bar 修复 value 属性与 modelValue 属性不兼容的Bug +- uni-swipe-action 新增 close-all 方法,关闭所有已打开的组件 +- uni-swipe-action 新增 resize() 方法,在非微信小程序、h5、app-vue端出现不能滑动的问题的时候,重置组件 +- uni-swipe-action 修复 app 端偶尔出现类似 Page[x][-x,xx;-x,xx,x,x-x] 的问题 +- uni-swipe-action 优化 微信小程序、h5、app-vue 滑动逻辑,避免出现动态新增组件后不能滑动的问题 +- uni-tag 新增 提供组件设计资源,组件样式调整 +- uni-tag 移除 插槽 +- uni-tag 移除 type 属性的 royal 选项 +- uni-tag type 不是 default 时,size 为 small 字体大小显示不正确 +## 1.4.2(2021-08-20) +- 新增 uni-ui 组件支持国际化 i18n +- uni-collapse 优化 show-arrow 属性默认为true +- uni-collapse 新增 show-arrow 属性,控制是否显示右侧箭头 +- uni-data-checkbox 修复 单选 list 模式下 ,icon 为 left 时,选中图标不显示的问题 +- uni-easyinput 修复 在 uni-forms 的动态表单中默认值校验不通过的 bug +- uni-file-picker 修复 由于 0.2.11 版本引起的不能回显图片的Bug +- uni-file-picker 新增 clearFiles(index) 方法,可以手动删除指定文件 +- uni-file-picker 修复 v-model 值设为 null 报错的Bug +- uni-swipe-action 新增 close-all 方法,关闭所有已打开的组件 +- uni-swipe-action 新增 resize() 方法,在非微信小程序、h5、app-vue端出现不能滑动的问题的时候,重置组件 +- uni-swipe-action 修复 app 端偶尔出现类似 Page[x][-x,xx;-x,xx,x,x-x] 的问题 +- uni-swipe-action 优化 微信小程序、h5、app-vue 滑动逻辑,避免出现动态新增组件后不能滑动的问题 +## 1.4.0(2021-08-13) +- uni-calendar 修复 弹出层被 tabbar 遮盖 bug +- uni-data-checkbox 修复 在 uni-forms 中重置表单,错误信息无法清除的问题 +- uni-dateformat 调整 默认时间不再是当前时间,而是显示'-'字符 +- uni-datetime-picker 新增 适配 vue3 +- uni-datetime-picker 新增 支持作为 uni-forms 子组件相关功能 +- uni-datetime-picker 修复 在 uni-forms 中使用时,选择时间报 NAN 错误的 bug +- uni-datetime-picker 修复 type 属性动态赋值无效的 bug +- uni-datetime-picker 修复 ‘确认’按钮被 tabbar 遮盖 bug +- uni-datetime-picker 修复 组件未赋值时范围选左、右日历相同的 bug +- uni-datetime-picker 修复 范围选未正确显示当前值的 bug +- uni-datetime-picker 修复 h5 平台(移动端)报错 'cale' of undefined 的 bug +- uni-easyinput 修复 在 uni-forms 中重置表单,错误信息无法清除的问题 +- uni-file-picker 修复 return-type="object" 时,无法删除文件的Bug +- uni-file-picker 修复 auto-upload 属性失效的Bug +- uni-forms 修复 没有添加校验规则的字段依然报错的Bug +- uni-forms 修复 重置表单错误信息无法清除的问题 +- uni-forms 优化 组件文档 +- uni-forms 修复 表单验证只生效一次的问题 +- uni-tag type 不是 default 时,size 为 small 字体大小显示不正确 +## 1.3.9(2021-08-02) +- uni-datetime-picker 新增 return-type 属性支持返回 date 日期对象 +- uni-file-picker 修复 fileExtname属性不指定值报错的Bug +- uni-file-picker 修复 在某种场景下图片不回显的Bug +- uni-link 支持自定义插槽 +## 1.3.8(2021-07-31) +- uni-ui 组件兼容 vue3 +- uni-collapse 修复 由1.2.0版本引起的 change 事件返回 undefined 的Bug +- uni-collapse 优化 组件示例 +- uni-collapse 新增 组件折叠动画 +- uni-collapse 新增 value\v-model 属性 ,动态修改面板折叠状态 +- uni-collapse 新增 title 插槽 ,可定义面板标题 +- uni-collapse 新增 border 属性 ,显示隐藏面板内容分隔线 +- uni-collapse 新增 title-border 属性 ,显示隐藏面板标题分隔线 +- uni-collapse 修复 resize 方法失效的Bug +- uni-collapse 修复 change 事件返回参数不正确的Bug +- uni-collapse 优化 H5、App 平台自动更具内容更新高度,无需调用 reszie() 方法 +- uni-data-checkbox 优化 在uni-forms组件,与label不对齐的问题 +- uni-data-checkbox 修复 单选默认值为0不能选中的Bug +- uni-easyinput 优化 errorMessage 属性支持 Boolean 类型 +- uni-file-picker 修复 return-type为object下,返回值不正确的Bug +- uni-file-picker 修复(重要) H5 平台下如果和uni-forms组件一同使用导致页面卡死的问题 +- uni-file-picker 优化 h5平台下上传文件导致页面卡死的问题 +- uni-forms 修复 vue2 下条件编译导致destroyed生命周期失效的Bug +- uni-forms 修复 1.2.1 引起的示例在小程序平台报错的Bug +- uni-forms 修复 动态校验表单,默认值为空的情况下校验失效的Bug +- uni-forms 修复 不指定name属性时,运行报错的Bug +- uni-forms 优化 label默认宽度从65调整至70,使required为true且四字时不换行 +- uni-forms 优化 组件示例,新增动态校验示例代码 +- uni-forms 优化 组件文档,使用方式更清晰 +- uni-list 修复 与其他组件嵌套使用时,点击失效的Bug +- uni-swipe-action 修复 跨页面修改组件数据 ,导致不能滑动的问题 +## 1.3.7(2021-07-16) +- uni-ui 兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +- uni-datetime-picker 修复 单选日期类型,初始赋值后不在当前日历的 bug +- uni-datetime-picker 新增 clearIcon 属性,显示框的清空按钮可配置显示隐藏(仅 pc 有效) +- uni-datetime-picker 优化 移动端移除显示框的清空按钮,无实际用途 +- uni-datetime-picker 修复 组件赋值为空,界面未更新的 bug +- uni-datetime-picker 修复 start 和 end 不能动态赋值的 bug +- uni-datetime-picker 修复 范围选类型,用户选择后再次选择右侧日历(结束日期)显示不正确的 bug +## 1.3.6(2021-07-09) +- uni-data-checkbox 优化 删除无用日志 +- uni-data-checkbox 修复 由 0.1.9 引起的非 nvue 端图标不显示的问题 +- uni-data-checkbox 修复 nvue 黑框样式问题 +- uni-datetime-picker 修复 范围选择不能动态赋值的 bug +- uni-datetime-picker 修复 范围选择的初始时间在一个月内时,造成无法选择的bug +- uni-datetime-picker 优化 弹出层在超出视窗边缘定位不准确的问题 +- uni-datetime-picker 修复 范围起始点样式的背景色与今日样式的字体前景色融合,导致日期字体看不清的 bug +- uni-datetime-picker 优化 弹出层在超出视窗边缘被遮盖的问题 +- uni-datetime-picker 新增 maskClick 事件 +- uni-datetime-picker 修复 特殊情况日历 rpx 布局错误的 bug,rpx -> px +- uni-datetime-picker 修复 范围选择时清空返回值不合理的bug,['', ''] -> [] +- uni-datetime-picker 新增 日期时间显示框支持插槽 +- uni-file-picker 修复 sourceType 缺少默认值导致 ios 无法选择文件 +- uni-file-picker 优化 解耦与uniCloud的强绑定关系 ,如不绑定服务空间,默认autoUpload为false且不可更改 +- uni-table 新增 uni-th 支持 date 日期筛选范围 +- uni-table 新增 uni-th 支持 range 筛选范围 +- uni-table 新增 uni-th 筛选功能 +## 1.3.5(2021-07-02) +- uni-card 优化 图文卡片无图片加载时,提供占位图标 +- uni-card 新增 header 插槽,自定义卡片头部( 图文卡片 mode="style" 时,不支持) +- uni-card 修复 thumbnail 不存在仍然占位的 bug +- uni-data-checkbox 修复 selectedTextColor 属性不生效的Bug +- uni-datetime-picker 优化 添加 uni-icons 依赖 +- uni-easyinput 修复 confirmType 属性(仅 type="text" 生效)导致多行文本框无法换行的 bug +- uni-file-picker 修复 由 0.0.10 版本引发的 returnType 属性失效的问题 +- uni-file-picker 优化 文件上传后进度条消失时机 +- uni-file-picker 修复 在uni-forms 中,删除文件 ,获取的值不对的Bug +- uni-forms 修复 pattern 属性在微信小程序平台无效的问题 +## 1.3.4(2021-06-25) +- uni-badge 优化 示例项目 +- uni-countdown 修复 uni-countdown 重复赋值跳两秒的 bug +- uni-easyinput 修复 passwordIcon 属性拼写错误的 bug +- uni-forms 修复 validate-trigger属性为submit且err-show-type属性为toast时不能弹出的Bug +- uni-forms 修复 只写setRules方法而导致校验不生效的Bug +- uni-forms 修复 由上个办法引发的错误提示文字错位的Bug +- uni-forms 修复 不设置 label 属性 ,无法设置label插槽的问题 +- uni-forms 修复 不设置label属性,label-width属性不生效的bug +- uni-forms 修复 setRules 方法与rules属性冲突的问题 +- uni-link 新增 download 属性,H5平台下载文件名 +- uni-popup 新增 mask-click 遮罩层点击事件 +- uni-popup 修复 nvue 平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug +- uni-tag 修复 uni-tag 在字节跳动小程序上 css 类名编译错误的 bug +## 1.3.3(2021-06-18) +- uni-easyinput 新增 passwordIcon 属性,当type=password时是否显示小眼睛图标 +- uni-easyinput 修复 confirmType 属性不生效的问题 +- uni-easyinput 修复 disabled 状态可清出内容的 bug +- uni-file-picker 修复 删除文件时无法触发 v-model 的Bug +- uni-popup 修复 H5平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug +- uni-popup 修复 错误的 watch 字段 +- uni-popup 修复 safeArea 属性不生效的问题 +- uni-popup 修复 点击内容,再点击遮罩无法关闭的Bug +## 1.3.2(2021-06-04) +- uni-data-checkbox 新增 map 属性,可以方便映射text/value属性 +- uni-data-checkbox 修复 不关联服务空间的情况下组件报错的Bug +- uni-data-picker 修复 上个版本引出的本地数据无法选择带有children的2级节点 +- uni-forms 修复 动态删减数据导致报错的问题 +- uni-forms 新增 modelValue 属性 ,value 即将废弃 +- uni-forms 新增 uni-forms-item 可以设置单独的 rules +- uni-forms 新增 validate 事件增加 keepitem 参数,可以选择那些字段不过滤 +- uni-forms 优化 submit 事件重命名为 validate +- uni-data-picker 修复 无法加载云端数据的问题 +- uni-data-picker 修复 v-model无效问题 +- uni-data-picker 修复 loaddata 为空数据组时加载时间过长问题 +- uni-datetime-picker 修复 图标在小程序上不显示的 bug +- uni-datetime-picker 优化 重命名引用组件,避免潜在组件命名冲突 +- uni-datetime-picker 优化 代码目录扁平化 +- uni-tag 修复 未定义 sass 变量 "$uni-color-royal" 的bug +## 1.3.1(2021-05-14) +- uni-badge 新增 uni-badge 的 absolute 属性,支持定位 +- uni-badge 新增 uni-badge 的 offset 属性,支持定位偏移 +- uni-badge 新增 uni-badge 的 is-dot 属性,支持仅显示有一个小点 +- uni-badge 新增 uni-badge 的 max-num 属性,支持自定义封顶的数字值,超过 99 显示99+ +- uni-badge 优化 uni-badge 属性 custom-style, 支持以对象形式自定义样式 +- uni-badge 修复 uni-badge 在 App 端,数字小于10时不是圆形的bug +- uni-badge 修复 uni-badge 在父元素不是 flex 布局时,宽度缩小的bug +- uni-badge 新增 uni-badge 属性 custom-style, 支持自定义样式 +- uni-datetime-picker 修复 ios 下不识别 '-' 日期格式的 bug +- uni-datetime-picker 优化 pc 下弹出层添加边框和阴影 +- uni-datetime-picker 修复 在 admin 中获取弹出层定位错误的bug +- uni-datetime-picker 修复 type 属性向下兼容,默认值从 date 变更为 datetime +- uni-datetime-picker 支持日历形式的日期+时间的范围选择 +- uni-steps 修复 uni-steps 横向布局时,多行文字高度不合理的 bug +- uni-countdown 修复 uni-countdown 不能控制倒计时的 bug +- uni-tag 修复 royal 类型无效的bug +- uni-tag 修复 uni-tag 宽度不自适应的bug +- uni-tag 新增 uni-tag 支持属性 custom-style 自定义样式 +- uni-link 新增 href 属性支持 tel:|mailto: +- uni-popup 修复 组件内放置 input 、textarea 组件,无法聚焦的问题 +- uni-popup 新增 type 属性的 left\right 值,支持左右弹出 +- uni-popup 新增 open(String:type) 方法参数 ,可以省略 type 属性 ,直接传入类型打开指定弹窗 +- uni-popup 新增 backgroundColor 属性,可定义主窗口背景色,默认不显示背景色 +- uni-popup 新增 safeArea 属性,是否适配底部安全区 +- uni-popup 修复 App\h5\微信小程序底部安全区占位不对的Bug +- uni-popup 修复 App 端弹出等待的Bug +- uni-popup 优化 提升低配设备性能,优化动画卡顿问题 +- uni-popup 优化 更简单的组件自定义方式 +- uni-table 修复 示例项目缺少组件的Bug +- uni-forms 修复 自定义检验器失效的问题 +- uni-title 修复 示例项目缺少组件的Bug +- uni-transition 修复 示例项目缺少组件的Bug +- uni-swiper-dot 修复 示例项目缺少组件的Bug +- uni-ui 新增 组件示例地址 +## 1.3.0(2021-04-23) +- uni-combox 优化 添加依赖 uni-icons, 导入后自动下载依赖 +- uni-data-picker 修复 非树形数据有 where 属性查询报错的问题 +- uni-fav 优化 添加依赖 uni-icons, 导入后自动下载依赖 +- uni-goods-nav 优化 添加依赖 uni-icons, 导入后自动下载依赖 +- uni-nav-bar 优化 添加依赖 uni-icons, 导入后自动下载依赖 +- uni-notice-bar 优化 添加依赖 uni-icons, 导入后自动下载依赖 +- uni-number-box 修复 uni-number-box 浮点数运算不精确的 bug +- uni-number-box 修复 uni-number-box change 事件触发不正确的 bug +- uni-number-box 新增 uni-number-box v-model 双向绑定 +- uni-rate 修复 布局变化后 uni-rate 星星计算不准确的 bug +- uni-rate 优化 添加依赖 uni-icons, 导入 uni-rate 自动下载依赖 +- uni-search-bar 优化 添加依赖 uni-icons, 导入后自动下载依赖 +- uni-steps 优化 添加依赖 uni-icons, 导入后自动下载依赖 +- uni-transition 新增 通过方法自定义动画 +- uni-transition 新增 custom-class 非 NVUE 平台支持自定义 class 定制样式 +- uni-transition 优化 动画触发逻辑,使动画更流畅 +- uni-transition 优化 支持单独的动画类型 +- uni-transition 优化 文档示例 +## 1.2.13(2021-04-16) +- uni-ui 新增 uni-data-picker 支持云端非树形表结构数据 +- uni-ui 修复 uni-data-checkbox nvue 下无法选中的问题 +- uni-ui 修复 uni-data-picker 根节点 parent_field 字段等于null时选择界面错乱问题 +- uni-ui 修复 uni-file-picker 选择的文件非 file-extname 字段指定的扩展名报错的Bug +- uni-ui 修复 uni-swipe-action 报错 nv_navigator is not defined 的bug +- uni-ui 修复 uni-load-more 在首页使用时,h5 平台报 'uni is not defined' 的 bug +- uni-ui 优化 uni-file-picker file-extname 字段支持字符串写法,多个扩展名需要用逗号分隔 +- uni-ui 优化 uni-pagination PC 和 移动端适配不同的 ui +- uni-ui 更新 uni-file-picker 组件示例 +- uni-ui 修复 uni-nav-bar 当 fixed 属性为 true 时铺不满屏幕的 bug +- uni-ui 新增 uni-search-bar 的 focus 事件 +- uni-ui 修复 uni-rate 属性 margin 值为 string 组件失效的 bug +- uni-data-picker 修复 本地数据概率无法回显时问题 +- uni-table 新增 sortable 属性,是否开启单列排序 +- uni-table 优化 表格多选逻辑 +## 1.2.12(2021-03-23) +- uni-ui 新增 uni-datetime-picker 的 hide-second 属性、border 属性; +- uni-ui 修复 uni-datetime-picker 选择跟显示的日期不一样的 bug, +- uni-ui 修复 uni-datetime-picker change事件触发2次的 bug +- uni-ui 修复 uni-datetime-picker 分、秒 end 范围错误的 bug +- uni-ui 新增 uni-tr selectable 属性,用于 type=selection 时,设置某行是否可由全选按钮控制 +- uni-ui 新增 uni-data-checkbox 新增 disabled属性,支持nvue +- uni-ui 优化 uni-data-checkbox 无选项时提示“暂无数据” +- uni-ui 优化 uni-data-checkbox 默认颜色显示 +- uni-ui 新增 uni-link href 属性支持 tel:|mailto: +- uni-ui 新增 uni-table 示例demo +- uni-ui 修复 uni-data-picker 微信小程序某些情况下无法选择的问题,事件无法触发的问题 +- uni-ui 修复 uni-nav-bar easycom 下,找不到 uni-status-bar 的bug +- uni-ui 修复 uni-easyinput 示例在 qq 小程序上的bug +- uni-ui 修复 uni-forms 动态显示uni-forms-item的情况下,submit 方法获取值错误的Bug +- uni-ui 调整 cli 项目 建议使用 easycom 方式引用组件,如使用按需引用,需手动维护组件内部引用 + +## 1.2.11(2021-02-24) +- 调整为uni_modules目录规范 +- uni-data-picker 新增 数据驱动的picker选择器 +- uni-file-picker 新增 文件选择上传 +- uni-row 新增 栅格系统 +- uni-data-checkbox 优化 支持 nvue +- uni-forms 修复 偶发性获取表单值错误的Bug +- uni-forms 修复 校验 uni-data-picker value 为 0 时,返回值错误的Bug +- uni-forms 修复 uni-forms-item 组件隐藏时依然触发校验的bug +- uni-forms 优化 实时校验 +- uni-forms 优化 兼容nvue页面 +- uni-easyinput 优化 兼容nvue页面 +- uni-group 优化 兼容nvue页面 +- uni-popup 优化 组件适配 PC +- uni-fab 优化 适配 PC +- uni-swiper-dot 优化 适配 PC +- uni-rate 优化 适配 PC +- uni-notice-bar 优化 适配 PC +- uni-indexed-list 优化 适配 PC +- uni-combox 优化 适配 PC +- uni-transition 优化 适配 PC +- uni-nav-bar 优化 适配 PC +- uni-swipe-action 优化 适配 PC diff --git a/uni_modules/uni-ui/components/uni-ui/uni-ui.vue b/uni_modules/uni-ui/components/uni-ui/uni-ui.vue new file mode 100644 index 0000000..0970892 --- /dev/null +++ b/uni_modules/uni-ui/components/uni-ui/uni-ui.vue @@ -0,0 +1,7 @@ + + + diff --git a/uni_modules/uni-ui/package.json b/uni_modules/uni-ui/package.json new file mode 100644 index 0000000..e860d58 --- /dev/null +++ b/uni_modules/uni-ui/package.json @@ -0,0 +1,128 @@ +{ + "id": "uni-ui", + "displayName": "uni-ui", + "version": "1.4.14", + "description": "uni-ui 是基于uni-app的、全端兼容的、高性能UI框架", + "keywords": [ + "uni-ui", + "uniui", + "UI组件库", + "ui框架", + "ui库" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "^3.2.10" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-badge", + "uni-calendar", + "uni-card", + "uni-collapse", + "uni-combox", + "uni-countdown", + "uni-data-checkbox", + "uni-data-picker", + "uni-dateformat", + "uni-datetime-picker", + "uni-drawer", + "uni-easyinput", + "uni-fab", + "uni-fav", + "uni-file-picker", + "uni-forms", + "uni-goods-nav", + "uni-grid", + "uni-group", + "uni-icons", + "uni-indexed-list", + "uni-link", + "uni-list", + "uni-load-more", + "uni-nav-bar", + "uni-notice-bar", + "uni-number-box", + "uni-pagination", + "uni-popup", + "uni-rate", + "uni-row", + "uni-search-bar", + "uni-segmented-control", + "uni-steps", + "uni-swipe-action", + "uni-swiper-dot", + "uni-table", + "uni-tag", + "uni-title", + "uni-transition" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "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" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-ui/readme.md b/uni_modules/uni-ui/readme.md new file mode 100644 index 0000000..5541b22 --- /dev/null +++ b/uni_modules/uni-ui/readme.md @@ -0,0 +1,248 @@ +> 当前插件不包含示例页面 ,如需示例请在 HBuiderX 中新建 `hello uni-app > 扩展组件` 中查看 +> +> 代码示例地址 :[https://ext.dcloud.net.cn/plugin?id=4941](https://ext.dcloud.net.cn/plugin?id=4941) +> +> 组件演示地址:[https://hellouniapp.dcloud.net.cn](https://hellouniapp.dcloud.net.cn/pages/extUI/badge/badge) +> +> 组件文档地址:[https://uniapp.dcloud.io/component/uniui/uni-ui](https://uniapp.dcloud.io/component/uniui/uni-ui) + +# uni-ui 介绍 + +## uni-ui产品特点 + +### 1. 高性能 + +目前为止,在小程序和混合app领域,暂时还没有比 `uni-ui` 更高性能的框架。 +- 自动差量更新数据 + +虽然uni-app支持小程序自定义组件,所有小程序的ui库都可以用。但小程序自定义组件的ui库都需要使用setData手动更新数据,在大数据量时、或高频更新数据时,很容易产生性能问题。 + +而 `uni-ui` 属于vue组件,uni-app引擎底层自动diff更新数据。当然其实插件市场里众多vue组件都具备这个特点。 +- 优化逻辑层和视图层通讯折损 + +非H5,不管是小程序还是App,不管是app的webview渲染还是原生渲染,全都是逻辑层和视图层分离的。这里就有一个逻辑层和视图层通讯的折损问题。 +比如在视图层拖动一个可跟手的组件,由于通讯的损耗,用js监听很难做到实时跟手。 + +这时就需要使用css动画以及平台底层提供的wxs、bindingx等技术。不过这些技术都比较复杂,所以 `uni-ui` 里做了封装,在需要跟手式操作的ui组件,比如swiperaction列表项左滑菜单,就在底层使用了这些技术,实现了高性能的交互体验 +- 背景停止 + +很多ui组件是会一直动的,比如轮播图、跑马灯。即便这个窗体被新窗体挡住,它在背景层仍然在消耗着硬件资源。在Android的webview版本为chrome66以上,背景操作ui会引发很严重的性能问题,造成前台界面明显卡顿。 + +而 `uni-ui` 的组件,会自动判断自己的显示状态,在组件不再可见时,不会再消耗硬件资源。 + +### 2. 全端 + + `uni-ui` 的组件都是多端自适应的,底层会抹平很多小程序平台的差异或bug。 + +比如导航栏navbar组件,会自动处理不同端的状态栏。 +比如swiperaction组件,在app和微信小程序上会使用交互体验更好的wxs技术,但在不支持wxs的其他小程序端会使用js模拟类似效果。 + + `uni-ui` 还支持nvue原生渲染,[详见](https://github.com/dcloudio/uni-ui/tree/nvue-uni-ui) + +未来 `uni-ui` 还会支持pc等大屏设备。 + +### 3. 与uni统计自动集成实现免打点 + +uni统计是优秀的多端统计平台,见[tongji.dcloud.net.cn](https://tongji.dcloud.net.cn)。 + +除了一张报表看全端,它的另一个重要特点是免打点。 +比如使用 `uni-ui` 的navbar标题栏、收藏、购物车等组件,均可实现自动打点,统计页面标题等各种行为数据。 +当然你也可以关闭uni统计,这不是强制的。 + +### 4. 主题扩展 + + `uni-ui` 支持[uni.scss](https://uniapp.dcloud.io/collocation/uni-scss),可以方便的切换App的风格。 + +ui是一种需求非常发散的产品,DCloud官方也无意用 `uni-ui` 压制第三方ui插件的空间,但官方有义务在性能和多端方面提供一个开源的标杆给大家。 + +我们欢迎更多优秀的ui组件出现,也欢迎更多人贡献 `uni-ui` 的主题风格,满足更多用户的需求。 + + +## 快速开始 + +uni-ui支持 HBuilderX直接新建项目模板、npm安装和单独导入个别组件等多种使用方式 + +### 在HBuilderX 新建uni-app项目的模板中,选择uni-ui模板 +![HBuilderX内创建uni-ui项目](https://img.cdn.aliyun.dcloud.net.cn/uni-app/doc/create-uni-ui-project.jpg) + +由于uni-app独特的[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)技术,可以免引用、注册,直接使用各种符合规则的vue组件。 + +在代码区键入`u`,拉出各种内置或uni-ui的组件列表,选择其中一个,即可使用该组件。 + +光标放在组件名称上,按F1,可以查阅组件的文档。 + +![uni-ui代码块](https://img.cdn.aliyun.dcloud.net.cn/uni-app/doc/uni-ui-snippet.jpg) + +### 通过 uni_modules 单独安装组件 +如果你没有创建uni-ui项目模板,也可以在你的工程里,通过 uni_modules 单独安装需要的某个组件。下表为uni-ui的扩展组件清单,点击每个组件在详情页面可以导入组件到项目下,导入后直接使用即可,无需import和注册。 + +|组件名|组件说明| +|---|---| +|uni-badge|[数字角标](https://ext.dcloud.net.cn/plugin?name=uni-badge)| +|uni-calendar|[日历](https://ext.dcloud.net.cn/plugin?name=uni-calendar)| +|uni-card|[卡片](https://ext.dcloud.net.cn/plugin?name=uni-card)| +|uni-collapse|[折叠面板](https://ext.dcloud.net.cn/plugin?name=uni-collapse)| +|uni-combox|[组合框](https://ext.dcloud.net.cn/plugin?name=uni-combox)| +|uni-countdown|[倒计时](https://ext.dcloud.net.cn/plugin?name=uni-countdown)| +|uni-data-checkbox|[数据选择器](https://ext.dcloud.net.cn/plugin?name=uni-data-checkbox)| +|uni-data-picker|[数据驱动的picker选择器](https://ext.dcloud.net.cn/plugin?name=uni-data-picker)| +|uni-dateformat|[日期格式化](https://ext.dcloud.net.cn/plugin?name=uni-dateformat)| +|uni-datetime-picker|[日期选择器](https://ext.dcloud.net.cn/plugin?name=uni-datetime-picker)| +|uni-drawer|[抽屉](https://ext.dcloud.net.cn/plugin?name=uni-drawer)| +|uni-easyinput|[增强输入框](https://ext.dcloud.net.cn/plugin?name=uni-easyinput)| +|uni-fab|[悬浮按钮](https://ext.dcloud.net.cn/plugin?name=uni-fab)| +|uni-fav|[收藏按钮](https://ext.dcloud.net.cn/plugin?name=uni-fav)| +|uni-file-picker|[文件选择上传](https://ext.dcloud.net.cn/plugin?name=uni-file-picker)| +|uni-forms|[表单](https://ext.dcloud.net.cn/plugin?name=uni-forms)| +|uni-goods-nav|[商品导航](https://ext.dcloud.net.cn/plugin?name=uni-goods-nav)| +|uni-grid|[宫格](https://ext.dcloud.net.cn/plugin?name=uni-grid)| +|uni-group|[分组](https://ext.dcloud.net.cn/plugin?name=uni-group)| +|uni-icons|[图标](https://ext.dcloud.net.cn/plugin?name=uni-icons)| +|uni-indexed-list|[索引列表](https://ext.dcloud.net.cn/plugin?name=uni-indexed-list)| +|uni-link|[超链接](https://ext.dcloud.net.cn/plugin?name=uni-link)| +|uni-list|[列表](https://ext.dcloud.net.cn/plugin?name=uni-list)| +|uni-load-more|[加载更多](https://ext.dcloud.net.cn/plugin?name=uni-load-more)| +|uni-nav-bar|[自定义导航栏](https://ext.dcloud.net.cn/plugin?name=uni-nav-bar)| +|uni-notice-bar|[通告栏](https://ext.dcloud.net.cn/plugin?name=uni-notice-bar)| +|uni-number-box|[数字输入框](https://ext.dcloud.net.cn/plugin?name=uni-number-box)| +|uni-pagination|[分页器](https://ext.dcloud.net.cn/plugin?name=uni-pagination)| +|uni-popup|[弹出层](https://ext.dcloud.net.cn/plugin?name=uni-popup)| +|uni-rate|[评分](https://ext.dcloud.net.cn/plugin?name=uni-rate)| +|uni-row|[布局-行](https://ext.dcloud.net.cn/plugin?name=uni-row)| +|uni-search-bar|[搜索栏](https://ext.dcloud.net.cn/plugin?name=uni-search-bar)| +|Section|[标题栏](https://ext.dcloud.net.cn/plugin?name=uni-section)| +|uni-segmented-control|[分段器](https://ext.dcloud.net.cn/plugin?name=uni-segmented-control)| +|uni-steps|[步骤条](https://ext.dcloud.net.cn/plugin?name=uni-steps)| +|uni-swipe-action|[滑动操作](https://ext.dcloud.net.cn/plugin?name=uni-swipe-action)| +|uni-swiper-dot|[轮播图指示点](https://ext.dcloud.net.cn/plugin?name=uni-swiper-dot)| +|uni-table|[表格](https://ext.dcloud.net.cn/plugin?name=uni-table)| +|uni-tag|[标签](https://ext.dcloud.net.cn/plugin?name=uni-tag)| +|uni-title|[章节标题](https://ext.dcloud.net.cn/plugin?name=uni-title)| +|uni-transition|[过渡动画](https://ext.dcloud.net.cn/plugin?name=uni-transition)| + + +使用 `uni_modules` 方式安装组件库,可以直接通过插件市场导入,通过右键菜单快速更新组件,不需要引用、注册,直接在页面中使用 `uni-ui` 组件。[点击安装 uni-ui 组件库](https://ext.dcloud.net.cn/plugin?id=55) + +**注意:下载最新的组件目前仅支持 uni_modules ,非 uni_modules 版本最高支持到组件的1.2.10版本** + +如不能升级到 `uni_modules` 版本,可以使用 `uni_modules` 安装好对应组件,将组件拷贝到对应目录。 + +例如需更新 `uni-list`和`uni-badge` ,将 `uni_modules>uni-list>components`和`uni_modules>uni-badege>components`下所有目录拷贝到如下目录即可: + + +**目录示例** + +```json +┌─components 组件目录 +│ ├─uni-list list 列表目录 +│ │ └─uni-list.vue list 组件文件 +│ ├─uni-list-item list-item 列表目录 +│ │ └─uni-list-item.vue list 组件文件 +│ ├─uni-badge badge 角标目录 +│ │ └─uni-badge.vue badge 组件文件 +│ └─ //.... 更多组件文件 +├─pages 业务页面文件存放的目录 +│ ├─index +│ │ └─index.vue index示例页面 +├─main.js Vue初始化入口文件 +├─App.vue 应用配置,用来配置App全局样式以及监听 应用生命周期 +├─manifest.json 配置应用名称、appid、logo、版本等打包信息,详见 +└─pages.json 配置页 + +``` + +### 通过 `uni_modules` 导入全部组件 +如果想一次把所有uni-ui组件导入到项目中,只需要导入一个 `uni-ui` 组件即可 [点击去导入](https://ext.dcloud.net.cn/plugin?id=55)。 + +如果没有自动导入其他组件,可以在 uni-ui 组件目录上右键选择 `安装三方插件依赖` 即可。 + + + +### npm安装 +在 `vue-cli` 项目中可以使用 `npm` 安装 `uni-ui` 库 ,或者直接在 `HBuilderX` 项目中使用 `npm` 。 + +> **注意** +> cli 项目默认是不编译 `node_modules` 下的组件的,导致条件编译等功能失效 ,导致组件异常 +> 需要在根目录创建 `vue.config.js` 文件 ,增加 `@dcloudio/uni-ui` 包的编译即可正常 +> ```javascript +> // vue.config.js +> module.exports = { +> transpileDependencies:['@dcloudio/uni-ui'] +> } +> ``` + + + +**准备 sass** + +`vue-cli` 项目请先安装 sass 及 sass-loader,如在 HBuliderX 中使用,可跳过此步。 + +- 安装 sass +``` + npm i sass -D 或 yarn add sass -D +``` + +- 安装 sass-loader +``` +npm i sass-loader@10.1.1 -D 或 yarn add sass-loader@10.1.1 -D +``` + +> 如果 `node` 版本小于 16 ,sass-loader 请使用低于 @11.0.0 的版本,[sass-loader@11.0.0 不支持 vue@2.6.12 ](https://stackoverflow.com/questions/66082397/typeerror-this-getoptions-is-not-a-function) +> 如果 `node` 版本大于 16 , `sass-loader` 建议使用 `v8.x` 版本 + +**安装 uni-ui** + +``` +npm i @dcloudio/uni-ui 或 yarn add @dcloudio/uni-ui +``` + + + +**配置easycom** + +使用 `npm` 安装好 `uni-ui` 之后,需要配置 `easycom` 规则,让 `npm` 安装的组件支持 `easycom` + +打开项目根目录下的 `pages.json` 并添加 `easycom` 节点: + +```javascript +// pages.json +{ + "easycom": { + "autoscan": true, + "custom": { + // uni-ui 规则如下配置 + "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue" + } + }, + + // 其他内容 + pages:[ + // ... + ] +} + +``` + +在 ``template`` 中使用组件: + +```html + + + +``` + + **注意** + - uni-ui 现在只推荐使用 `easycom` ,如自己引用组件,可能会出现组件找不到的问题 + - 使用 npm 安装的组件,默认情况下 babel-loader 会忽略所有 node_modules 中的文件 ,导致条件编译失效,需要通过配置 `vue.config.js` 解决: + ```javascript + // 在根目录创建 vue.config.js 文件,并配置如下 + module.exports = { + transpileDependencies: ['@dcloudio/uni-ui'] + } + ``` + - uni-ui 是uni-app内置组件的扩展。注意与web开发不同,uni-ui不包括基础组件,它是基础组件的补充。web开发中有的开发者习惯用一个ui库完成所有开发,但在uni-app体系中,推荐开发者首先使用性能更高的基础组件,然后按需引入必要的扩展组件。 + - `uni-ui` 不支持使用 `Vue.use()` 的方式安装 + + +### 贡献代码 +在使用 `uni-ui` 中,如遇到无法解决的问题,请提 [Issues](https://github.com/dcloudio/uni-ui/issues) 给我们,假如您有更好的点子或更好的实现方式,也欢迎给我们提交 [PR](https://github.com/dcloudio/uni-ui/pulls) \ No newline at end of file