commit 8dcee4faddec53ed5a6275150f1e00a3c8668740 Author: luojie Date: Mon Feb 23 16:31:39 2026 +0800 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7d1a9ef --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +unpackage/ +**/node_modules/ +node_modules diff --git a/.hbuilderx/launch.json b/.hbuilderx/launch.json new file mode 100644 index 0000000..ee5be77 --- /dev/null +++ b/.hbuilderx/launch.json @@ -0,0 +1,20 @@ +{ // 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": [{ + "app-plus" : + { + "launchtype" : "local" + }, + "default" : + { + "launchtype" : "local" + }, + "mp-weixin" : + { + "launchtype" : "local" + }, + "type" : "uniCloud" + } + ] +} diff --git a/App.vue b/App.vue new file mode 100644 index 0000000..a981323 --- /dev/null +++ b/App.vue @@ -0,0 +1,18 @@ + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8e39ead --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 www.uviewui.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..06d5676 --- /dev/null +++ b/README.md @@ -0,0 +1,106 @@ +

+ logo +

+

uView

+

多平台快速开发的UI框架

+ + +## 说明 + +uView UI,是[uni-app](https://uniapp.dcloud.io/)生态优秀的UI框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水 + +## 特性 + +- 兼容安卓,iOS,微信小程序,H5,QQ小程序,百度小程序,支付宝小程序,头条小程序 +- 60+精选组件,功能丰富,多端兼容,让您快速集成,开箱即用 +- 众多贴心的JS利器,让您飞镖在手,召之即来,百步穿杨 +- 众多的常用页面和布局,让您专注逻辑,事半功倍 +- 详尽的文档支持,现代化的演示效果 +- 按需引入,精简打包体积 + + +## 安装 + +```bash +# npm方式安装 +npm i uview-ui +``` + +## 快速上手 + +1. `main.js`引入uView库 +```js +// main.js +import uView from 'uview-ui'; +Vue.use(uView); +``` + +2. `App.vue`引入基础样式(注意style标签需声明scss属性支持) +```css +/* App.vue */ + +``` + +3. `uni.scss`引入全局scss变量文件 +```css +/* uni.scss */ +@import "uview-ui/theme.scss"; +``` + +4. `pages.json`配置easycom规则(按需引入) + +```js +// pages.json +{ + "easycom": { + // npm安装的方式不需要前面的"@/",下载安装的方式需要"@/" + // npm安装方式 + "^u-(.*)": "uview-ui/components/u-$1/u-$1.vue" + // 下载安装方式 + // "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue" + }, + // 此为本身已有的内容 + "pages": [ + // ...... + ] +} +``` + +请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容 + +## 使用方法 +配置easycom规则后,自动按需引入,无需`import`组件,直接引用即可。 + +```html + +``` + +请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容 + +## 链接 + +- [官方文档](https://uviewui.com/) +- [更新日志](https://uviewui.com/components/changelog.html) +- [升级指南](https://uviewui.com/components/changelog.html) +- [关于我们](https://uviewui.com/cooperation/about.html) + +## 预览 + +您可以通过**微信**扫码,查看最佳的演示效果。 +
+
+ + + +## 版权信息 +uView遵循[MIT](https://en.wikipedia.org/wiki/MIT_License)开源协议,意味着您无需支付任何费用,也无需授权,即可将uView应用到您的产品中。 diff --git a/components/hjb-upload/README.md b/components/hjb-upload/README.md new file mode 100644 index 0000000..4ce1e08 --- /dev/null +++ b/components/hjb-upload/README.md @@ -0,0 +1,52 @@ +### 使用说明 + +拷贝该组件到 components 目录下之后 +在 script 中引用组件 + +```js +import hjbUpload from "@/components/hjb-upload/hjb-upload.vue"; +export default { + components: { hjbUpload }, +}; +``` + +在 template 中使用组件: + +```html + + + + +``` + +### 组件参数说明 + +| 参数 | 说明 | 类型 | 默认值 | +| ------------- | ------------------------------------------------------------------------------------------------------- | ---------------------------------- | ------ | +| action | 必选参数,上传的地址 | string | — | +| headers | 设置上传的请求头部 | object | — | +| multiple | 是否支持多选文件 | boolean | false | +| formData | 上传时附带的额外参数 | object | — | +| name | 上传的文件字段名 | string | file | +| fileType | 接受上传的文件类型,例如: ['png'] | array | [] | +| on-preview | 点击文件列表中已上传的文件时的钩子 | function(file) | — | +| on-remove | 文件列表移除文件时的钩子 | function(file, fileList) | — | +| on-success | 文件上传成功时的钩子 | function(response, file, fileList) | — | +| on-error | 文件上传失败时的钩子 | function(err, file, fileList) | — | +| on-progress | 文件上传时的钩子 | function(event, file, fileList) | — | +| on-change | 文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用 | function(file, fileList) | — | +| before-upload | 上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。 | function(file) | — | +| before-remove | 删除文件之前的钩子,参数为上传的文件和文件列表,若返回 false 或者返回 Promise 且被 reject,则停止删除。 | function(file, fileList) | — | +| auto-upload | 是否在选取文件后立即进行上传 | boolean | true | +| file-list | 上传的文件列表, 例如: [{name: 'food.jpg', url: 'https://xxx.cdn.com/xxx.jpg'}] | array | [] | +| http-request | 覆盖默认的上传行为,可以自定义上传的实现 | function | — | +| disabled | 是否禁用 | boolean | false | +| limit | 最大允许上传个数 | number | 10 | diff --git a/components/hjb-upload/hjb-upload.vue b/components/hjb-upload/hjb-upload.vue new file mode 100644 index 0000000..bd06e94 --- /dev/null +++ b/components/hjb-upload/hjb-upload.vue @@ -0,0 +1,599 @@ + + + + + diff --git a/components/hjb-upload/package.json b/components/hjb-upload/package.json new file mode 100644 index 0000000..0f0142d --- /dev/null +++ b/components/hjb-upload/package.json @@ -0,0 +1,4 @@ +{ + "name": "hjb-upload", + "version": "1.0.3" +} diff --git a/components/z-paging-cell/z-paging-cell.vue b/components/z-paging-cell/z-paging-cell.vue new file mode 100644 index 0000000..e9aca70 --- /dev/null +++ b/components/z-paging-cell/z-paging-cell.vue @@ -0,0 +1,34 @@ + + + + + + + + + + diff --git a/components/z-paging-empty-view/z-paging-empty-view.vue b/components/z-paging-empty-view/z-paging-empty-view.vue new file mode 100644 index 0000000..f1b02ad --- /dev/null +++ b/components/z-paging-empty-view/z-paging-empty-view.vue @@ -0,0 +1,160 @@ + + + + + + + + + + + diff --git a/components/z-paging-swiper-item/z-paging-swiper-item.vue b/components/z-paging-swiper-item/z-paging-swiper-item.vue new file mode 100644 index 0000000..707b5e9 --- /dev/null +++ b/components/z-paging-swiper-item/z-paging-swiper-item.vue @@ -0,0 +1,145 @@ + + + + + + + + + + + diff --git a/components/z-paging-swiper/z-paging-swiper.vue b/components/z-paging-swiper/z-paging-swiper.vue new file mode 100644 index 0000000..cf2a22f --- /dev/null +++ b/components/z-paging-swiper/z-paging-swiper.vue @@ -0,0 +1,221 @@ + + + + + + + + + + + diff --git a/components/z-paging/components/z-paging-load-more.vue b/components/z-paging/components/z-paging-load-more.vue new file mode 100644 index 0000000..80b70b9 --- /dev/null +++ b/components/z-paging/components/z-paging-load-more.vue @@ -0,0 +1,152 @@ + + + + + + diff --git a/components/z-paging/components/z-paging-refresh.vue b/components/z-paging/components/z-paging-refresh.vue new file mode 100644 index 0000000..4d0eeed --- /dev/null +++ b/components/z-paging/components/z-paging-refresh.vue @@ -0,0 +1,273 @@ + + + + + + diff --git a/components/z-paging/config/index.js b/components/z-paging/config/index.js new file mode 100644 index 0000000..15a37e2 --- /dev/null +++ b/components/z-paging/config/index.js @@ -0,0 +1,3 @@ +// z-paging全局配置文件,注意避免更新时此文件被覆盖,若被覆盖,可在此文件中右键->点击本地历史记录,找回覆盖前的配置 + +export default {} \ No newline at end of file diff --git a/components/z-paging/css/z-paging-main.css b/components/z-paging/css/z-paging-main.css new file mode 100644 index 0000000..a12a458 --- /dev/null +++ b/components/z-paging/css/z-paging-main.css @@ -0,0 +1,227 @@ +/* [z-paging]公共css*/ + +.z-paging-content { + position: relative; + /* #ifndef APP-NVUE */ + display: flex; + width: 100%; + height: 100%; + overflow: hidden; + /* #endif */ + flex-direction: column; +} + +.z-paging-content-fixed, .zp-loading-fixed { + position: fixed; + /* #ifndef APP-NVUE */ + height: auto; + width: auto; + /* #endif */ + top: 0; + left: 0; + bottom: 0; + right: 0; +} + +.zp-page-top,.zp-page-bottom { + /* #ifndef APP-NVUE */ + width: auto; + /* #endif */ + position: fixed; + left: 0; + right: 0; + z-index: 999; +} + +.zp-page-left,.zp-page-right{ + /* #ifndef APP-NVUE */ + height: 100%; + /* #endif */ +} + +.zp-scroll-view-super { + flex: 1; + position: relative; +} + +.zp-view-super{ + /* #ifndef APP-NVUE */ + display: flex; + /* #endif */ + flex-direction: row; +} + +.zp-custom-refresher-container { + overflow: hidden; +} + +.zp-scroll-view-container,.zp-scroll-view { + position: relative; + /* #ifndef APP-NVUE */ + height: 100%; + width: 100%; + /* #endif */ +} + +.zp-absoulte{ + /* #ifndef APP-NVUE */ + position: absolute; + top: 0; + width: auto; + /* #endif */ +} + +.zp-right{ + right: 0; +} + +.zp-scroll-view-absolute { + position: absolute; + top: 0; + left: 0; +} + +/* #ifndef APP-NVUE */ +.zp-scroll-view-hide-scrollbar ::-webkit-scrollbar { + display: none; + -webkit-appearance: none; + width: 0 !important; + height: 0 !important; + background: transparent; +} +/* #endif */ + +.zp-paging-touch-view { + width: 100%; + height: 100%; + position: relative; +} + +.zp-fixed-bac-view { + position: absolute; + width: 100%; + top: 0; + left: 0; + height: 200px; +} + +.zp-paging-main { + height: 100%; + /* #ifndef APP-NVUE */ + display: flex; + /* #endif */ + flex-direction: column; +} + +.zp-paging-container { + flex: 1; + position: relative; + /* #ifndef APP-NVUE */ + display: flex; + /* #endif */ + flex-direction: column; +} + +.zp-chat-record-loading-container { + /* #ifndef APP-NVUE */ + display: flex; + width: 100%; + /* #endif */ + /* #ifdef APP-NVUE */ + width: 750rpx; + /* #endif */ + align-items: center; + justify-content: center; + height: 60rpx; + font-size: 26rpx; +} + +.zp-chat-record-loading-custom-image { + width: 35rpx; + height: 35rpx; + /* #ifndef APP-NVUE */ + animation: loading-flower 1s linear infinite; + /* #endif */ +} + +.zp-custom-refresher-container { + /* #ifndef APP-NVUE */ + display: flex; + /* #endif */ + flex-direction: row; + justify-content: center; + align-items: center; +} + +.zp-back-to-top { + width: 76rpx; + height: 76rpx; + z-index: 999; + position: absolute; + bottom: 0rpx; + right: 25rpx; + transition-duration: .3s; + transition-property: opacity; +} + +.zp-back-to-top-show { + opacity: 1; +} + +.zp-back-to-top-hide { + opacity: 0; +} + +.zp-back-to-top-img { + /* #ifndef APP-NVUE */ + width: 100%; + height: 100%; + /* #endif */ + /* #ifdef APP-NVUE */ + flex: 1; + /* #endif */ + z-index: 999; +} + +.zp-empty-view { + /* #ifdef APP-NVUE */ + height: 100%; + /* #endif */ + flex: 1; +} + +.zp-empty-view-center { + /* #ifndef APP-NVUE */ + display: flex; + /* #endif */ + flex-direction: column; + align-items: center; + justify-content: center; +} + +.zp-loading-fixed { + z-index: 9999; +} + +.zp-safe-area-inset-bottom { + position: absolute; + /* #ifndef APP-PLUS */ + height: env(safe-area-inset-bottom); + /* #endif */ +} + +.zp-n-refresh-container { + /* #ifndef APP-NVUE */ + display: flex; + /* #endif */ + justify-content: center; + width: 750rpx; +} + +.zp-n-list-container{ + /* #ifndef APP-NVUE */ + display: flex; + /* #endif */ + flex-direction: row; + flex: 1; +} diff --git a/components/z-paging/css/z-paging-static.css b/components/z-paging/css/z-paging-static.css new file mode 100644 index 0000000..eaad977 --- /dev/null +++ b/components/z-paging/css/z-paging-static.css @@ -0,0 +1,35 @@ +/* [z-paging]公用的静态css资源 */ + +.zp-line-loading-image { + margin-right: 8rpx; + width: 28rpx; + height: 28rpx; + /* #ifndef APP-NVUE */ + animation: loading-flower 1s steps(12) infinite; + /* #endif */ + color: #666666; +} + +.zp-loading-image-ios{ + width: 20px; + height: 20px; +} + +.zp-loading-image-android{ + width: 32rpx; + height: 32rpx; +} + +/* #ifndef APP-NVUE */ +@keyframes loading-flower { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + to { + -webkit-transform: rotate(1turn); + transform: rotate(1turn); + } +} +/* #endif */ + diff --git a/components/z-paging/js/modules/back-to-top.js b/components/z-paging/js/modules/back-to-top.js new file mode 100644 index 0000000..c14d096 --- /dev/null +++ b/components/z-paging/js/modules/back-to-top.js @@ -0,0 +1,108 @@ +// [z-paging]点击返回顶部view模块 +import u from '.././z-paging-utils' + +const ZPBackToTop = { + props: { + //自动显示点击返回顶部按钮,默认为否 + autoShowBackToTop: { + type: Boolean, + default: u.gc('autoShowBackToTop', false) + }, + //点击返回顶部按钮显示/隐藏的阈值(滚动距离),单位为px,默认为400rpx + backToTopThreshold: { + type: [Number, String], + default: u.gc('backToTopThreshold', '400rpx') + }, + //点击返回顶部按钮的自定义图片地址,默认使用z-paging内置的图片 + backToTopImg: { + type: String, + default: u.gc('backToTopImg', '') + }, + //点击返回顶部按钮返回到顶部时是否展示过渡动画,默认为是 + backToTopWithAnimate: { + type: Boolean, + default: u.gc('backToTopWithAnimate', true) + }, + //点击返回顶部按钮与底部的距离,注意添加单位px或rpx,默认为160rpx + backToTopBottom: { + type: [Number, String], + default: u.gc('backToTopBottom', '160rpx') + }, + //点击返回顶部按钮的自定义样式 + backToTopStyle: { + type: Object, + default: function() { + return u.gc('backToTopStyle', {}); + }, + }, + //iOS点击顶部状态栏、安卓双击标题栏时,滚动条返回顶部,只支持竖向,默认为是 + enableBackToTop: { + type: Boolean, + default: u.gc('enableBackToTop', true) + }, + }, + data() { + return { + backToTopClass: 'zp-back-to-top zp-back-to-top-hide', + lastBackToTopShowTime: 0, + showBackToTopClass: false, + } + }, + computed: { + finalEnableBackToTop() { + return this.usePageScroll ? false : this.enableBackToTop; + }, + finalBackToTopThreshold() { + return u.convertTextToPx(this.backToTopThreshold); + }, + finalBackToTopStyle() { + let tempBackToTopStyle = this.backToTopStyle; + if (!tempBackToTopStyle.bottom) { + tempBackToTopStyle.bottom = this.windowBottom + u.convertTextToPx(this.backToTopBottom) + 'px'; + } + if(!tempBackToTopStyle.position){ + tempBackToTopStyle.position = this.usePageScroll ? 'fixed': 'absolute'; + } + return tempBackToTopStyle; + }, + }, + methods: { + //点击返回顶部 + _backToTopClick() { + !this.backToTopWithAnimate && this._checkShouldShowBackToTop(1, 0); + this.scrollToTop(this.backToTopWithAnimate); + }, + //判断是否要显示返回顶部按钮 + _checkShouldShowBackToTop(newVal, oldVal) { + if (!this.autoShowBackToTop) { + this.showBackToTopClass = false; + return; + } + if (newVal !== oldVal) { + if (newVal > this.finalBackToTopThreshold) { + if (!this.showBackToTopClass) { + this.showBackToTopClass = true; + this.lastBackToTopShowTime = new Date().getTime(); + setTimeout(() => { + this.backToTopClass = 'zp-back-to-top zp-back-to-top-show'; + }, 300) + } + } else { + if (this.showBackToTopClass) { + const currentTime = new Date().getTime(); + let dalayTime = 300; + if(currentTime - this.lastBackToTopShowTime < 500){ + dalayTime = 0; + } + this.backToTopClass = 'zp-back-to-top zp-back-to-top-hide'; + setTimeout(() => { + this.showBackToTopClass = false; + }, dalayTime) + } + } + } + }, + } +} + +export default ZPBackToTop; diff --git a/components/z-paging/js/modules/data-handle.js b/components/z-paging/js/modules/data-handle.js new file mode 100644 index 0000000..f7054cc --- /dev/null +++ b/components/z-paging/js/modules/data-handle.js @@ -0,0 +1,732 @@ +// [z-paging]数据处理模块 +import u from '.././z-paging-utils' +import c from '.././z-paging-constant' +import Enum from '.././z-paging-enum' +import interceptor from '../z-paging-interceptor' + +const ZPData = { + props: { + //自定义初始的pageNo,默认为1 + defaultPageNo: { + type: [Number, String], + default: u.gc('defaultPageNo', 1), + observer: function(newVal, oldVal) { + this.pageNo = newVal; + }, + }, + //自定义pageSize,默认为10 + defaultPageSize: { + type: [Number, String], + default: u.gc('defaultPageSize', 10), + validator: (value) => { + if(value <= 0) u.consoleErr('default-page-size必须大于0!'); + return value > 0; + } + }, + //为保证数据一致,设置当前tab切换时的标识key,并在complete中传递相同key,若二者不一致,则complete将不会生效 + dataKey: { + type: [Number, String, Object], + default: function() { + return u.gc('dataKey', null); + }, + }, + //自动注入的list名,可自动修改父view(包含ref="paging")中对应name的list值 + autowireListName: { + type: String, + default: function() { + return u.gc('autowireListName', ''); + }, + }, + //自动注入的query名,可自动调用父view(包含ref="paging")中的query方法 + autowireQueryName: { + type: String, + default: function() { + return u.gc('autowireQueryName', ''); + }, + }, + //z-paging mounted后自动调用reload方法(mounted后自动调用接口),默认为是。请使用简便写法:auto + mountedAutoCallReload: { + type: Boolean, + default: u.gc('mountedAutoCallReload', true) + }, + //z-paging mounted后自动调用reload方法(mounted后自动调用接口),默认为是 + auto: { + type: Boolean, + default: u.gc('auto', true) + }, + //用户下拉刷新时是否触发reload方法,默认为是 + reloadWhenRefresh: { + type: Boolean, + default: u.gc('reloadWhenRefresh', true) + }, + //reload时自动滚动到顶部,默认为是 + autoScrollToTopWhenReload: { + type: Boolean, + default: u.gc('autoScrollToTopWhenReload', true) + }, + //reload时立即自动清空原list,默认为是,若立即自动清空,则在reload之后、请求回调之前页面是空白的 + autoCleanListWhenReload: { + type: Boolean, + default: u.gc('autoCleanListWhenReload', true) + }, + //列表刷新时自动显示下拉刷新view,默认为否 + showRefresherWhenReload: { + type: Boolean, + default: u.gc('showRefresherWhenReload', false) + }, + //列表刷新时自动显示加载更多view,且为加载中状态,默认为否 + showLoadingMoreWhenReload: { + type: Boolean, + default: u.gc('showLoadingMoreWhenReload', false) + }, + //组件created时立即触发reload(可解决一些情况下先看到页面再看到loading的问题),auto为true时有效。为否时将在mounted+nextTick后触发reload,默认为否 + createdReload: { + type: Boolean, + default: u.gc('createdReload', false) + }, + //本地分页时上拉加载更多延迟时间,单位为毫秒,默认200毫秒 + localPagingLoadingTime: { + type: [Number, String], + default: u.gc('localPagingLoadingTime', 200) + }, + //当分页未满一屏时,是否自动加载更多,默认为否(nvue无效) + insideMore: { + type: Boolean, + default: u.gc('insideMore', false) + }, + //使用聊天记录模式,默认为否 + useChatRecordMode: { + type: Boolean, + default: u.gc('useChatRecordMode', false) + }, + //自动拼接complete中传过来的数组(使用聊天记录模式时无效) + concat: { + type: Boolean, + default: u.gc('concat', true) + }, + //父组件v-model所绑定的list的值 + value: { + type: Array, + default: function() { + return []; + } + }, + // #ifdef VUE3 + modelValue: { + type: Array, + default: function() { + return []; + } + } + // #endif + }, + data (){ + return { + currentData: [], + totalData: [], + realTotalData: [], + totalLocalPagingList: [], + pageNo: 1, + isLocalPaging: false, + isAddedData: false, + isTotalChangeFromAddData: false, + privateConcat: true, + myParentQuery: -1, + firstPageLoaded: false, + pagingLoaded: false, + loaded: false, + isUserReload: true, + fromEmptyViewReload: false, + listRendering: false + } + }, + computed: { + pageSize() { + return this.defaultPageSize; + }, + finalConcat() { + return this.concat && this.privateConcat; + }, + isFirstPage() { + return this.pageNo === this.defaultPageNo; + } + }, + watch: { + totalData(newVal, oldVal) { + this._totalDataChange(newVal, oldVal); + }, + currentData(newVal, oldVal) { + this._currentDataChange(newVal, oldVal); + }, + useChatRecordMode(newVal, oldVal) { + if (newVal) { + this.nLoadingMoreFixedHeight = false; + } + }, + value: { + handler(newVal) { + this.realTotalData = newVal; + }, + immediate: true + }, + // #ifdef VUE3 + modelValue: { + handler(newVal) { + this.realTotalData = newVal; + }, + immediate: true + } + // #endif + }, + methods: { + //请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为是否成功(默认是是) + complete(data, success = true) { + this.customNoMore = -1; + this.addData(data, success); + }, + //简写,与complete完全相同 + end(data, success = true) { + this.complete(data, success); + }, + //【保证数据一致】请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为dataKey,需与:data-key绑定的一致,第三个参数为是否成功(默认为是) + completeByKey(data, dataKey = null, success = true) { + if (dataKey !== null && this.dataKey !== null && dataKey !== this.dataKey) { + if (this.isFirstPage) { + this.endRefresh(); + } + return; + } + this.customNoMore = -1; + this.addData(data, success); + }, + //简写,与completeByKey完全相同 + endByKey(data, dataKey = null, success = true) { + this.completeByKey(data, dataKey, success); + }, + //【通过totalCount判断是否有更多数据】请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为totalCount(列表总数),第三个参数为是否成功(默认为是) + completeByTotalCount(data, totalCount, success = true) { + if (totalCount == 'undefined') { + this.customNoMore = -1; + } else { + let dataTypeRes = this._checkDataType(data, success, false); + data = dataTypeRes.data; + success = dataTypeRes.success; + if (totalCount >= 0 && success) { + this.$nextTick(() => { + let nomore = true; + let realTotalDataCount = this.realTotalData.length; + if (this.pageNo == this.defaultPageNo) { + realTotalDataCount = 0; + } + let exceedCount = realTotalDataCount + data.length - totalCount; + if (exceedCount >= 0) { + nomore = false; + exceedCount = this.defaultPageSize - exceedCount; + if (exceedCount > 0 && exceedCount < data.length) { + data = data.splice(0, exceedCount); + } + } + this.completeByNoMore(data, nomore, success); + }) + return; + } + } + this.addData(data, success); + }, + //简写,与completeByTotalCount完全相同 + completeByTotal(data, totalCount, success = true) { + this.completeByTotalCount(data, totalCount, success); + }, + //简写,与completeByTotalCount完全相同 + endByTotalCount(data, totalCount, success = true) { + this.completeByTotalCount(data, totalCount, success); + }, + //简写,与completeByTotalCount完全相同 + endByTotal(data, totalCount, success = true) { + this.completeByTotalCount(data, totalCount, success); + }, + //【自行判断是否有更多数据】请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为是否有更多数据,第三个参数为是否成功(默认是是) + completeByNoMore(data, nomore, success = true) { + if (nomore != 'undefined') { + this.customNoMore = nomore == true ? 1 : 0; + } + this.addData(data, success); + }, + //简写,与completeByNoMore完全相同 + endByNoMore(data, nomore, success = true) { + this.completeByNoMore(data, nomore, success); + }, + //与上方complete方法功能一致,新版本中设置服务端回调数组请使用complete方法 + addData(data, success = true) { + if (!this.fromCompleteEmit) { + this.disabledCompleteEmit = true; + this.fromCompleteEmit = false; + } + const currentTimeStamp = u.getTime(); + let addDataDalay = 0; + const disTime = currentTimeStamp - this.requestTimeStamp; + let minDelay = this.minDelay; + if(this.isFirstPage && this.finalShowRefresherWhenReload){ + minDelay = Math.max(400,minDelay); + } + if(this.requestTimeStamp > 0 && disTime < minDelay){ + addDataDalay = minDelay - disTime; + } + this.$nextTick(() => { + let delay = this.delay > 0 ? this.delay : addDataDalay; + setTimeout(() => { + this._addData(data, success, false); + }, delay) + }) + }, + //从顶部添加数据,不会影响分页的pageNo和pageSize + addDataFromTop(data, toTop = true, toTopWithAnimate = true) { + let dataType = Object.prototype.toString.call(data); + if (dataType !== '[object Array]') { + data = [data]; + } + this.totalData = [...data, ...this.totalData]; + if (toTop) { + setTimeout(() => { + this._scrollToTop(toTopWithAnimate); + }, c.delayTime) + } + }, + //重新设置列表数据,调用此方法不会影响pageNo和pageSize,也不会触发请求。适用场景:当需要删除列表中某一项时,将删除对应项后的数组通过此方法传递给z-paging。(当出现类似的需要修改列表数组的场景时,请使用此方法,请勿直接修改page中:list.sync绑定的数组) + resetTotalData(data) { + if (data == undefined) { + if (this.showConsoleError) { + u.consoleErr('方法resetTotalData参数缺失!'); + } + return; + } + this.isTotalChangeFromAddData = true; + let dataType = Object.prototype.toString.call(data); + if (dataType !== '[object Array]') { + data = [data]; + } + this.totalData = data; + }, + //添加聊天记录 + addChatRecordData(data, toBottom = true, toBottomWithAnimate = true) { + let dataType = Object.prototype.toString.call(data); + if (dataType !== '[object Array]') { + data = [data]; + } + if (!this.useChatRecordMode) return; + this.isTotalChangeFromAddData = true; + //#ifndef APP-NVUE + this.totalData = [...this.totalData, ...data]; + //#endif + //#ifdef APP-NVUE + this.totalData = this.nIsFirstPageAndNoMore ? [...this.totalData, ...data] : [...data, ...this.totalData]; + //#endif + if (toBottom) { + setTimeout(() => { + //#ifndef APP-NVUE + this._scrollToBottom(toBottomWithAnimate); + //#endif + //#ifdef APP-NVUE + if (this.nIsFirstPageAndNoMore) { + this._scrollToBottom(toBottomWithAnimate); + } else { + this._scrollToTop(toBottomWithAnimate); + } + //#endif + }, c.delayTime) + } + }, + //设置本地分页数据,请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging作分页处理(若调用了此方法,则上拉加载更多时内部会自动分页,不会触发@query所绑定的事件) + setLocalPaging(data, success = true) { + this.isLocalPaging = true; + this.$nextTick(() => { + this._addData(data, success, true); + }) + }, + //重新加载分页数据,pageNo会恢复为默认值,相当于下拉刷新的效果(animate为true时会展示下拉刷新动画,默认为false) + reload(animate = this.showRefresherWhenReload) { + if (animate) { + this.privateShowRefresherWhenReload = animate; + this.isUserPullDown = true; + } + this._preReload(animate, false); + }, + //刷新列表数据,pageNo和pageSize不会重置,列表数据会重新从服务端获取。必须保证@query绑定的方法中的pageNo和pageSize和传给服务端的一致 + refresh() { + if(!this.realTotalData.length){ + this.reload(); + return; + } + const disPageNo = this.pageNo - this.defaultPageNo + 1; + if (disPageNo >= 1) { + this.loading = true; + this.privateConcat = false; + const totalPageSize = disPageNo * this.pageSize; + this._emitQuery(this.defaultPageNo, totalPageSize, Enum.QueryFrom.Refresh); + this._callMyParentQuery(this.defaultPageNo, totalPageSize); + } + }, + //清空分页数据 + clean() { + this._reload(true); + this._addData([], true, false); + }, + //清空分页数据 + clear() { + this.clean(); + }, + //手动触发滚动到顶部加载更多,聊天记录模式时有效 + doChatRecordLoadMore() { + this.useChatRecordMode && this._onLoadingMore('click'); + }, + //reload之前的一些处理 + _preReload(animate = this.showRefresherWhenReload, isFromMounted = true) { + this.isUserReload = true; + this.loadingType = Enum.LoadingType.Refresher; + if (animate) { + this.privateShowRefresherWhenReload = animate; + // #ifndef APP-NVUE + if (this.useCustomRefresher) { + this._doRefresherRefreshAnimate(); + } else { + this.refresherTriggered = true; + } + // #endif + // #ifdef APP-NVUE + this.refresherStatus = Enum.Refresher.Loading; + this.refresherRevealStackCount++; + setTimeout(() => { + this._getNodeClientRect('zp-n-refresh-container', false).then((node) => { + if (node) { + let nodeHeight = node[0].height; + this.nShowRefresherReveal = true; + this.nShowRefresherRevealHeight = nodeHeight; + setTimeout(() => { + this._nDoRefresherEndAnimation(0, -nodeHeight, false, false); + setTimeout(() => { + this._nDoRefresherEndAnimation(nodeHeight, 0); + }, 10) + }, 10) + } + this._reload(false, isFromMounted); + this._doRefresherLoad(false); + }); + }, 10) + return; + // #endif + } else { + this._refresherEnd(false, false, false, false); + } + this._reload(false, isFromMounted); + }, + //重新加载分页数据 + _reload(isClean = false, isFromMounted = false, isUserPullDown = false) { + this.isAddedData = false; + this.cacheScrollNodeHeight = -1; + this.insideOfPaging = -1; + this.pageNo = this.defaultPageNo; + this._cleanRefresherEndTimeout(); + !this.privateShowRefresherWhenReload && !isClean && this._startLoading(true); + this.firstPageLoaded = true; + this.isTotalChangeFromAddData = false; + this.totalData = []; + if (!isClean) { + this._emitQuery(this.pageNo, this.defaultPageSize, isUserPullDown ? Enum.QueryFrom.UserPullDown : Enum.QueryFrom.Reload); + let delay = 0; + // #ifdef MP-TOUTIAO + delay = 5; + // #endif + setTimeout(() => { + this._callMyParentQuery(); + }, delay) + if (!isFromMounted && this.autoScrollToTopWhenReload) { + let checkedNRefresherLoading = true; + // #ifdef APP-NVUE + checkedNRefresherLoading = !this.nRefresherLoading; + // #endif + if (checkedNRefresherLoading) { + this._scrollToTop(false); + } + } + // #ifndef APP-NVUE + if (!this.usePageScroll && this.useChatRecordMode) { + if (this.showConsoleError) { + u.consoleWarn('使用聊天记录模式时,建议使用页面滚动,可将usePageScroll设置为true以启用页面滚动!!'); + } + } + // #endif + } + this.$nextTick(() => { + // #ifdef APP-NVUE + this.nShowBottom = this.realTotalData.length > 0; + // #endif + }) + }, + //处理服务端返回的数组 + _addData(data, success, isLocal) { + this.isAddedData = true; + this.fromEmptyViewReload = false; + this.isTotalChangeFromAddData = true; + this.refresherTriggered = false; + !this.useCustomRefresher && uni.stopPullDownRefresh(); + // #ifdef APP-NVUE + this.usePageScroll && uni.stopPullDownRefresh(); + // #endif + const tempIsUserPullDown = this.isUserPullDown; + if (this.showRefresherUpdateTime && this.isFirstPage) { + u.setRefesrherTime(u.getTime(), this.refresherUpdateTimeKey); + this.tempLanguageUpdateKey = u.getTime(); + this.$refs.refresh && this.$refs.refresh.updateTime(); + } + if (tempIsUserPullDown && this.isFirstPage) { + this.isUserPullDown = false; + } + let dataTypeRes = this._checkDataType(data, success, isLocal); + data = dataTypeRes.data; + success = dataTypeRes.success; + let delayTime = c.delayTime; + // #ifdef APP-NVUE + if (this.useChatRecordMode) delayTime = 0; + // #endif + this.loadingForNow = false; + setTimeout(() => { + this.pagingLoaded = true; + this.$nextTick(()=>{ + this._refresherEnd(delayTime > 0, true, tempIsUserPullDown); + }) + }, delayTime) + if (this.isFirstPage) { + this.isLoadFailed = !success; + } + if (success) { + if (!(this.privateConcat === false && this.loadingStatus === Enum.More.NoMore)) { + this.loadingStatus = Enum.More.Default; + } + if (isLocal) { + this.totalLocalPagingList = data; + this._localPagingQueryList(this.defaultPageNo, this.defaultPageSize, 0, (res) => { + this.complete(res); + }) + } else { + let dataChangeDelayTime = 0; + // #ifdef APP-NVUE + if (this.privateShowRefresherWhenReload && this.finalNvueListIs === 'waterfall') { + dataChangeDelayTime = 150; + } + // #endif + setTimeout(() => { + this._currentDataChange(data, this.currentData); + }, dataChangeDelayTime) + } + } else { + this._currentDataChange(data, this.currentData); + this.loadingStatus = Enum.More.Fail; + if (this.loadingType === Enum.LoadingType.LoadingMore) { + this.pageNo--; + } + } + }, + //所有数据改变时调用 + _totalDataChange(newVal, oldVal, eventThrow=true) { + if ((!this.isUserReload || !this.autoCleanListWhenReload) && this.firstPageLoaded && !newVal.length && oldVal.length) { + return; + } + this._doCheckScrollViewShouldFullHeight(newVal); + if(!this.realTotalData.length && !newVal.length){ + eventThrow = false; + } + this.realTotalData = newVal; + if (eventThrow) { + this.$emit('input', newVal); + // #ifdef VUE3 + this.$emit('update:modelValue', newVal); + // #endif + this.$emit('update:list', newVal); + this.$emit('listChange', newVal); + this._callMyParentList(newVal); + } + this.firstPageLoaded = false; + this.isTotalChangeFromAddData = false; + this.$nextTick(() => { + setTimeout(()=>{ + this._getNodeClientRect('.zp-paging-container-content').then((res) => { + if (res) { + this.$emit('contentHeightChanged', res[0].height); + } + }); + },this.isIos?100:300) + // #ifdef APP-NVUE + if (this.useChatRecordMode && this.nIsFirstPageAndNoMore && this.isFirstPage && !this.nFirstPageAndNoMoreChecked) { + this.nFirstPageAndNoMoreChecked = true; + this._scrollToBottom(false); + } + // #endif + }) + }, + //当前数据改变时调用 + _currentDataChange(newVal, oldVal) { + newVal = [...newVal]; + this.listRendering = true; + this.$nextTick(() => { + setTimeout(() => { + this.listRendering = false; + },50) + }) + // #ifndef APP-NVUE + if (this.finalUseVirtualList) { + this._setCellIndex(newVal,this.totalData.length === 0); + } + this.useChatRecordMode && newVal.reverse(); + // #endif + if (this.isFirstPage && this.finalConcat) { + this.totalData = []; + } + if (this.customNoMore !== -1) { + if (this.customNoMore === 0 || !newVal.length) { + this.loadingStatus = Enum.More.NoMore; + } + } else { + if (!newVal.length || (newVal.length && newVal.length < this.defaultPageSize)) { + this.loadingStatus = Enum.More.NoMore; + } + } + if (!this.totalData.length) { + if (this.finalConcat) { + // #ifdef APP-NVUE + if(this.useChatRecordMode && this.isFirstPage && this.loadingStatus === Enum.More.NoMore){ + newVal.reverse(); + } + // #endif + this.totalData = newVal; + } + if (this.useChatRecordMode) { + // #ifndef APP-NVUE + this.$nextTick(() => { + this._scrollToBottom(false); + }) + // #endif + } + } else { + if (this.useChatRecordMode) { + // #ifdef APP-NVUE + this.totalData = [...this.totalData, ...newVal]; + // #endif + //#ifndef APP-NVUE + const idIndex = newVal.length; + let idIndexStr = `z-paging-${idIndex}`; + this.totalData = [...newVal, ...this.totalData]; + if (this.pageNo !== this.defaultPageNo) { + this.privateScrollWithAnimation = 0; + let delayTime = 200; + this.$emit('update:chatIndex', idIndex); + setTimeout(() => { + this._scrollIntoView(idIndexStr, 30 + this.cacheTopHeight, false, () => { + this.$emit('update:chatIndex', 0); + }); + }, this.usePageScroll ? 0 : delayTime) + } else { + this.$nextTick(() => { + this._scrollToBottom(false); + }) + } + //#endif + + } else { + if (this.finalConcat) { + const currentScrollTop = this.oldScrollTop; + this.totalData = [...this.totalData, ...newVal]; + // #ifdef MP-WEIXIN + if (!this.isIos && !this.refresherOnly && !this.usePageScroll && newVal.length) { + this.loadingMoreTimeStamp = u.getTime(); + this.$nextTick(()=>{ + this.scrollToY(currentScrollTop); + }) + } + // #endif + } else { + this.totalData = newVal; + } + } + } + this.privateConcat = true; + }, + //本地分页请求 + _localPagingQueryList(pageNo, pageSize, localPagingLoadingTime, callback) { + pageNo = parseInt(pageNo); + pageSize = parseInt(pageSize); + if (pageNo < 0 || pageSize <= 0) { + this._localPagingQueryResult(callback, [], localPagingLoadingTime); + return; + } + pageNo = Math.max(1,pageNo); + let totalPagingList = [...this.totalLocalPagingList]; + let pageNoIndex = (pageNo - 1) * pageSize; + if (pageNoIndex + pageSize <= totalPagingList.length) { + this._localPagingQueryResult(callback, totalPagingList.splice(pageNoIndex, pageSize), localPagingLoadingTime); + } else if (pageNoIndex < totalPagingList.length) { + this._localPagingQueryResult(callback, totalPagingList.splice(pageNoIndex, totalPagingList.length - pageNoIndex), localPagingLoadingTime); + } else { + this._localPagingQueryResult(callback, [], localPagingLoadingTime); + } + }, + //本地分页请求回调 + _localPagingQueryResult(callback, arg, localPagingLoadingTime) { + setTimeout(() => { + callback(arg); + }, localPagingLoadingTime) + }, + //修改父view的list + _callMyParentList(newVal) { + if (this.autowireListName.length) { + const myParent = u.getParent(this.$parent); + if (myParent && myParent[this.autowireListName]) { + myParent[this.autowireListName] = newVal; + } + } + }, + //调用父view的query + _callMyParentQuery(customPageNo = 0, customPageSize = 0) { + if (this.autowireQueryName) { + if (this.myParentQuery === -1) { + const myParent = u.getParent(this.$parent); + if (myParent && myParent[this.autowireQueryName]) { + this.myParentQuery = myParent[this.autowireQueryName]; + } + } + if (this.myParentQuery !== -1) { + if (customPageSize > 0) { + this.myParentQuery(customPageNo, customPageSize); + } else { + this.myParentQuery(this.pageNo, this.defaultPageSize); + } + } + } + }, + //发射query事件 + _emitQuery(pageNo, pageSize, from){ + this.requestTimeStamp = u.getTime(); + this.$emit('query', ...interceptor._handleQuery(pageNo, pageSize, from)); + }, + //检查complete data的类型 + _checkDataType(data, success, isLocal) { + const dataType = Object.prototype.toString.call(data); + if (dataType === '[object Boolean]') { + success = data; + data = []; + } else if (dataType === '[object Null]') { + data = []; + } else if (dataType !== '[object Array]') { + data = []; + let methodStr = isLocal ? 'setLocalPaging' : 'complete'; + if (dataType !== '[object Undefined]') { + if (this.showConsoleError) { + u.consoleErr(`${methodStr}参数类型不正确,第一个参数类型必须为Array!`); + } + } + } + return {data,success}; + }, + } +} + +export default ZPData; diff --git a/components/z-paging/js/modules/empty.js b/components/z-paging/js/modules/empty.js new file mode 100644 index 0000000..c7466ce --- /dev/null +++ b/components/z-paging/js/modules/empty.js @@ -0,0 +1,150 @@ +// [z-paging]空数据图view模块 +import u from '.././z-paging-utils' + +const ZPEmptyView = { + props: { + //是否强制隐藏空数据图,默认为否 + hideEmptyView: { + type: Boolean, + default: u.gc('hideEmptyView', false) + }, + //空数据图描述文字,默认为“没有数据哦~” + emptyViewText: { + type: [String, Object], + default: u.gc('emptyViewText', null) + }, + //是否显示空数据图重新加载按钮(无数据时),默认为否 + showEmptyViewReload: { + type: Boolean, + default: u.gc('showEmptyViewReload', false) + }, + //加载失败时是否显示空数据图重新加载按钮,默认为是 + showEmptyViewReloadWhenError: { + type: Boolean, + default: u.gc('showEmptyViewReloadWhenError', true) + }, + //空数据图点击重新加载文字,默认为“重新加载” + emptyViewReloadText: { + type: [String, Object], + default: u.gc('emptyViewReloadText', null) + }, + //空数据图图片,默认使用z-paging内置的图片 + emptyViewImg: { + type: String, + default: u.gc('emptyViewImg', '') + }, + //空数据图“加载失败”描述文字,默认为“很抱歉,加载失败” + emptyViewErrorText: { + type: [String, Object], + default: u.gc('emptyViewErrorText', null) + }, + //空数据图“加载失败”图片,默认使用z-paging内置的图片 + emptyViewErrorImg: { + type: String, + default: u.gc('emptyViewErrorImg', '') + }, + //空数据图样式 + emptyViewStyle: { + type: Object, + default: function() { + return u.gc('emptyViewStyle', {}); + } + }, + //空数据图容器样式 + emptyViewSuperStyle: { + type: Object, + default: function() { + return u.gc('emptyViewSuperStyle', {}); + } + }, + //空数据图img样式 + emptyViewImgStyle: { + type: Object, + default: function() { + return u.gc('emptyViewImgStyle', {}); + } + }, + //空数据图描述文字样式 + emptyViewTitleStyle: { + type: Object, + default: function() { + return u.gc('emptyViewTitleStyle', {}); + } + }, + //空数据图重新加载按钮样式 + emptyViewReloadStyle: { + type: Object, + default: function() { + return u.gc('emptyViewReloadStyle', {}); + } + }, + //空数据图片是否铺满z-paging,默认为是。若设置为否,则为填充满z-paging的剩余部分 + emptyViewFixed: { + type: Boolean, + default: function() { + return u.gc('emptyViewFixed', false) + } + }, + //空数据图片是否垂直居中,默认为是。emptyViewFixed为false时有效 + emptyViewCenter: { + type: Boolean, + default: function() { + return u.gc('emptyViewCenter', true) + } + }, + //加载中时是否自动隐藏空数据图,默认为是 + autoHideEmptyViewWhenLoading: { + type: Boolean, + default: u.gc('autoHideEmptyViewWhenLoading', true) + }, + //用户下拉列表触发下拉刷新加载中时是否自动隐藏空数据图,默认为是 + autoHideEmptyViewWhenPull: { + type: Boolean, + default: u.gc('autoHideEmptyViewWhenPull', true) + }, + //空数据view的z-index,默认为9 + emptyViewZIndex: { + type: Number, + default: u.gc('emptyViewZIndex', 9) + }, + }, + computed: { + finalEmptyViewImg() { + return this.isLoadFailed ? this.emptyViewErrorImg : this.emptyViewImg; + }, + finalShowEmptyViewReload() { + return this.isLoadFailed ? this.showEmptyViewReloadWhenError : this.showEmptyViewReload; + }, + showEmpty() { + if(this.refresherOnly || this.hideEmptyView || this.totalData.length) return false; + if(this.autoHideEmptyViewWhenLoading){ + if (this.isAddedData && !this.firstPageLoaded && !this.loading) return true; + }else{ + return true; + } + if (!this.autoHideEmptyViewWhenPull && !this.isUserReload) return true; + return false; + }, + }, + methods: { + //点击了空数据view重新加载按钮 + _emptyViewReload() { + let callbacked = false; + this.$emit('emptyViewReload', (reload) => { + if (reload === undefined || reload === true) { + this.fromEmptyViewReload = true; + this.reload(); + } + callbacked = true; + }); + this.$nextTick(() => { + if (!callbacked) { + this.fromEmptyViewReload = true; + this.reload(); + } + }) + }, + } +} + +export default ZPEmptyView; diff --git a/components/z-paging/js/modules/i18n.js b/components/z-paging/js/modules/i18n.js new file mode 100644 index 0000000..5264e1a --- /dev/null +++ b/components/z-paging/js/modules/i18n.js @@ -0,0 +1,98 @@ +// [z-paging]i18n模块 +import u from '.././z-paging-utils' +import c from '.././z-paging-constant' +import zI18n from '.././z-paging-i18n' + +const systemInfo = uni.getSystemInfoSync(); +const ZPI18n = { + props: { + //i18n国际化设置语言,支持简体中文(zh-cn)、繁体中文(zh-hant-cn)和英文(en) + language: { + type: String, + default: u.gc('language', '') + }, + //i18n国际化默认是否跟随系统语言,默认为是 + followSystemLanguage: { + type: Boolean, + default: u.gc('followSystemLanguage', true) + }, + }, + data() { + return { + tempLanguageUpdateKey: 0, + } + }, + computed: { + tempLanguage() { + let systemLanguage = false; + const temp = this.tempLanguageUpdateKey; + if (this.followSystemLanguage) { + systemLanguage = systemInfo.language; + } + return uni.getStorageSync(c.i18nUpdateKey) || systemLanguage || 'zh-cn'; + }, + finalTempLanguage() { + return this.language.length ? this.language : this.tempLanguage; + }, + finalLanguage() { + let language = this.finalTempLanguage.toLowerCase(); + return zI18n._getPrivateLanguage(language, this.followSystemLanguage); + }, + finalRefresherDefaultText() { + return this._getI18nText('refresherDefaultText', this.refresherDefaultText); + }, + finalRefresherPullingText() { + return this._getI18nText('refresherPullingText', this.refresherPullingText); + }, + finalRefresherRefreshingText() { + return this._getI18nText('refresherRefreshingText', this.refresherRefreshingText); + }, + finalRefresherCompleteText() { + return this._getI18nText('refresherCompleteText', this.refresherCompleteText); + }, + finalLoadingMoreDefaultText() { + return this._getI18nText('loadingMoreDefaultText', this.loadingMoreDefaultText); + }, + finalLoadingMoreLoadingText() { + return this._getI18nText('loadingMoreLoadingText', this.loadingMoreLoadingText); + }, + finalLoadingMoreNoMoreText() { + return this._getI18nText('loadingMoreNoMoreText', this.loadingMoreNoMoreText); + }, + finalLoadingMoreFailText() { + return this._getI18nText('loadingMoreFailText', this.loadingMoreFailText); + }, + finalEmptyViewText() { + return this.isLoadFailed ? this.finalEmptyViewErrorText : this._getI18nText('emptyViewText', this.emptyViewText); + }, + finalEmptyViewReloadText() { + return this._getI18nText('emptyViewReloadText', this.emptyViewReloadText); + }, + finalEmptyViewErrorText() { + return this._getI18nText('emptyViewErrorText', this.emptyViewErrorText); + }, + }, + methods: { + //设置i18n国际化语言 + setI18n(language) { + zI18n.setLanguage(language); + }, + //获取当前z-paging的语言 + getLanguage() { + return this.finalLanguage; + }, + //获取国际化转换后的文本 + _getI18nText(key, value) { + const dataType = Object.prototype.toString.call(value); + if (dataType === '[object Object]') { + const nextValue = value[this.finalLanguage]; + if (nextValue) return nextValue; + } else if (dataType === '[object String]') { + return value; + } + return zI18n.t[key][this.finalLanguage]; + }, + } +} + +export default ZPI18n; diff --git a/components/z-paging/js/modules/load-more.js b/components/z-paging/js/modules/load-more.js new file mode 100644 index 0000000..c14edae --- /dev/null +++ b/components/z-paging/js/modules/load-more.js @@ -0,0 +1,328 @@ +// [z-paging]滚动到底部加载更多模块 +import u from '.././z-paging-utils' +import Enum from '.././z-paging-enum' + +const ZPLoadMore = { + props: { + //自定义底部加载更多样式 + loadingMoreCustomStyle: { + type: Object, + default: function() { + return u.gc('loadingMoreCustomStyle', {}); + } + }, + //自定义底部加载更多文字样式 + loadingMoreTitleCustomStyle: { + type: Object, + default: function() { + return u.gc('loadingMoreTitleCustomStyle', {}); + } + }, + //自定义底部加载更多加载中动画样式 + loadingMoreLoadingIconCustomStyle: { + type: Object, + default: function() { + return u.gc('loadingMoreLoadingIconCustomStyle', {}); + } + }, + //自定义底部加载更多加载中动画图标类型,可选flower或circle,默认为flower + loadingMoreLoadingIconType: { + type: String, + default: u.gc('loadingMoreLoadingIconType', 'flower') + }, + //自定义底部加载更多加载中动画图标图片 + loadingMoreLoadingIconCustomImage: { + type: String, + default: u.gc('loadingMoreLoadingIconCustomImage', '') + }, + //底部加载更多加载中view是否展示旋转动画,默认为是 + loadingMoreLoadingAnimated: { + type: Boolean, + default: u.gc('loadingMoreLoadingAnimated', true) + }, + //是否启用加载更多数据(含滑动到底部加载更多数据和点击加载更多数据),默认为是 + loadingMoreEnabled: { + type: Boolean, + default: u.gc('loadingMoreEnabled', true) + }, + //是否启用滑动到底部加载更多数据,默认为是 + toBottomLoadingMoreEnabled: { + type: Boolean, + default: u.gc('toBottomLoadingMoreEnabled', true) + }, + //滑动到底部状态为默认状态时,以加载中的状态展示,默认为否。若设置为是,可避免滚动到底部看到默认状态然后立刻变为加载中状态的问题,但分页数量未超过一屏时,不会显示【点击加载更多】 + loadingMoreDefaultAsLoading: { + type: [Boolean], + default: u.gc('loadingMoreDefaultAsLoading', false) + }, + //滑动到底部"默认"文字,默认为【点击加载更多】 + loadingMoreDefaultText: { + type: [String, Object], + default: u.gc('loadingMoreDefaultText', null) + }, + //滑动到底部"加载中"文字,默认为【正在加载...】 + loadingMoreLoadingText: { + type: [String, Object], + default: u.gc('loadingMoreLoadingText', null) + }, + //滑动到底部"没有更多"文字,默认为【没有更多了】 + loadingMoreNoMoreText: { + type: [String, Object], + default: u.gc('loadingMoreNoMoreText', null) + }, + //滑动到底部"加载失败"文字,默认为【加载失败,点击重新加载】 + loadingMoreFailText: { + type: [String, Object], + default: u.gc('loadingMoreFailText', null) + }, + //当没有更多数据且分页内容未超出z-paging时是否隐藏没有更多数据的view,默认为否 + hideLoadingMoreWhenNoMoreAndInsideOfPaging: { + type: Boolean, + default: u.gc('hideLoadingMoreWhenNoMoreAndInsideOfPaging', false) + }, + //当没有更多数据且分页数组长度少于这个值时,隐藏没有更多数据的view,默认为0,代表不限制。 + hideLoadingMoreWhenNoMoreByLimit: { + type: Number, + default: u.gc('hideLoadingMoreWhenNoMoreByLimit', 0) + }, + //是否显示默认的加载更多text,默认为是 + showDefaultLoadingMoreText: { + type: Boolean, + default: u.gc('showDefaultLoadingMoreText', true) + }, + //是否显示没有更多数据的view + showLoadingMoreNoMoreView: { + type: Boolean, + default: u.gc('showLoadingMoreNoMoreView', true) + }, + //是否显示没有更多数据的分割线,默认为是 + showLoadingMoreNoMoreLine: { + type: Boolean, + default: u.gc('showLoadingMoreNoMoreLine', true) + }, + //自定义底部没有更多数据的分割线样式 + loadingMoreNoMoreLineCustomStyle: { + type: Object, + default: function() { + return u.gc('loadingMoreNoMoreLineCustomStyle', {}); + }, + }, + //距底部/右边多远时(单位px),触发 scrolltolower 事件,默认为100rpx + lowerThreshold: { + type: [Number, String], + default: u.gc('lowerThreshold', '100rpx') + }, + }, + data() { + return { + //底部加载更多状态 + loadingStatus: Enum.More.Default, + loadingStatusAfterRender: Enum.More.Default, + loadingMoreTimeStamp: 0, + loadingMoreDefaultSlot: null, + showLoadingMore: false, + customNoMore: -1, + } + }, + computed: { + zPagingLoadMoreConfig() { + return { + status: this.loadingStatusAfterRender, + defaultAsLoading: this.loadingMoreDefaultAsLoading, + defaultThemeStyle: this.finalLoadingMoreThemeStyle, + customStyle: this.loadingMoreCustomStyle, + titleCustomStyle: this.loadingMoreTitleCustomStyle, + iconCustomStyle: this.loadingMoreLoadingIconCustomStyle, + loadingIconType: this.loadingMoreLoadingIconType, + loadingIconCustomImage: this.loadingMoreLoadingIconCustomImage, + loadingAnimated: this.loadingMoreLoadingAnimated, + showNoMoreLine: this.showLoadingMoreNoMoreLine, + noMoreLineCustomStyle: this.loadingMoreNoMoreLineCustomStyle, + defaultText: this.finalLoadingMoreDefaultText, + loadingText: this.finalLoadingMoreLoadingText, + noMoreText: this.finalLoadingMoreNoMoreText, + failText: this.finalLoadingMoreFailText, + hideContent: !this.loadingMoreDefaultAsLoading && this.listRendering + }; + }, + finalLoadingMoreThemeStyle() { + return this.loadingMoreThemeStyle.length ? this.loadingMoreThemeStyle : this.defaultThemeStyle; + }, + showLoadingMoreDefault() { + return this._showLoadingMore('Default'); + }, + showLoadingMoreLoading() { + return this._showLoadingMore('Loading'); + }, + showLoadingMoreNoMore() { + return this._showLoadingMore('NoMore'); + }, + showLoadingMoreFail() { + return this._showLoadingMore('Fail'); + }, + showLoadingMoreCustom() { + return this._showLoadingMore('Custom'); + } + }, + methods: { + //手动触发上拉加载更多(非必须,可依据具体需求使用) + doLoadMore(type) { + this._onLoadingMore(type); + }, + //通过@scroll事件检测是否滚动到了底部 + _checkScrolledToBottom(scrollDiff, checked = false) { + if (this.checkScrolledToBottomTimeOut) { + clearTimeout(this.checkScrolledToBottomTimeOut); + this.checkScrolledToBottomTimeOut = null; + } + if (this.cacheScrollNodeHeight === -1) { + this._getNodeClientRect('.zp-scroll-view').then((res) => { + if (res) { + let pageScrollNodeHeight = res[0].height; + this.cacheScrollNodeHeight = pageScrollNodeHeight; + if (scrollDiff - pageScrollNodeHeight <= this.finalLowerThreshold) { + this._onLoadingMore('toBottom'); + } + } + }); + } else { + if (scrollDiff - this.cacheScrollNodeHeight <= this.finalLowerThreshold) { + this._onLoadingMore('toBottom'); + } else if (scrollDiff - this.cacheScrollNodeHeight <= 500 && !checked) { + this.checkScrolledToBottomTimeOut = setTimeout(() => { + this._getNodeClientRect('.zp-scroll-view', true, true).then((res) => { + this.oldScrollTop = res[0].scrollTop; + const newScrollDiff = res[0].scrollHeight - this.oldScrollTop; + this._checkScrolledToBottom(newScrollDiff, true); + }) + }, 150) + } + } + }, + //触发加载更多时调用,from:0-滑动到底部触发;1-点击加载更多触发 + _onLoadingMore(from = 'click') { + if (from === 'toBottom') { + if (!this.scrollToBottomBounceEnabled) { + if (this.scrollEnable) { + this.scrollEnable = false; + this.$nextTick(() => { + this.scrollEnable = true; + }) + } + } + //#ifdef APP-VUE || H5 + if (this.isIos) { + this.renderPropUsePageScroll = -1; + this.$nextTick(() => { + this.renderPropUsePageScroll = this.usePageScroll; + }) + } + //#endif + } + this.$emit('scrolltolower', from); + if (from === 'toBottom' && (!this.toBottomLoadingMoreEnabled || this.useChatRecordMode)) return; + if (this.refresherOnly || !this.loadingMoreEnabled || !(this.loadingStatus === Enum.More.Default || this.loadingStatus === Enum.More.Fail) || this.loading) return; + // #ifdef MP-WEIXIN + if (!this.isIos && !this.refresherOnly && !this.usePageScroll) { + const currentTimestamp = u.getTime(); + if (this.loadingMoreTimeStamp > 0 && currentTimestamp - this.loadingMoreTimeStamp < 100) { + this.loadingMoreTimeStamp = 0; + return; + } + } + // #endif + this._doLoadingMore(); + }, + //处理开始加载更多 + _doLoadingMore() { + if (this.pageNo >= this.defaultPageNo && this.loadingStatus !== Enum.More.NoMore) { + this.pageNo++; + this._startLoading(false); + if (this.isLocalPaging) { + this._localPagingQueryList(this.pageNo, this.defaultPageSize, this.localPagingLoadingTime, (res) => { + this.addData(res); + }) + } else { + this._emitQuery(this.pageNo, this.defaultPageSize, Enum.QueryFrom.LoadingMore); + this._callMyParentQuery(); + } + this.loadingType = Enum.LoadingType.LoadingMore; + } + }, + //(预处理)判断当没有更多数据且分页内容未超出z-paging时是否显示没有更多数据的view + _preCheckShowLoadingMoreWhenNoMoreAndInsideOfPaging(newVal, scrollViewNode, pagingContainerNode) { + if (this.loadingStatus === Enum.More.NoMore && this.hideLoadingMoreWhenNoMoreByLimit > 0 && newVal.length) { + this.showLoadingMore = newVal.length > this.hideLoadingMoreWhenNoMoreByLimit; + } else if ((this.loadingStatus === Enum.More.NoMore && this.hideLoadingMoreWhenNoMoreAndInsideOfPaging && newVal.length) || (this.insideMore && this.insideOfPaging !== false && newVal.length)) { + this.$nextTick(() => { + this._checkShowLoadingMoreWhenNoMoreAndInsideOfPaging(newVal, scrollViewNode, pagingContainerNode); + }) + if (this.insideMore && this.insideOfPaging !== false && newVal.length) { + this.showLoadingMore = newVal.length; + } + } else { + this.showLoadingMore = newVal.length; + } + }, + //判断当没有更多数据且分页内容未超出z-paging时是否显示没有更多数据的view + async _checkShowLoadingMoreWhenNoMoreAndInsideOfPaging(totalData, oldScrollViewNode, oldPagingContainerNode) { + try { + const scrollViewNode = oldScrollViewNode || await this._getNodeClientRect('.zp-scroll-view'); + if (this.usePageScroll) { + if (scrollViewNode) { + const scrollViewTotalH = scrollViewNode[0].top + scrollViewNode[0].height; + this.insideOfPaging = scrollViewTotalH < this.windowHeight; + if (this.hideLoadingMoreWhenNoMoreAndInsideOfPaging) { + this.showLoadingMore = !this.insideOfPaging; + } + this._updateInsideOfPaging(); + } + } else { + let pagingContainerH = 0; + let scrollViewH = 0; + const pagingContainerNode = oldPagingContainerNode || await this._getNodeClientRect('.zp-paging-container-content'); + if (pagingContainerNode) { + pagingContainerH = pagingContainerNode[0].height; + } + if (scrollViewNode) { + scrollViewH = scrollViewNode[0].height; + } + this.insideOfPaging = pagingContainerH < scrollViewH; + if (this.hideLoadingMoreWhenNoMoreAndInsideOfPaging) { + this.showLoadingMore = !this.insideOfPaging; + } + this._updateInsideOfPaging(); + } + } catch (e) { + this.insideOfPaging = !totalData.length; + if (this.hideLoadingMoreWhenNoMoreAndInsideOfPaging) { + this.showLoadingMore = !this.insideOfPaging; + } + this._updateInsideOfPaging(); + } + }, + //是否要展示上拉加载更多view + _showLoadingMore(type) { + if (!(this.loadingStatus === Enum.More.Default ? this.nShowBottom : true) || !this.totalData.length) return false; + if (((!this.showLoadingMoreWhenReload || this.isUserPullDown || this.loadingStatus !== Enum.More.Loading) && !this.showLoadingMore) || + (!this.loadingMoreEnabled && (!this.showLoadingMoreWhenReload || this.isUserPullDown || this.loadingStatus !== Enum.More.Loading)) || + this.refresherOnly) return false; + if (this.useChatRecordMode && type !== 'Loading') return false; + if (!this.$slots) return false; + if (type === 'Custom') { + return this.showDefaultLoadingMoreText && !(this.loadingStatus === Enum.More.NoMore && !this.showLoadingMoreNoMoreView); + } + const res = this.loadingStatus === Enum.More[type] && this.$slots[`loadingMore${type}`] && (type === 'NoMore' ? this.showLoadingMoreNoMoreView : true); + if (res) { + // #ifdef APP-NVUE + if (!this.isIos) { + this.nLoadingMoreFixedHeight = false; + } + // #endif + } + return res; + }, + } +} + +export default ZPLoadMore; diff --git a/components/z-paging/js/modules/nvue.js b/components/z-paging/js/modules/nvue.js new file mode 100644 index 0000000..b286e04 --- /dev/null +++ b/components/z-paging/js/modules/nvue.js @@ -0,0 +1,219 @@ +// [z-paging]nvue独有部分模块 +import u from '.././z-paging-utils' +import Enum from '.././z-paging-enum' + +// #ifdef APP-NVUE +const weexAnimation = weex.requireModule('animation'); +// #endif +const ZPNvue = { + props: { + //nvue中修改列表类型,可选值有list、waterfall和scroller,默认为list + nvueListIs: { + type: String, + default: u.gc('nvueListIs', 'list') + }, + //nvue waterfall配置,仅在nvue中且nvueListIs=waterfall时有效,配置参数详情参见:https://uniapp.dcloud.io/component/waterfall + nvueWaterfallConfig: { + type: Object, + default: function() { + return u.gc('nvueWaterfallConfig', {}); + } + }, + //nvue 控制是否回弹效果,iOS不支持动态修改 + nvueBounce: { + type: Boolean, + default: u.gc('nvueBounce', true) + }, + //nvue中通过代码滚动到顶部/底部时,是否加快动画效果(无滚动动画时无效),默认为否 + nvueFastScroll: { + type: Boolean, + default: u.gc('nvueFastScroll', false) + }, + //nvue中list的id + nvueListId: { + type: String, + default: u.gc('nvueListId', '') + }, + //nvue中refresh组件的样式 + nvueRefresherStyle: { + type: Object, + default: function() { + return u.gc('nvueRefresherStyle', {}); + } + }, + //nvue中是否按分页模式(类似竖向swiper)显示List,默认为false + nvuePagingEnabled: { + type: Boolean, + default: u.gc('nvuePagingEnabled', false) + }, + //是否隐藏nvue列表底部的tagView,此view用于标识滚动到底部位置,若隐藏则滚动到底部功能将失效,在nvue中实现吸顶+swiper功能时需将最外层z-paging的此属性设置为true。默认为否 + hideNvueBottomTag: { + type: Boolean, + default: u.gc('hideNvueBottomTag', false) + }, + }, + data() { + return { + nRefresherLoading: false, + nListIsDragging: false, + nShowBottom: true, + nFixFreezing: false, + nShowRefresherReveal: false, + nIsFirstPageAndNoMore: false, + nFirstPageAndNoMoreChecked: false, + nLoadingMoreFixedHeight: false, + nShowRefresherRevealHeight: 0, + nRefresherWidth: uni.upx2px(750), + } + }, + watch: { + nIsFirstPageAndNoMore: { + handler(newVal) { + const cellStyle = !this.useChatRecordMode || newVal ? {} : {transform: 'rotate(180deg)'}; + this.$emit('update:cellStyle', cellStyle); + }, + immediate: true + } + }, + computed: { + // #ifdef APP-NVUE + nWaterfallColumnCount() { + if (this.finalNvueListIs !== 'waterfall') return 0; + return this._nGetWaterfallConfig('column-count', 2); + }, + nWaterfallColumnWidth() { + return this._nGetWaterfallConfig('column-width', 'auto'); + }, + nWaterfallColumnGap() { + return this._nGetWaterfallConfig('column-gap', 'normal'); + }, + nWaterfallLeftGap() { + return this._nGetWaterfallConfig('left-gap', 0); + }, + nWaterfallRightGap() { + return this._nGetWaterfallConfig('right-gap', 0); + }, + nViewIs() { + const is = this.finalNvueListIs; + return is === 'scroller' || is === 'view' ? 'view' : is === 'waterfall' ? 'header' : 'cell'; + }, + nSafeAreaBottomHeight() { + return this.safeAreaInsetBottom ? this.safeAreaBottom : 0; + }, + finalNvueListIs() { + if (this.usePageScroll) return 'view'; + const nvueListIsLowerCase = this.nvueListIs.toLowerCase(); + if (['list','waterfall','scroller'].indexOf(nvueListIsLowerCase) !== -1) { + return nvueListIsLowerCase; + } + return 'list'; + }, + finalNvueSuperListIs() { + return this.usePageScroll ? 'view' : 'scroller'; + }, + finalNvueRefresherEnabled() { + return this.finalNvueListIs !== 'view' && this.finalRefresherEnabled && !this.nShowRefresherReveal && !this.useChatRecordMode; + }, + // #endif + }, + methods: { + // #ifdef APP-NVUE + //列表滚动时触发 + _nOnScroll(e) { + this.$emit('scroll', e); + const contentOffsetY = e.contentOffset.y; + this.nListIsDragging = e.isDragging; + this._checkShouldShowBackToTop(-e.contentOffset.y, -e.contentOffset.y - 1); + }, + //下拉刷新刷新中 + _nOnRrefresh() { + if (this.nShowRefresherReveal) return; + this.nRefresherLoading = true; + this.refresherStatus = Enum.Refresher.Loading; + this._doRefresherLoad(); + }, + //下拉刷新下拉中 + _nOnPullingdown(e) { + if (this.refresherStatus === Enum.Refresher.Loading || (this.isIos && !this.nListIsDragging)) return; + this._emitTouchmove(e); + const viewHeight = e.viewHeight; + const pullingDis = e.pullingDistance; + this.refresherStatus = pullingDis >= viewHeight ? Enum.Refresher.ReleaseToRefresh : Enum.Refresher.Default; + }, + //下拉刷新结束 + _nRefresherEnd(doEnd=true) { + if (doEnd) { + this._nDoRefresherEndAnimation(0, -this.nShowRefresherRevealHeight); + !this.usePageScroll && this.$refs['zp-n-list'].resetLoadmore(); + this.nRefresherLoading = false; + } + this.$nextTick(() => { + setTimeout(()=> { + this.nShowBottom = true; + }, 10); + }) + }, + //执行主动触发下拉刷新动画 + _nDoRefresherEndAnimation(height, translateY, animate = true, checkStack = true) { + this._cleanRefresherCompleteTimeout(); + this._cleanRefresherEndTimeout(); + if (!this.finalShowRefresherWhenReload) { + this.refresherEndTimeout = setTimeout(() => { + this.refresherStatus = Enum.Refresher.Default; + }, this.refresherCompleteDuration); + return; + } + const stackCount = this.refresherRevealStackCount; + if (height === 0 && checkStack) { + this.refresherRevealStackCount--; + if (stackCount > 1) return; + this.refresherEndTimeout = setTimeout(() => { + this.refresherStatus = Enum.Refresher.Default; + }, this.refresherCompleteDuration); + } + if (stackCount > 1) { + this.refresherStatus = Enum.Refresher.Loading; + } + const duration = animate ? 120 : 0; + weexAnimation.transition(this.$refs['zp-n-list-refresher-reveal'], { + styles: { + height: `${height}px`, + transform: `translateY(${translateY}px)`, + }, + duration: duration, + timingFunction: 'linear', + needLayout: true, + delay: 0 + }) + setTimeout(() => { + if (animate) { + this.nShowRefresherReveal = height > 0; + } + }, duration > 0 ? duration - 100 : 0); + }, + //滚动到底部加载更多 + _nOnLoadmore() { + if (this.nShowRefresherReveal || !this.totalData.length) return; + this.useChatRecordMode ? this.doChatRecordLoadMore() : this._onLoadingMore('toBottom'); + }, + //获取nvue waterfall单项配置 + _nGetWaterfallConfig(key, defaultValue) { + return this.nvueWaterfallConfig[key] || defaultValue; + }, + //更新nvue 下拉刷新view容器的宽度 + _nUpdateRefresherWidth() { + this.$nextTick(()=>{ + this._getNodeClientRect('.zp-n-list').then(node => { + if (node) { + const nodeWidth = node[0].width; + this.nRefresherWidth = nodeWidth; + } + }) + }) + + } + // #endif + } +} + +export default ZPNvue; diff --git a/components/z-paging/js/modules/refresher.js b/components/z-paging/js/modules/refresher.js new file mode 100644 index 0000000..440c580 --- /dev/null +++ b/components/z-paging/js/modules/refresher.js @@ -0,0 +1,632 @@ +// [z-paging]下拉刷新view模块 +import u from '.././z-paging-utils' +import c from '.././z-paging-constant' +import Enum from '.././z-paging-enum' + +const ZPRefresher = { + props: { + //下拉刷新的主题样式,支持black,white,默认black + refresherThemeStyle: { + type: String, + default: function() { + return u.gc('refresherThemeStyle', ''); + } + }, + //自定义下拉刷新中左侧图标的样式 + refresherImgStyle: { + type: Object, + default: function() { + return u.gc('refresherImgStyle', {}); + } + }, + //自定义下拉刷新中右侧状态描述文字的样式 + refresherTitleStyle: { + type: Object, + default: function() { + return u.gc('refresherTitleStyle', {}); + } + }, + //自定义下拉刷新中右侧最后更新时间文字的样式(show-refresher-update-time为true时有效) + refresherUpdateTimeStyle: { + type: Object, + default: function() { + return u.gc('refresherUpdateTimeStyle', {}); + } + }, + //在微信小程序和QQ小程序中,是否实时监听下拉刷新中进度,默认为否 + watchRefresherTouchmove: { + type: Boolean, + default: u.gc('watchRefresherTouchmove', false) + }, + //底部加载更多的主题样式,支持black,white,默认black + loadingMoreThemeStyle: { + type: String, + default: function() { + return u.gc('loadingMoreThemeStyle', ''); + } + }, + //是否只使用下拉刷新,设置为true后将关闭mounted自动请求数据、关闭滚动到底部加载更多,强制隐藏空数据图。默认为否 + refresherOnly: { + type: Boolean, + default: u.gc('refresherOnly', false) + }, + //自定义下拉刷新默认状态下回弹动画时间,单位为毫秒,默认为100毫秒,nvue无效 + refresherDefaultDuration: { + type: [Number, String], + default: u.gc('refresherDefaultDuration', 100) + }, + //自定义下拉刷新结束以后延迟回弹的时间,单位为毫秒,默认为0 + refresherCompleteDelay: { + type: [Number, String], + default: u.gc('refresherCompleteDelay', 0) + }, + //自定义下拉刷新结束回弹动画时间,单位为毫秒,默认为300毫秒(refresherEndBounceEnabled为false时,refresherCompleteDuration为设定值的1/3),nvue无效 + refresherCompleteDuration: { + type: [Number, String], + default: u.gc('refresherCompleteDuration', 300) + }, + //自定义下拉刷新结束状态下是否允许列表滚动,默认为否 + refresherCompleteScrollable: { + type: Boolean, + default: u.gc('refresherCompleteScrollable', false) + }, + //是否使用自定义的下拉刷新,默认为是,即使用z-paging的下拉刷新。设置为false即代表使用uni scroll-view自带的下拉刷新,h5、App、微信小程序以外的平台不支持uni scroll-view自带的下拉刷新 + useCustomRefresher: { + type: Boolean, + default: u.gc('useCustomRefresher', true) + }, + //自定义下拉刷新下拉帧率,默认为40,过高可能会出现抖动问题 + refresherFps: { + type: [Number, String], + default: u.gc('refresherFps', 40) + }, + //自定义下拉刷新允许触发的最大下拉角度,默认为40度,当下拉角度小于设定值时,自定义下拉刷新动画不会被触发 + refresherMaxAngle: { + type: [Number, String], + default: u.gc('refresherMaxAngle', 40) + }, + //自定义下拉刷新的角度由未达到最大角度变到达到最大角度时,是否继续下拉刷新手势,默认为否 + refresherAngleEnableChangeContinued: { + type: Boolean, + default: u.gc('refresherAngleEnableChangeContinued', false) + }, + //自定义下拉刷新默认状态下的文字 + refresherDefaultText: { + type: [String, Object], + default: u.gc('refresherDefaultText', null) + }, + //自定义下拉刷新松手立即刷新状态下的文字 + refresherPullingText: { + type: [String, Object], + default: u.gc('refresherPullingText', null) + }, + //自定义下拉刷新刷新中状态下的文字 + refresherRefreshingText: { + type: [String, Object], + default: u.gc('refresherRefreshingText', null) + }, + //自定义下拉刷新刷新结束状态下的文字 + refresherCompleteText: { + type: [String, Object], + default: u.gc('refresherCompleteText', null) + }, + //是否开启自定义下拉刷新刷新结束回弹效果,默认为是 + refresherEndBounceEnabled: { + type: Boolean, + default: u.gc('refresherEndBounceEnabled', true) + }, + //是否开启自定义下拉刷新,默认为是 + refresherEnabled: { + type: Boolean, + default: u.gc('refresherEnabled', true) + }, + //设置自定义下拉刷新阈值,默认为80rpx + refresherThreshold: { + type: [Number, String], + default: u.gc('refresherThreshold', '80rpx') + }, + //设置系统下拉刷新默认样式,支持设置 black,white,none,none 表示不使用默认样式,默认为black + refresherDefaultStyle: { + type: String, + default: u.gc('refresherDefaultStyle', 'black') + }, + //设置自定义下拉刷新区域背景 + refresherBackground: { + type: String, + default: u.gc('refresherBackground', 'transparent') + }, + //设置固定的自定义下拉刷新区域背景 + refresherFixedBackground: { + type: String, + default: u.gc('refresherFixedBackground', 'transparent') + }, + //设置固定的自定义下拉刷新区域高度,默认为0 + refresherFixedBacHeight: { + type: [Number, String], + default: u.gc('refresherFixedBacHeight', 0) + }, + //设置自定义下拉刷新下拉超出阈值后继续下拉位移衰减的比例,范围0-1,值越大代表衰减越多。默认为0.7(nvue无效) + refresherOutRate: { + type: Number, + default: u.gc('refresherOutRate', 0.7) + }, + //是否显示最后更新时间,默认为否 + showRefresherUpdateTime: { + type: Boolean, + default: u.gc('showRefresherUpdateTime', false) + }, + //如果需要区别不同页面的最后更新时间,请为不同页面的z-paging的`refresher-update-time-key`设置不同的字符串 + refresherUpdateTimeKey: { + type: String, + default: u.gc('refresherUpdateTimeKey', 'default') + }, + }, + data() { + return { + //下拉刷新状态 + refresherStatus: Enum.Refresher.Default, + refresherTouchstartY: 0, + lastRefresherTouchmove: null, + refresherReachMaxAngle: true, + refresherTransform: 'translateY(0px)', + refresherTransition: '', + finalRefresherDefaultStyle: 'black', + refresherRevealStackCount: 0, + refresherCompleteTimeout: null, + refresherCompleteSubTimeout: null, + refresherEndTimeout: null, + isTouchmovingTimeout: null, + refresherTriggered: false, + isTouchmoving: false, + isTouchEnded: false, + isUserPullDown: false, + privateRefresherEnabled: -1, + privateShowRefresherWhenReload: false, + customRefresherHeight: -1, + showCustomRefresher: false, + doRefreshAnimateAfter: false, + isRefresherInComplete: false, + pullDownTimeStamp: 0, + moveDis: 0, + oldMoveDis: 0, + oldRefresherTouchmoveY: 0, + oldTouchDirection: '' + } + }, + watch: { + refresherDefaultStyle: { + handler(newVal) { + if (newVal.length) { + this.finalRefresherDefaultStyle = newVal; + } + }, + immediate: true + }, + refresherStatus(newVal, oldVal) { + if (newVal === Enum.Refresher.Loading){ + this._cleanRefresherEndTimeout(); + } + this.$emit('refresherStatusChange', newVal); + this.$emit('update:refresherStatus', newVal); + }, + moveDis(newVal, oldVal){ + this.oldMoveDis = oldVal; + } + }, + computed: { + pullDownDisTimeStamp() { + return 1000 / this.refresherFps; + }, + finalRefresherEnabled() { + if (this.useChatRecordMode) return false; + if (this.privateRefresherEnabled === -1) return this.refresherEnabled; + return this.privateRefresherEnabled === 1; + }, + finalRefresherThreshold() { + let refresherThreshold = this.refresherThreshold; + let idDefault = false; + if (refresherThreshold === '80rpx') { + idDefault = true; + if (this.showRefresherUpdateTime) { + refresherThreshold = '120rpx'; + } + } + if (idDefault && this.customRefresherHeight > 0) { + return this.customRefresherHeight; + } + return u.convertTextToPx(refresherThreshold); + }, + finalRefresherFixedBacHeight() { + return u.convertTextToPx(this.refresherFixedBacHeight); + }, + finalRefresherThemeStyle() { + return this.refresherThemeStyle.length ? this.refresherThemeStyle : this.defaultThemeStyle; + }, + finalRefresherOutRate() { + let rate = this.refresherOutRate; + rate = Math.max(0,rate); + rate = Math.min(1,rate); + return rate; + }, + finalRefresherTransform() { + if (this.refresherTransform === 'translateY(0px)') return 'none'; + return this.refresherTransform; + }, + finalShowRefresherWhenReload() { + return this.showRefresherWhenReload || this.privateShowRefresherWhenReload; + }, + finalRefresherTriggered() { + if (!(this.finalRefresherEnabled && !this.useCustomRefresher)) return false; + return this.refresherTriggered; + }, + showRefresher() { + const showRefresher = this.finalRefresherEnabled && this.useCustomRefresher && this.isTouchmoving; + // #ifndef APP-NVUE + if (this.customRefresherHeight === -1 && showRefresher) { + setTimeout(() => { + this.$nextTick(()=>{ + this._updateCustomRefresherHeight(); + }) + }, 100) + } + // #endif + return showRefresher; + }, + hasTouchmove(){ + // #ifdef VUE2 + // #ifdef APP-VUE || H5 + if (this.$listeners && !this.$listeners.refresherTouchmove) return false; + // #endif + // #ifdef MP-WEIXIN || MP-QQ + return this.watchRefresherTouchmove; + // #endif + return true; + // #endif + return this.watchRefresherTouchmove; + }, + }, + methods: { + //终止下拉刷新状态 + endRefresh(){ + this._refresherEnd(); + }, + handleRefresherStatusChanged(func) { + this.refresherStatusChangedFunc = func; + }, + //自定义下拉刷新被触发 + _onRefresh(fromScrollView=false,isUserPullDown=true) { + if (fromScrollView && !(this.finalRefresherEnabled && !this.useCustomRefresher)) return; + this.$emit('onRefresh'); + this.$emit('Refresh'); + // #ifdef APP-NVUE + if (this.loading) { + setTimeout(()=>{ + this._nRefresherEnd(); + },500) + return; + } + // #endif + if (this.loading || this.isRefresherInComplete) return; + this.loadingType = Enum.LoadingType.Refresher; + if (this.nShowRefresherReveal) return; + this.isUserPullDown = isUserPullDown; + this.isUserReload = !isUserPullDown; + this._startLoading(true); + this.refresherTriggered = true; + if(this.reloadWhenRefresh && isUserPullDown){ + if (this.useChatRecordMode) { + this._onLoadingMore('click') + } else { + this._reload(false, false, isUserPullDown); + } + } + }, + //自定义下拉刷新被复位 + _onRestore() { + this.refresherTriggered = 'restore'; + this.$emit('onRestore'); + this.$emit('Restore'); + }, + // #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 + //拖拽开始 + _refresherTouchstart(e) { + if (this._touchDisabled()) return; + const touch = u.getTouch(e); + this._handleRefresherTouchstart(touch); + }, + // #endif + //进一步处理拖拽开始结果 + _handleRefresherTouchstart(touch) { + if (!this.loading && this.isTouchEnded) { + this.isTouchmoving = false; + } + this.isTouchmovingTimeout && clearTimeout(this.isTouchmovingTimeout); + this.isTouchEnded = false; + this.refresherTransition = ''; + this.refresherTouchstartY = touch.touchY; + this.$emit('refresherTouchstart', this.refresherTouchstartY); + this.lastRefresherTouchmove = touch; + this._cleanRefresherCompleteTimeout(); + this._cleanRefresherEndTimeout(); + }, + // #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 + //拖拽中 + _refresherTouchmove(e) { + const currentTimeStamp = u.getTime(); + let touch = null; + let refresherTouchmoveY = 0; + if (this.watchTouchDirectionChange) { + touch = u.getTouch(e); + refresherTouchmoveY = touch.touchY; + const direction = refresherTouchmoveY > this.oldRefresherTouchmoveY ? 'top' : 'bottom'; + direction === this.oldTouchDirection && this._handleTouchDirectionChange({direction}); + this.oldTouchDirection = direction; + this.oldRefresherTouchmoveY = refresherTouchmoveY; + } + if (this.pullDownTimeStamp && currentTimeStamp - this.pullDownTimeStamp <= this.pullDownDisTimeStamp) return; + if (this._touchDisabled()) return; + this.pullDownTimeStamp = Number(currentTimeStamp); + touch = u.getTouch(e); + refresherTouchmoveY = touch.touchY; + let moveDis = refresherTouchmoveY - this.refresherTouchstartY; + if (moveDis < 0) return; + if (this.refresherMaxAngle >= 0 && this.refresherMaxAngle <= 90 && this.lastRefresherTouchmove && this.lastRefresherTouchmove.touchY <= refresherTouchmoveY) { + if (!moveDis && !this.refresherAngleEnableChangeContinued && this.moveDis < 1 && !this.refresherReachMaxAngle) return; + const x = Math.abs(touch.touchX - this.lastRefresherTouchmove.touchX); + const y = Math.abs(refresherTouchmoveY - this.lastRefresherTouchmove.touchY); + const z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); + if ((x || y) && x > 1) { + const angle = Math.asin(y / z) / Math.PI * 180; + if (angle < this.refresherMaxAngle) { + this.lastRefresherTouchmove = touch; + this.refresherReachMaxAngle = false; + return; + } + } + } + moveDis = this._getFinalRefresherMoveDis(moveDis); + this._handleRefresherTouchmove(moveDis, touch); + if (!this.disabledBounce) { + if(this.isIos){ + // #ifndef MP-LARK + this._handleScrollViewDisableBounce({bounce: false}); + // #endif + } + this.disabledBounce = true; + } + this._emitTouchmove({pullingDistance:moveDis,dy:this.moveDis - this.oldMoveDis}); + }, + // #endif + //进一步处理拖拽中结果 + _handleRefresherTouchmove(moveDis, touch) { + this.refresherReachMaxAngle = true; + this.isTouchmovingTimeout && clearTimeout(this.isTouchmovingTimeout); + this.isTouchmoving = true; + //this.refresherTransition = ''; + this.isTouchEnded = false; + this.refresherStatus = moveDis >= this.finalRefresherThreshold ? Enum.Refresher.ReleaseToRefresh : this.refresherStatus = Enum.Refresher.Default; + // #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 + // this.scrollEnable = false; + this.refresherTransform = `translateY(${moveDis}px)`; + this.lastRefresherTouchmove = touch; + // #endif + this.moveDis = moveDis; + }, + // #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 + //拖拽结束 + _refresherTouchend(e) { + if (this._touchDisabled() || !this.isTouchmoving) return; + const touch = u.getTouch(e); + let refresherTouchendY = touch.touchY; + let moveDis = refresherTouchendY - this.refresherTouchstartY; + moveDis = this._getFinalRefresherMoveDis(moveDis); + this._handleRefresherTouchend(moveDis); + this._handleScrollViewDisableBounce({bounce: true}); + this.disabledBounce = false; + }, + // #endif + //进一步处理拖拽结束结果 + _handleRefresherTouchend(moveDis) { + // #ifndef APP-PLUS || H5 || MP-WEIXIN + if (!this.isTouchmoving) return; + // #endif + this.isTouchmovingTimeout && clearTimeout(this.isTouchmovingTimeout); + this.refresherReachMaxAngle = true; + if (moveDis < 0 && this.usePageScroll && this.loadingMoreEnabled && this.useCustomRefresher && this.pageScrollTop === -1) { + if (this.showConsoleError) { + u.consoleErr('usePageScroll为true并且自定义下拉刷新时必须引入mixin或在page滚动时通过调用z-paging组件的updatePageScrollTop方法设置当前的scrollTop'); + } + } + this.isTouchEnded = true; + if (moveDis >= this.finalRefresherThreshold && this.refresherStatus === Enum.Refresher.ReleaseToRefresh) { + // #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 + this.refresherTransform = `translateY(${this.finalRefresherThreshold}px)`; + // #endif + this.moveDis = this.finalRefresherThreshold; + this.refresherStatus = Enum.Refresher.Loading; + this._doRefresherLoad(); + } else { + this._refresherEnd(); + this.isTouchmovingTimeout = setTimeout(() => { + this.isTouchmoving = false; + }, this.refresherDefaultDuration); + } + this.scrollEnable = true; + this.$emit('refresherTouchend', moveDis); + }, + //处理scroll-view bounce是否生效 + _handleScrollViewDisableBounce(e) { + if (!this.usePageScroll && !this.scrollToTopBounceEnabled) { + this.refresherTransition = ''; + this.scrollEnable = e.bounce; + } + }, + //wxs正在下拉状态改变处理 + _handleWxsPullingDownStatusChange(onPullingDown) { + this.wxsOnPullingDown = onPullingDown; + if (onPullingDown && !this.useChatRecordMode) { + this.renderPropScrollTop = 0; + } + }, + //wxs正在下拉处理 + _handleWxsPullingDown(e){ + this._emitTouchmove({pullingDistance:e.moveDis,dy:e.diffDis}); + }, + //wxs触摸方向改变 + _handleTouchDirectionChange(e) { + this.$emit('touchDirectionChange',e.direction); + }, + //wxs通知更新其props + _handlePropUpdate(e){ + this.wxsPropType = u.getTime().toString(); + }, + //下拉刷新结束 + _refresherEnd(shouldEndLoadingDelay = true, fromAddData = false, isUserPullDown = false, setLoading = true) { + if (this.loadingType === Enum.LoadingType.Refresher) { + let refresherCompleteDelay = 0; + if(fromAddData && (isUserPullDown || this.showRefresherWhenReload)){ + refresherCompleteDelay = this.refresherCompleteDuration > 700 ? 1 : this.refresherCompleteDelay; + } + const refresherStatus = refresherCompleteDelay > 0 ? Enum.Refresher.Complete : Enum.Refresher.Default; + if (this.finalShowRefresherWhenReload) { + const stackCount = this.refresherRevealStackCount; + this.refresherRevealStackCount--; + if (stackCount > 1) return; + } + this._cleanRefresherEndTimeout(); + this.refresherEndTimeout = setTimeout(() => { + this.refresherStatus = refresherStatus; + }, this.refresherStatus !== Enum.Refresher.Default && refresherStatus === Enum.Refresher.Default ? this.refresherCompleteDuration : 0); + + // #ifndef APP-NVUE + if (refresherCompleteDelay > 0) { + this.isRefresherInComplete = true; + } + // #endif + this._cleanRefresherCompleteTimeout(); + this.refresherCompleteTimeout = setTimeout(() => { + let animateDuration = 1; + const animateType = this.refresherEndBounceEnabled && fromAddData ? 'cubic-bezier(0.19,1.64,0.42,0.72)' : 'linear'; + if (fromAddData) { + animateDuration = this.refresherEndBounceEnabled ? this.refresherCompleteDuration / 1000 : this.refresherCompleteDuration / 3000; + } + this.refresherTransition = `transform ${fromAddData ? animateDuration : this.refresherDefaultDuration / 1000}s ${animateType}`; + // #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 + this.refresherTransform = 'translateY(0px)'; + // #endif + // #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 + this.wxsPropType = this.refresherTransition + 'end' + u.getTime(); + // #endif + // #ifdef APP-NVUE + this._nRefresherEnd(); + // #endif + this.moveDis = 0; + // #ifndef APP-NVUE + if (refresherStatus === Enum.Refresher.Complete) { + if (this.refresherCompleteSubTimeout) { + clearTimeout(this.refresherCompleteSubTimeout); + this.refresherCompleteSubTimeout = null; + } + this.refresherCompleteSubTimeout = setTimeout(() => { + this.$nextTick(() => { + this.refresherStatus = Enum.Refresher.Default; + this.isRefresherInComplete = false; + }) + }, animateDuration * 800); + } + // #endif + }, refresherCompleteDelay); + } + if (setLoading) { + setTimeout(() => { + this.loading = false; + }, shouldEndLoadingDelay ? c.delayTime : 0); + isUserPullDown && this._onRestore(); + } + }, + //模拟用户手动触发下拉刷新 + _doRefresherRefreshAnimate() { + this._cleanRefresherCompleteTimeout(); + // #ifndef APP-NVUE + const doRefreshAnimateAfter = !this.doRefreshAnimateAfter && (this.finalShowRefresherWhenReload) && this + .customRefresherHeight === -1 && this.refresherThreshold === '80rpx'; + if (doRefreshAnimateAfter) { + this.doRefreshAnimateAfter = true; + return; + } + // #endif + this.refresherRevealStackCount++; + // #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 + this.refresherTransform = `translateY(${this.finalRefresherThreshold}px)`; + // #endif + // #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 + this.wxsPropType = 'begin' + u.getTime(); + // #endif + this.moveDis = this.finalRefresherThreshold; + this.refresherStatus = Enum.Refresher.Loading; + this.isTouchmoving = true; + this.isTouchmovingTimeout && clearTimeout(this.isTouchmovingTimeout); + this._doRefresherLoad(false); + }, + //触发下拉刷新 + _doRefresherLoad(isUserPullDown=true) { + this._onRefresh(false,isUserPullDown); + this.loading = true; + }, + //获取处理后的moveDis + _getFinalRefresherMoveDis(moveDis) { + moveDis = moveDis * 0.85; + if (moveDis >= this.finalRefresherThreshold) { + moveDis = this.finalRefresherThreshold + (moveDis - this.finalRefresherThreshold) * (1 - this.finalRefresherOutRate); + } + return moveDis; + }, + // #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 + //判断touch手势是否要触发 + _touchDisabled() { + let checkOldScrollTop = this.oldScrollTop > 5; + return this.loading || this.isRefresherInComplete || this.useChatRecordMode || !this.refresherEnabled || !this.useCustomRefresher ||(this.usePageScroll && this.useCustomRefresher && this.pageScrollTop > 10) || (!(this.usePageScroll && this.useCustomRefresher) && checkOldScrollTop); + }, + // #endif + //更新自定义下拉刷新view高度 + _updateCustomRefresherHeight() { + this._getNodeClientRect('.zp-custom-refresher-slot-view').then((res) => { + if (res) { + this.customRefresherHeight = res[0].height; + if (this.customRefresherHeight > 0) { + this.showCustomRefresher = true; + } + } else { + this.customRefresherHeight = 0; + } + if (this.doRefreshAnimateAfter) { + this.doRefreshAnimateAfter = false; + this._doRefresherRefreshAnimate(); + } + }); + }, + //发射pullingDown事件 + _emitTouchmove(e){ + // #ifndef APP-NVUE + e.viewHeight = this.finalRefresherThreshold; + // #endif + e.rate = e.pullingDistance / e.viewHeight; + if(this.hasTouchmove){ + this.$emit('refresherTouchmove',e); + } + }, + //清除refresherCompleteTimeout + _cleanRefresherCompleteTimeout() { + this.refresherCompleteTimeout = this._cleanTimeout(this.refresherCompleteTimeout); + // #ifdef APP-NVUE + this._nRefresherEnd(false); + // #endif + }, + //清除refresherEndTimeout + _cleanRefresherEndTimeout() { + this.refresherEndTimeout = this._cleanTimeout(this.refresherEndTimeout); + }, + } +} + +export default ZPRefresher; diff --git a/components/z-paging/js/modules/scroller.js b/components/z-paging/js/modules/scroller.js new file mode 100644 index 0000000..73d50a1 --- /dev/null +++ b/components/z-paging/js/modules/scroller.js @@ -0,0 +1,469 @@ +// [z-paging]scroll相关模块 +import u from '.././z-paging-utils' +import Enum from '.././z-paging-enum' + +// #ifdef APP-NVUE +const weexDom = weex.requireModule('dom'); +// #endif +const ZPScroller = { + props: { + //使用页面滚动,默认为否,当设置为是时则使用页面的滚动而非此组件内部的scroll-view的滚动,使用页面滚动时z-paging无需设置确定的高度且对于长列表展示性能更高,但配置会略微繁琐 + usePageScroll: { + type: Boolean, + default: u.gc('usePageScroll', false) + }, + //是否可以滚动,使用内置scroll-view和nvue时有效,默认为是 + scrollable: { + type: Boolean, + default: u.gc('scrollable', true) + }, + //控制是否出现滚动条,默认为是 + showScrollbar: { + type: Boolean, + default: u.gc('showScrollbar', true) + }, + //是否允许横向滚动,默认为否 + scrollX: { + type: Boolean, + default: u.gc('scrollX', false) + }, + //iOS设备上滚动到顶部时是否允许回弹效果,默认为否。关闭回弹效果后可使滚动到顶部与下拉刷新更连贯,但是有吸顶view时滚动到顶部时可能出现抖动。 + scrollToTopBounceEnabled: { + type: Boolean, + default: u.gc('scrollToTopBounceEnabled', false) + }, + //iOS设备上滚动到底部时是否允许回弹效果,默认为是。 + scrollToBottomBounceEnabled: { + type: Boolean, + default: u.gc('scrollToBottomBounceEnabled', true) + }, + //在设置滚动条位置时使用动画过渡,默认为否 + scrollWithAnimation: { + type: Boolean, + default: u.gc('scrollWithAnimation', false) + }, + //值应为某子元素id(id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素 + scrollIntoView: { + type: String, + default: u.gc('scrollIntoView', '') + }, + }, + data() { + return { + scrollTop: 0, + oldScrollTop: 0, + scrollViewStyle: {}, + scrollViewContainerStyle: {}, + scrollViewInStyle: {}, + pageScrollTop: -1, + scrollEnable: true, + privateScrollWithAnimation: -1, + cacheScrollNodeHeight: -1 + } + }, + watch: { + oldScrollTop(newVal, oldVal) { + !this.usePageScroll && this._scrollTopChange(newVal,oldVal,false); + }, + pageScrollTop(newVal, oldVal) { + this.usePageScroll && this._scrollTopChange(newVal,oldVal,true); + }, + usePageScroll: { + handler(newVal) { + this.$nextTick(() => { + this.renderPropUsePageScroll = newVal; + }) + if (this.loaded && this.autoHeight) { + this._setAutoHeight(!newVal); + } + // #ifdef H5 + if (newVal) { + this.$nextTick(()=>{ + const mainScrollRef = this.$refs['zp-scroll-view'].$refs.main; + if (mainScrollRef) { + mainScrollRef.style = {}; + } + }) + } + // #endif + }, + immediate: true + }, + finalScrollTop(newVal, oldVal) { + if (!this.useChatRecordMode) { + this.renderPropScrollTop = newVal < 6 ? 0 : 10; + } + }, + }, + computed: { + finalScrollWithAnimation() { + if (this.privateScrollWithAnimation !== -1) { + const scrollWithAnimation = this.privateScrollWithAnimation === 1; + this.privateScrollWithAnimation = -1; + return scrollWithAnimation; + } + return this.scrollWithAnimation; + }, + finalScrollViewStyle() { + if (this.superContentZIndex != 1) { + this.scrollViewStyle['z-index'] = this.superContentZIndex; + this.scrollViewStyle['position'] = 'relative'; + } + return this.scrollViewStyle; + }, + finalScrollTop() { + return this.usePageScroll ? this.pageScrollTop : this.oldScrollTop; + }, + finalIsOldWebView() { + return this.isOldWebView && !this.usePageScroll; + } + }, + methods: { + //滚动到顶部,animate为是否展示滚动动画,默认为是 + scrollToTop(animate,checkReverse = true) { + // #ifdef APP-NVUE + if (checkReverse && this.useChatRecordMode) { + if(!this.nIsFirstPageAndNoMore){ + this.scrollToBottom(animate, false); + return; + } + } + // #endif + this.$nextTick(() => { + this._scrollToTop(animate, false); + // #ifdef APP-NVUE + if (this.nvueFastScroll && animate) { + setTimeout(() => { + this._scrollToTop(false, false); + }, 150); + } + // #endif + }) + }, + //滚动到底部,animate为是否展示滚动动画,默认为是 + scrollToBottom(animate,checkReverse = true) { + // #ifdef APP-NVUE + if (checkReverse && this.useChatRecordMode) { + if(!this.nIsFirstPageAndNoMore){ + this.scrollToTop(animate, false); + return; + } + } + // #endif + this.$nextTick(() => { + this._scrollToBottom(animate); + // #ifdef APP-NVUE + if (this.nvueFastScroll && animate) { + setTimeout(() => { + this._scrollToBottom(false); + }, 150); + } + // #endif + }) + }, + //滚动到指定view(vue中有效)。sel为需要滚动的view的id值,不包含"#";offset为偏移量,单位为px;animate为是否展示滚动动画,默认为否 + scrollIntoViewById(sel, offset, animate) { + this._scrollIntoView(sel, offset, animate); + }, + //滚动到指定view(vue中有效)。nodeTop为需要滚动的view的top值(通过uni.createSelectorQuery()获取);offset为偏移量,单位为px;animate为是否展示滚动动画,默认为否 + scrollIntoViewByNodeTop(nodeTop, offset, animate) { + this.scrollTop = this.oldScrollTop; + this.$nextTick(() => { + this._scrollIntoViewByNodeTop(nodeTop, offset, animate); + }) + }, + //滚动到指定位置(vue中有效)。y为与顶部的距离,单位为px;offset为偏移量,单位为px;animate为是否展示滚动动画,默认为否 + scrollToY(y, offset, animate) { + this.scrollTop = this.oldScrollTop; + this.$nextTick(() => { + this._scrollToY(y, offset, animate); + }) + }, + //滚动到指定view(nvue中有效)。index为需要滚动的view的index(第几个);offset为偏移量,单位为px;animate为是否展示滚动动画,默认为否 + scrollIntoViewByIndex(index, offset, animate) { + this._scrollIntoView(index, offset, animate); + }, + //滚动到指定view(nvue中有效)。view为需要滚动的view(通过`this.$refs.xxx`获取),不包含"#";offset为偏移量,单位为px;animate为是否展示滚动动画,默认为否 + scrollIntoViewByView(view, offset, animate) { + this._scrollIntoView(view, offset, animate); + }, + //当使用页面滚动并且自定义下拉刷新时,请在页面的onPageScroll中调用此方法,告知z-paging当前的pageScrollTop,否则会导致在任意位置都可以下拉刷新 + updatePageScrollTop(value) { + if (value == undefined) { + u.consoleErr('updatePageScrollTop方法缺少参数,请将页面onPageScroll事件中的scrollTop传递给此方法'); + return; + } + this.pageScrollTop = value; + }, + //当使用页面滚动并且设置了slot="top"时,默认初次加载会自动获取其高度,并使内部容器下移,当slot="top"的view高度动态改变时,在其高度需要更新时调用此方法 + updatePageScrollTopHeight() { + this._updatePageScrollTopOrBottomHeight('top'); + }, + //当使用页面滚动并且设置了slot="bottom"时,默认初次加载会自动获取其高度,并使内部容器下移,当slot="bottom"的view高度动态改变时,在其高度需要更新时调用此方法 + updatePageScrollBottomHeight() { + this._updatePageScrollTopOrBottomHeight('bottom'); + }, + //更新z-paging内置scroll-view的scrollTop + updateScrollViewScrollTop(scrollTop, animate = true) { + this.privateScrollWithAnimation = animate ? 1 : 0; + this.scrollTop = this.oldScrollTop; + this.$nextTick(() => { + this.scrollTop = scrollTop; + this.oldScrollTop = this.scrollTop; + }); + }, + + //当滚动到顶部时 + _scrollToUpper() { + this.$emit('scrolltoupper'); + this.$emit('scrollTopChange', 0); + this.$nextTick(() => { + this.oldScrollTop = 0; + }) + if (!this.useChatRecordMode) return; + if (this.loadingStatus === Enum.More.NoMore) return; + this._onLoadingMore('click'); + }, + //滚动到顶部 + _scrollToTop(animate = true, isPrivate = true) { + // #ifdef APP-NVUE + const el = this.$refs['zp-n-list-top-tag']; + if (this.usePageScroll) { + this._getNodeClientRect('zp-page-scroll-top', false).then((node) => { + let nodeHeight = 0; + if (node) { + nodeHeight = node[0].height; + } + weexDom.scrollToElement(el, { + offset: -nodeHeight, + animated: animate + }); + }); + } else { + if(!this.isIos && this.nvueListIs === 'scroller'){ + this._getNodeClientRect('zp-n-refresh-container', false).then((node) => { + let nodeHeight = 0; + if (node) { + nodeHeight = node[0].height; + } + weexDom.scrollToElement(el, { + offset: -nodeHeight, + animated: animate + }); + }); + }else{ + weexDom.scrollToElement(el, { + offset: 0, + animated: animate + }); + } + } + return; + // #endif + if (this.usePageScroll) { + this.$nextTick(() => { + uni.pageScrollTo({ + scrollTop: 0, + duration: animate ? 100 : 0, + }); + }); + return; + } + this.privateScrollWithAnimation = animate ? 1 : 0; + this.scrollTop = this.oldScrollTop; + this.$nextTick(() => { + this.scrollTop = 0; + this.oldScrollTop = this.scrollTop; + }); + }, + //滚动到底部 + async _scrollToBottom(animate = true) { + // #ifdef APP-NVUE + const el = this.$refs['zp-n-list-bottom-tag']; + if (el) { + weexDom.scrollToElement(el, { + offset: 0, + animated: animate + }); + } else { + u.consoleErr('滚动到底部失败,因为您设置了hideNvueBottomTag为true'); + } + return; + // #endif + if (this.usePageScroll) { + this.$nextTick(() => { + uni.pageScrollTo({ + scrollTop: Number.MAX_VALUE, + duration: animate ? 100 : 0, + }); + }); + return; + } + try { + this.privateScrollWithAnimation = animate ? 1 : 0; + let pagingContainerH = 0; + let scrollViewH = 0; + const pagingContainerNode = await this._getNodeClientRect('.zp-paging-container'); + const scrollViewNode = await this._getNodeClientRect('.zp-scroll-view'); + if (pagingContainerNode) { + pagingContainerH = pagingContainerNode[0].height; + } + if (scrollViewNode) { + scrollViewH = scrollViewNode[0].height; + } + if (pagingContainerH > scrollViewH) { + this.scrollTop = this.oldScrollTop; + this.$nextTick(() => { + this.scrollTop = pagingContainerH - scrollViewH + this.virtualPlaceholderTopHeight; + this.oldScrollTop = this.scrollTop; + }); + } + } catch (e) {} + }, + //滚动到指定view + _scrollIntoView(sel, offset = 0, animate = false, finishCallback) { + try { + this.scrollTop = this.oldScrollTop; + this.$nextTick(() => { + // #ifdef APP-NVUE + const refs = this.$parent.$refs; + if (!refs) return; + const dataType = Object.prototype.toString.call(sel); + let el = null; + if (dataType === '[object Number]') { + const els = refs[`z-paging-${sel}`]; + el = els ? els[0] : null; + } else if (dataType === '[object Array]') { + el = sel[0]; + } else { + el = sel; + } + if (el) { + weexDom.scrollToElement(el, { + offset: -offset, + animated: animate + }); + } else { + u.consoleErr('在nvue中滚动到指定位置,cell必须设置 :ref="`z-paging-${index}`"'); + } + return; + // #endif + if (sel.indexOf('#') != -1) { + sel = sel.replace('#', ''); + } + this._getNodeClientRect('#' + sel, false).then((node) => { + if (node) { + let nodeTop = node[0].top; + this._scrollIntoViewByNodeTop(nodeTop, offset, animate); + if (finishCallback) { + finishCallback(); + } + } + }); + }); + } catch (e) {} + }, + //通过nodeTop滚动到指定view + _scrollIntoViewByNodeTop(nodeTop, offset = 0, animate = false) { + this._scrollToY(nodeTop,offset,animate,true); + }, + //滚动到指定位置 + _scrollToY(y, offset = 0, animate = false, addScrollTop = false) { + this.privateScrollWithAnimation = animate ? 1 : 0; + if (this.usePageScroll) { + uni.pageScrollTo({ + scrollTop: y - offset, + duration: animate ? 100 : 0 + }); + } else { + if(addScrollTop){ + y += this.oldScrollTop; + } + this.scrollTop = y - offset; + this.oldScrollTop = this.scrollTop; + } + }, + //scroll-view滚动中 + _scroll(e) { + this.$emit('scroll', e); + const scrollTop = e.detail.scrollTop; + // #ifndef APP-NVUE + this.finalUseVirtualList && this._updateVirtualScroll(scrollTop,this.oldScrollTop - scrollTop); + // #endif + this.oldScrollTop = scrollTop; + const scrollDiff = e.detail.scrollHeight - this.oldScrollTop; + !this.isIos && this._checkScrolledToBottom(scrollDiff); + }, + //scrollTop改变时触发 + _scrollTopChange(newVal,oldVal,isPageScrollTop){ + this.$emit('scrollTopChange', newVal); + this.$emit('update:scrollTop', newVal); + this._checkShouldShowBackToTop(newVal, oldVal); + const scrollTop = this.isIos ? (newVal > 5 ? 6 : 0) : newVal; + if (isPageScrollTop) { + this.wxsPageScrollTop = scrollTop; + } else { + this.wxsScrollTop = scrollTop; + } + }, + //更新使用页面滚动时slot="top"或"bottom"插入view的高度 + _updatePageScrollTopOrBottomHeight(type) { + // #ifndef APP-NVUE + if (!this.usePageScroll) return; + // #endif + this._doCheckScrollViewShouldFullHeight(this.realTotalData); + const node = `.zp-page-${type}`; + const marginText = `margin${type.slice(0,1).toUpperCase() + type.slice(1)}`; + let safeAreaInsetBottomAdd = this.safeAreaInsetBottom; + // #ifdef APP-NVUE + if (!this.usePageScroll) { + safeAreaInsetBottomAdd = false; + } + // #endif + this.$nextTick(() => { + let delayTime = 0; + // #ifdef MP-BAIDU || APP-NVUE + delayTime = 10; + // #endif + setTimeout(() => { + this._getNodeClientRect(node).then((res) => { + if (res) { + let pageScrollNodeHeight = res[0].height; + if (type === 'bottom') { + if (safeAreaInsetBottomAdd) { + pageScrollNodeHeight += this.safeAreaBottom; + } + } else { + this.cacheTopHeight = pageScrollNodeHeight; + } + this.$set(this.scrollViewStyle, marginText, + `${pageScrollNodeHeight}px`); + } else if (safeAreaInsetBottomAdd) { + this.$set(this.scrollViewStyle, marginText, `${this.safeAreaBottom}px`); + } + }); + }, delayTime) + }) + }, + //获取slot="left"和slot="right"宽度并且更新布局 + _updateLeftAndRightWidth(){ + if (!this.finalIsOldWebView) return; + this.$nextTick(() => { + let delayTime = 0; + // #ifdef MP-BAIDU + delayTime = 10; + // #endif + setTimeout(() => { + this._getNodeClientRect('.zp-page-left').then((res) => { + this.scrollViewContainerStyle['left'] = res ? res[0].width + 'px' : 0; + }); + this._getNodeClientRect('.zp-page-right').then((res) => { + this.scrollViewContainerStyle['right'] = res ? res[0].width + 'px' : 0; + }); + }, delayTime) + }) + } + } +} + +export default ZPScroller; diff --git a/components/z-paging/js/modules/virtual-list.js b/components/z-paging/js/modules/virtual-list.js new file mode 100644 index 0000000..6a44fcd --- /dev/null +++ b/components/z-paging/js/modules/virtual-list.js @@ -0,0 +1,374 @@ +// [z-paging]虚拟列表模块 +import u from '.././z-paging-utils' +import c from '.././z-paging-constant' +import Enum from '.././z-paging-enum' + +const ZPVirtualList = { + props: { + //是否使用虚拟列表,默认为否 + useVirtualList: { + type: Boolean, + default: u.gc('useVirtualList', false) + }, + //是否在z-paging内部循环渲染列表(内置列表),默认为否。若use-virtual-list为true,则此项恒为true + useInnerList: { + type: Boolean, + default: u.gc('useInnerList', false) + }, + //强制关闭inner-list,默认为false,如果为true将强制关闭innerList,适用于开启了虚拟列表后需要强制关闭inner-list的情况 + forceCloseInnerList: { + type: Boolean, + default: u.gc('forceCloseInnerList', false) + }, + //内置列表cell的key名称,仅nvue有效,在nvue中开启use-inner-list时必须填此项 + cellKeyName: { + type: String, + default: u.gc('cellKeyName', '') + }, + //innerList样式 + innerListStyle: { + type: Object, + default: function() { + return u.gc('innerListStyle', {}); + } + }, + //innerCell样式 + innerCellStyle: { + type: Object, + default: function() { + return u.gc('innerCellStyle', {}); + } + }, + //预加载的列表可视范围(列表高度)页数,默认为7,即预加载当前页及上下各7页的cell。此数值越大,则虚拟列表中加载的dom越多,内存消耗越大(会维持在一个稳定值),但增加预加载页面数量可缓解快速滚动短暂白屏问题 + preloadPage: { + type: [Number, String], + default: u.gc('preloadPage', 7), + validator: (value) => { + if (value <= 0) u.consoleErr('preload-page必须大于0!'); + return value > 0; + } + }, + //虚拟列表cell高度模式,默认为fixed,也就是每个cell高度完全相同,将以第一个cell高度为准进行计算。可选值【dynamic】,即代表高度是动态非固定的,【dynamic】性能低于【fixed】。 + cellHeightMode: { + type: String, + default: u.gc('cellHeightMode', 'fixed') + }, + //虚拟列表列数,默认为1。常用于每行有多列的情况,例如每行有2列数据,需要将此值设置为2 + virtualListCol: { + type: [Number, String], + default: u.gc('virtualListCol', 1) + }, + //虚拟列表scroll取样帧率,默认为60,过高可能出现卡顿等问题 + virtualScrollFps: { + type: [Number, String], + default: u.gc('virtualScrollFps', 60) + }, + }, + data() { + return { + virtualListKey: u.getInstanceId(), + virtualPageHeight: 0, + virtualCellHeight: 0, + virtualScrollTimeStamp: 0, + + virtualList: [], + virtualPlaceholderTopHeight: 0, + virtualPlaceholderBottomHeight: 0, + virtualTopRangeIndex: 0, + virtualBottomRangeIndex: 0, + lastVirtualTopRangeIndex: 0, + lastVirtualBottomRangeIndex: 0, + + virtualHeightCacheList: [], + + getCellHeightRetryCount: { + fixed: 0, + dynamic: 0 + }, + pagingOrgTop: -1, + updateVirtualListFromDataChange: false + } + }, + watch: { + realTotalData(newVal) { + // #ifndef APP-NVUE + if (this.finalUseVirtualList) { + this.updateVirtualListFromDataChange = true; + this.$nextTick(() => { + if (!newVal.length) { + this._resetDynamicListState(!this.isUserPullDown); + } + this.getCellHeightRetryCount.fixed = 0; + this.finalUseVirtualList && newVal.length && this.cellHeightMode === Enum.CellHeightMode.Fixed && this.isFirstPage && this._updateFixedCellHeight(); + this.finalUseVirtualList && this._updateVirtualScroll(this.oldScrollTop); + }) + } + // #endif + }, + virtualList(newVal){ + this.$emit('update:virtualList', newVal); + this.$emit('virtualListChange', newVal); + } + }, + computed: { + finalUseVirtualList() { + if (this.useVirtualList && this.usePageScroll){ + u.consoleErr('使用页面滚动时,开启虚拟列表无效!'); + } + return this.useVirtualList && !this.usePageScroll; + }, + finalUseInnerList() { + return this.useInnerList || (this.finalUseVirtualList && !this.forceCloseInnerList) + }, + finalCellKeyName() { + // #ifdef APP-NVUE + if (this.finalUseVirtualList){ + if (!this.cellKeyName.length){ + u.consoleErr('在nvue中开启use-virtual-list必须设置cell-key-name,否则将可能导致列表渲染错误!'); + } + } + // #endif + return this.cellKeyName; + }, + finalVirtualPageHeight(){ + return this.virtualPageHeight > 0 ? this.virtualPageHeight : this.windowHeight; + return virtualPageHeight * this.preloadPage; + }, + virtualRangePageHeight(){ + return this.finalVirtualPageHeight * this.preloadPage; + }, + virtualScrollDisTimeStamp() { + return 1000 / this.virtualScrollFps; + }, + }, + methods: { + //初始化虚拟列表 + _virtualListInit() { + this.$nextTick(() => { + setTimeout(() => { + this._getNodeClientRect('.zp-scroll-view').then(node => { + if (node && node.length) { + this.pagingOrgTop = node[0].top; + this.virtualPageHeight = node[0].height; + } + }); + }, 100); + }) + }, + //cellHeightMode为fixed时获取第一个cell高度 + _updateFixedCellHeight() { + this.$nextTick(() => { + const updateFixedCellHeightTimeout = setTimeout(() => { + this._getNodeClientRect(`#zp-${0}`,this.finalUseInnerList).then(cellNode => { + const hasCellNode = cellNode && cellNode.length; + if (!hasCellNode) { + clearTimeout(updateFixedCellHeightTimeout); + if (this.getCellHeightRetryCount.fixed > 10) { + u.consoleErr('获取虚拟列表cell高度失败,可能是for循环cell处没有写:id="`zp-${item.zp_index}`",请检查您的代码!') + return; + } + this.getCellHeightRetryCount.fixed++; + this._updateFixedCellHeight(); + } else { + this.virtualCellHeight = cellNode[0].height; + this._updateVirtualScroll(this.oldScrollTop); + } + }); + }, 100); + }) + }, + //cellHeightMode为dynamic时获取每个cell高度 + _updateDynamicCellHeight(list) { + this.$nextTick(() => { + const updateDynamicCellHeightTimeout = setTimeout(async () => { + for (let i = 0; i < list.length; i++) { + let item = list[i]; + const cellNode = await this._getNodeClientRect(`#zp-${item[c.listCellIndexKey]}`,this.finalUseInnerList); + const hasCellNode = cellNode && cellNode.length; + const currentHeight = hasCellNode ? cellNode[0].height : 0; + if (!hasCellNode) { + clearTimeout(updateDynamicCellHeightTimeout); + this.virtualHeightCacheList = this.virtualHeightCacheList.slice(-i); + if (this.getCellHeightRetryCount.dynamic > 10) { + u.consoleErr('获取虚拟列表cell高度失败,可能是for循环cell处没有写:id="`zp-${item.zp_index}`",请检查您的代码!') + return; + } + this.getCellHeightRetryCount.dynamic++; + this._updateDynamicCellHeight(list); + break; + } + let lastHeightCache = null; + if (this.virtualHeightCacheList.length) { + lastHeightCache = this.virtualHeightCacheList.slice(-1)[0]; + } + const lastHeight = lastHeightCache ? lastHeightCache.totalHeight : 0; + this.virtualHeightCacheList.push({ + height: currentHeight, + lastHeight: lastHeight, + totalHeight: lastHeight + currentHeight + }); + } + this._updateVirtualScroll(this.oldScrollTop); + }, 100) + }) + }, + //设置cellItem的index + _setCellIndex(list, isFirstPage) { + let lastItem = null; + let lastItemIndex = 0; + if (!isFirstPage) { + lastItemIndex = this.realTotalData.length; + if (this.realTotalData.length) { + lastItem = this.realTotalData.slice(-1)[0]; + } + if (lastItem && lastItem[c.listCellIndexKey] !== undefined) { + lastItemIndex = lastItem[c.listCellIndexKey] + 1; + } + } else { + this._resetDynamicListState(); + } + for (let i = 0; i < list.length; i++) { + let item = list[i]; + if (!item || Object.prototype.toString.call(item) !== '[object Object]') { + item = {item}; + } + item[c.listCellIndexKey] = lastItemIndex + i; + item[c.listCellIndexUniqueKey] = `${this.virtualListKey}-${item[c.listCellIndexKey]}`; + list[i] = item; + } + this.getCellHeightRetryCount.dynamic = 0; + this.cellHeightMode === Enum.CellHeightMode.Dynamic && this._updateDynamicCellHeight(list); + }, + //更新scroll滚动 + _updateVirtualScroll(scrollTop, scrollDiff = 0) { + const currentTimeStamp = u.getTime(); + if (scrollTop === 0) { + this._resetTopRange(); + } + if (scrollTop !== 0 && this.virtualScrollTimeStamp && currentTimeStamp - this.virtualScrollTimeStamp <= this.virtualScrollDisTimeStamp) { + return; + } + this.virtualScrollTimeStamp = Number(currentTimeStamp); + + let scrollIndex = 0; + const cellHeightMode = this.cellHeightMode; + if (cellHeightMode === Enum.CellHeightMode.Fixed) { + scrollIndex = parseInt(scrollTop / this.virtualCellHeight) || 0; + this._updateFixedTopRangeIndex(scrollIndex); + this._updateFixedBottomRangeIndex(scrollIndex); + } else if(cellHeightMode === Enum.CellHeightMode.Dynamic) { + const scrollDirection = scrollDiff > 0 ? 'top' : 'bottom'; + const rangePageHeight = this.virtualRangePageHeight; + const topRangePageOffset = scrollTop - rangePageHeight; + const bottomRangePageOffset = scrollTop + this.finalVirtualPageHeight + rangePageHeight; + + let virtualBottomRangeIndex = 0; + let virtualPlaceholderBottomHeight = 0; + let reachedLimitBottom = false; + let lastHeightCache = null; + const heightCacheList = this.virtualHeightCacheList; + if (heightCacheList.length) { + lastHeightCache = heightCacheList.slice(-1)[0]; + } + let startTopRangeIndex = this.virtualTopRangeIndex; + if (scrollDirection === 'bottom') { + for (let i = startTopRangeIndex; i < heightCacheList.length;i++){ + const heightCacheItem = heightCacheList[i]; + if (heightCacheItem && heightCacheItem.totalHeight > topRangePageOffset) { + this.virtualTopRangeIndex = i; + this.virtualPlaceholderTopHeight = heightCacheItem.lastHeight; + break; + } + } + } else { + let topRangeMatched = false; + for (let i = startTopRangeIndex; i >= 0;i--){ + const heightCacheItem = heightCacheList[i]; + if (heightCacheItem && heightCacheItem.totalHeight < topRangePageOffset) { + this.virtualTopRangeIndex = i; + this.virtualPlaceholderTopHeight = heightCacheItem.lastHeight; + topRangeMatched = true; + break; + } + } + !topRangeMatched && this._resetTopRange(); + } + for (let i = this.virtualTopRangeIndex; i < heightCacheList.length;i++){ + const heightCacheItem = heightCacheList[i]; + if (heightCacheItem && heightCacheItem.totalHeight > bottomRangePageOffset) { + virtualBottomRangeIndex = i; + virtualPlaceholderBottomHeight = lastHeightCache.totalHeight - heightCacheItem.totalHeight; + reachedLimitBottom = true; + break; + } + } + if (!reachedLimitBottom || this.virtualBottomRangeIndex === 0) { + this.virtualBottomRangeIndex = this.realTotalData.length ? this.realTotalData.length - 1 : this.pageSize; + this.virtualPlaceholderBottomHeight = 0; + } else { + this.virtualBottomRangeIndex = virtualBottomRangeIndex; + this.virtualPlaceholderBottomHeight = virtualPlaceholderBottomHeight; + } + this._updateVirtualList(); + } + }, + //更新fixedCell模式下topRangeIndex&placeholderTopHeight + _updateFixedTopRangeIndex(scrollIndex) { + let virtualTopRangeIndex = this.virtualCellHeight === 0 ? 0 : scrollIndex - parseInt(this.finalVirtualPageHeight / this.virtualCellHeight) * this.preloadPage; + virtualTopRangeIndex *= this.virtualListCol; + virtualTopRangeIndex = Math.max(0, virtualTopRangeIndex); + this.virtualTopRangeIndex = virtualTopRangeIndex; + this.virtualPlaceholderTopHeight = (virtualTopRangeIndex / this.virtualListCol) * this.virtualCellHeight; + }, + //更新fixedCell模式下bottomRangeIndex&placeholderBottomHeight + _updateFixedBottomRangeIndex(scrollIndex) { + let virtualBottomRangeIndex = this.virtualCellHeight === 0 ? this.pageSize : scrollIndex + parseInt(this.finalVirtualPageHeight / this.virtualCellHeight) * (this.preloadPage + 1); + virtualBottomRangeIndex *= this.virtualListCol; + virtualBottomRangeIndex = Math.min(this.realTotalData.length, virtualBottomRangeIndex); + this.virtualBottomRangeIndex = virtualBottomRangeIndex; + this.virtualPlaceholderBottomHeight = (this.realTotalData.length - virtualBottomRangeIndex) * this.virtualCellHeight / this.virtualListCol; + this._updateVirtualList(); + }, + //更新virtualList + _updateVirtualList() { + const shouldUpdateList = this.updateVirtualListFromDataChange || (this.lastVirtualTopRangeIndex !== this.virtualTopRangeIndex || this.lastVirtualBottomRangeIndex !== this.virtualBottomRangeIndex); + if (shouldUpdateList) { + this.updateVirtualListFromDataChange = false; + this.lastVirtualTopRangeIndex = this.virtualTopRangeIndex; + this.lastVirtualBottomRangeIndex = this.virtualBottomRangeIndex; + this.virtualList = this.realTotalData.slice(this.virtualTopRangeIndex, this.virtualBottomRangeIndex + 1); + } + }, + //重置动态cell模式下的高度缓存数据、虚拟列表和滚动状态 + _resetDynamicListState(resetVirtualList = false) { + this.virtualHeightCacheList = []; + if (resetVirtualList) { + this.virtualList = []; + } + this.virtualTopRangeIndex = 0; + this.virtualPlaceholderTopHeight = 0; + }, + //重置topRangeIndex和placeholderTopHeight + _resetTopRange() { + this.virtualTopRangeIndex = 0; + this.virtualPlaceholderTopHeight = 0; + this._updateVirtualList(); + }, + //检测虚拟列表当前滚动位置,如发现滚动位置不正确则重新计算虚拟列表相关参数(为解决在App中可能出现的长时间进入后台后打开App白屏的问题) + _checkVirtualListScroll() { + if (this.finalUseVirtualList) { + this.$nextTick(() => { + this._getNodeClientRect('.zp-paging-touch-view').then(node => { + const hasNode = node && node.length; + const currentTop = hasNode ? node[0].top : 0; + if (!hasNode || (currentTop === this.pagingOrgTop && this.virtualPlaceholderTopHeight !== 0)){ + this._updateVirtualScroll(0); + } + }); + }) + } + } + } +} + +export default ZPVirtualList; diff --git a/components/z-paging/js/z-paging-config.js b/components/z-paging/js/z-paging-config.js new file mode 100644 index 0000000..53a9e98 --- /dev/null +++ b/components/z-paging/js/z-paging-config.js @@ -0,0 +1,26 @@ +// [z-paging]处理main.js中的配置信息工具 + +let config = null; +let getedStorage = false; +const storageKey = 'Z-PAGING-CONFIG-STORAGE-KEY' + +function setConfig(value) { + try { + uni.setStorageSync(storageKey, value); + } catch (e) {} +} + +function getConfig() { + try { + if (getedStorage) return config; + config = uni.getStorageSync(storageKey); + getedStorage = true; + } catch (e) { + return null; + } +} + +export default { + setConfig, + getConfig +}; diff --git a/components/z-paging/js/z-paging-constant.js b/components/z-paging/js/z-paging-constant.js new file mode 100644 index 0000000..47b5953 --- /dev/null +++ b/components/z-paging/js/z-paging-constant.js @@ -0,0 +1,21 @@ +// [z-paging]常量 + +const version = '2.3.1'; +const delayTime = 100; +const i18nUpdateKey = 'z-paging-i18n-update'; + +const errorUpdateKey = 'z-paging-error-emit'; +const completeUpdateKey = 'z-paging-complete-emit'; + +const listCellIndexKey = 'zp_index'; +const listCellIndexUniqueKey = 'zp_unique_index'; + +export default { + version, + delayTime, + i18nUpdateKey, + errorUpdateKey, + completeUpdateKey, + listCellIndexKey, + listCellIndexUniqueKey +} \ No newline at end of file diff --git a/components/z-paging/js/z-paging-enum.js b/components/z-paging/js/z-paging-enum.js new file mode 100644 index 0000000..b6a7b0d --- /dev/null +++ b/components/z-paging/js/z-paging-enum.js @@ -0,0 +1,37 @@ +// [z-paging]枚举 + +const Enum = { + //当前加载类型 0.下拉刷新 1.上拉加载更多 + LoadingType: { + Refresher: 0, + LoadingMore: 1 + }, + //下拉刷新状态 0.默认状态 1.松手立即刷新 2.刷新中 3.刷新结束 + Refresher: { + Default: 0, + ReleaseToRefresh: 1, + Loading: 2, + Complete: 3 + }, + //底部加载更多状态 0.默认状态 1.加载中 2.没有更多数据 3.加载失败 + More: { + Default: 0, + Loading: 1, + NoMore: 2, + Fail: 3 + }, + //@query触发来源 0.用户主动下拉刷新 1.通过reload触发 2.通过refresh触发 3.通过滚动到底部加载更多或点击底部加载更多触发 + QueryFrom: { + UserPullDown: 0, + Reload: 1, + Refresh: 2, + LoadingMore: 3 + }, + //虚拟列表cell高度模式 + CellHeightMode: { + Fixed: 'fixed', + Dynamic: 'dynamic' + } +} + +export default Enum; diff --git a/components/z-paging/js/z-paging-i18n.js b/components/z-paging/js/z-paging-i18n.js new file mode 100644 index 0000000..46233c2 --- /dev/null +++ b/components/z-paging/js/z-paging-i18n.js @@ -0,0 +1,133 @@ +// z-paging国际化(支持中文、中文繁体和英文) +const i18nUpdateKey = 'z-paging-i18n-update'; + +const t = { + refresherDefaultText: { + 'en': 'Pull down to refresh', + 'zh-cn': '继续下拉刷新', + 'zh-hant-cn': '繼續下拉重繪', + }, + refresherPullingText: { + 'en': 'Release to refresh', + 'zh-cn': '松开立即刷新', + 'zh-hant-cn': '鬆開立即重繪', + }, + refresherRefreshingText: { + 'en': 'Refreshing...', + 'zh-cn': '正在刷新...', + 'zh-hant-cn': '正在重繪...', + }, + refresherCompleteText: { + 'en': 'Refresh succeeded', + 'zh-cn': '刷新成功', + 'zh-hant-cn': '重繪成功', + }, + loadingMoreDefaultText: { + 'en': 'Click to load more', + 'zh-cn': '点击加载更多', + 'zh-hant-cn': '點擊加載更多', + }, + loadingMoreLoadingText: { + 'en': 'Loading...', + 'zh-cn': '正在加载...', + 'zh-hant-cn': '正在加載...', + }, + loadingMoreNoMoreText: { + 'en': 'No more data', + 'zh-cn': '没有更多了', + 'zh-hant-cn': '沒有更多了', + }, + loadingMoreFailText: { + 'en': 'Load failed,click to reload', + 'zh-cn': '加载失败,点击重新加载', + 'zh-hant-cn': '加載失敗,點擊重新加載', + }, + emptyViewText: { + 'en': 'No data', + 'zh-cn': '没有数据哦~', + 'zh-hant-cn': '沒有數據哦~', + }, + emptyViewReloadText: { + 'en': 'Reload', + 'zh-cn': '重新加载', + 'zh-hant-cn': '重新加載', + }, + emptyViewErrorText: { + 'en': 'Sorry,load failed', + 'zh-cn': '很抱歉,加载失败', + 'zh-hant-cn': '很抱歉,加載失敗', + }, + refresherUpdateTimeText: { + 'en': 'Last update: ', + 'zh-cn': '最后更新:', + 'zh-hant-cn': '最後更新:', + }, + refresherUpdateTimeNoneText: { + 'en': 'None', + 'zh-cn': '无', + 'zh-hant-cn': '無', + }, + refresherUpdateTimeTodayText: { + 'en': 'Today', + 'zh-cn': '今天', + 'zh-hant-cn': '今天', + }, + refresherUpdateTimeYesterdayText: { + 'en': 'Yesterday', + 'zh-cn': '昨天', + 'zh-hant-cn': '昨天', + } +} + + +// 获取当前语言,格式为:zh-cn、zh-hant-cn、en。followSystemLanguage:获取的结果是否是在不跟随系统语言下获取到的 +function getLanguage(followSystemLanguage = true) { + return _getPrivateLanguage(false, followSystemLanguage); +} + +// 获取当前语言,格式为:简体中文、繁體中文、English。followSystemLanguage:获取的结果是否是在不跟随系统语言下获取到的 +function getLanguageName(followSystemLanguage = true) { + const language = getLanguage(followSystemLanguage); + const languageNameMap = { + 'zh-cn': '简体中文', + 'zh-hant-cn': '繁體中文', + 'en': 'English' + }; + return languageNameMap[language]; +} + +//设置当前语言,格式为:zh-cn、zh-hant-cn、en +function setLanguage(myLanguage) { + uni.setStorageSync(i18nUpdateKey, myLanguage); + uni.$emit(i18nUpdateKey, myLanguage); +} + +// 插件内部使用,请勿直接调用 +function _getPrivateLanguage(myLanguage, followSystemLanguage = true) { + let systemLanguage = ''; + if (followSystemLanguage) { + systemLanguage = uni.getSystemInfoSync().language; + } + let language = myLanguage || uni.getStorageSync(i18nUpdateKey) || systemLanguage; + language = language.toLowerCase(); + const reg = new RegExp('_', ''); + language = language.replace(reg, '-'); + if (language.indexOf('zh') !== -1) { + if (language === 'zh' || language === 'zh-cn' || language.indexOf('zh-hans') !== -1) { + return 'zh-cn'; + } + return 'zh-hant-cn'; + } + if (language.indexOf('en') !== -1) { + return 'en'; + } + return 'zh-cn'; +} + +export default { + t, + getLanguage, + getLanguageName, + setLanguage, + _getPrivateLanguage, +} diff --git a/components/z-paging/js/z-paging-interceptor.js b/components/z-paging/js/z-paging-interceptor.js new file mode 100644 index 0000000..b594e4c --- /dev/null +++ b/components/z-paging/js/z-paging-interceptor.js @@ -0,0 +1,34 @@ +// [z-paging]拦截器 + +//拦截&处理@query事件 +function handleQuery(callback) { + try { + setTimeout(function() { + _getApp().globalData.zp_handleQueryCallback = callback; + }, 1); + } catch (e) {} +} + +//拦截&处理@query事件(私有,请勿调用) +function _handleQuery(pageNo, pageSize, from){ + const handleQueryCallback = _getApp().globalData.zp_handleQueryCallback; + if (handleQueryCallback) { + return handleQueryCallback(pageNo, pageSize, from); + } + return [pageNo, pageSize, from]; +} + +//获取当前app对象 +function _getApp(){ + // #ifndef APP-NVUE + return getApp(); + // #endif + // #ifdef APP-NVUE + return getApp({allowDefault: true}); + // #endif +} + +export default { + handleQuery, + _handleQuery +}; diff --git a/components/z-paging/js/z-paging-main.js b/components/z-paging/js/z-paging-main.js new file mode 100644 index 0000000..c47a964 --- /dev/null +++ b/components/z-paging/js/z-paging-main.js @@ -0,0 +1,604 @@ +// [z-paging]核心js + +import zStatic from './z-paging-static' +import c from './z-paging-constant' +import u from './z-paging-utils' + +import zPagingRefresh from '../components/z-paging-refresh' +import zPagingLoadMore from '../components/z-paging-load-more' +import zPagingEmptyView from '../../z-paging-empty-view/z-paging-empty-view' + +// modules +import dataHandleModule from './modules/data-handle' +import i18nModule from './modules/i18n' +import nvueModule from './modules/nvue' +import emptyModule from './modules/empty' +import refresherModule from './modules/refresher' +import loadMoreModule from './modules/load-more' +import scrollerModule from './modules/scroller' +import backToTopModule from './modules/back-to-top' +import virtualListModule from './modules/virtual-list' + +import Enum from './z-paging-enum' + +const systemInfo = uni.getSystemInfoSync(); + +// #ifdef APP-NVUE +const weexDom = weex.requireModule('dom'); +// #endif + +export default { + name: "z-paging", + components: { + zPagingRefresh, + zPagingLoadMore, + zPagingEmptyView + }, + mixins: [ + dataHandleModule, + i18nModule, + nvueModule, + emptyModule, + refresherModule, + loadMoreModule, + scrollerModule, + backToTopModule, + virtualListModule + ], + data() { + return { + //--------------静态资源--------------- + base64Arrow: zStatic.base64Arrow, + base64Flower: zStatic.base64Flower, + base64BackToTop: zStatic.base64BackToTop, + + //-------------全局数据相关-------------- + //当前加载类型 + loadingType: Enum.LoadingType.Refresher, + requestTimeStamp: 0, + chatRecordLoadingMoreText: '', + wxsPropType: '', + renderPropScrollTop: -1, + renderPropUsePageScroll: -1, + checkScrolledToBottomTimeOut: null, + systemInfo: null, + cssSafeAreaInsetBottom: -1, + cacheTopHeight: 0, + + //--------------状态&判断--------------- + insideOfPaging: -1, + loading: false, + loadingForNow: false, + isLoadFailed: false, + isIos: systemInfo.platform === 'ios', + disabledBounce: false, + fromCompleteEmit: false, + disabledCompleteEmit: false, + + //---------------wxs相关--------------- + wxsIsScrollTopInTopRange: true, + wxsScrollTop: 0, + wxsPageScrollTop: 0, + wxsOnPullingDown: false, + }; + }, + props: { + //调用complete后延迟处理的时间,单位为毫秒,默认0毫秒,优先级高于minDelay + delay: { + type: [Number, String], + default: u.gc('delay', 0), + }, + //触发@query后最小延迟处理的时间,单位为毫秒,默认0毫秒,优先级低于delay(假设设置为300毫秒,若分页请求时间小于300毫秒,则在调用complete后延迟[300毫秒-请求时长];若请求时长大于300毫秒,则不延迟),当show-refresher-when-reload为true或reload(true)时,其最小值为400 + minDelay: { + type: [Number, String], + default: u.gc('minDelay', 0), + }, + //设置z-paging的style,部分平台(如微信小程序)无法直接修改组件的style,可使用此属性代替 + pagingStyle: { + type: Object, + default: function() { + return u.gc('pagingStyle', {}); + }, + }, + //z-paging的高度,优先级低于pagingStyle中设置的height;传字符串,如100px、100rpx、100% + height: { + type: String, + default: u.gc('height', '') + }, + //z-paging的宽度,优先级低于pagingStyle中设置的width;传字符串,如100px、100rpx、100% + width: { + type: String, + default: u.gc('width', '') + }, + //z-paging的背景色,优先级低于pagingStyle中设置的background。传字符串,如"#ffffff" + bgColor: { + type: String, + default: u.gc('bgColor', '') + }, + //设置z-paging的容器(插槽的父view)的style + pagingContentStyle: { + type: Object, + default: function() { + return u.gc('pagingContentStyle', {}); + }, + }, + //z-paging是否自动高度,若自动高度则会自动铺满屏幕 + autoHeight: { + type: Boolean, + default: u.gc('autoHeight', false) + }, + //z-paging是否自动高度时,附加的高度,注意添加单位px或rpx,若需要减少高度,则传负数 + autoHeightAddition: { + type: [Number, String], + default: u.gc('autoHeightAddition', '0px') + }, + //loading(下拉刷新、上拉加载更多)的主题样式,支持black,white,默认black + defaultThemeStyle: { + type: String, + default: function() { + return u.gc('defaultThemeStyle', 'black'); + } + }, + //z-paging是否使用fixed布局,若使用fixed布局,则z-paging的父view无需固定高度,z-paging高度默认为100%,默认为是(当使用内置scroll-view滚动时有效) + fixed: { + type: Boolean, + default: u.gc('fixed', true) + }, + //是否开启底部安全区域适配 + safeAreaInsetBottom: { + type: Boolean, + default: u.gc('safeAreaInsetBottom', false) + }, + //开启底部安全区域适配后,是否使用placeholder形式实现,默认为否。为否时滚动区域会自动避开底部安全区域,也就是所有滚动内容都不会挡住底部安全区域,若设置为是,则滚动时滚动内容会挡住底部安全区域,但是当滚动到底部时才会避开底部安全区域 + useSafeAreaPlaceholder: { + type: Boolean, + default: u.gc('useSafeAreaPlaceholder', false) + }, + //第一次加载后自动隐藏loading slot,默认为是 + autoHideLoadingAfterFirstLoaded: { + type: Boolean, + default: u.gc('autoHideLoadingAfterFirstLoaded', true) + }, + //loading slot是否铺满屏幕并固定,默认为否 + loadingFullFixed: { + type: Boolean, + default: u.gc('loadingFullFixed', false) + }, + //slot="top"的view的z-index,默认为99,仅使用页面滚动时有效 + topZIndex: { + type: Number, + default: u.gc('topZIndex', 99) + }, + //z-paging内容容器父view的z-index,默认为1 + superContentZIndex: { + type: Number, + default: u.gc('superContentZIndex', 1) + }, + //z-paging内容容器部分的z-index,默认为10 + contentZIndex: { + type: Number, + default: u.gc('contentZIndex', 10) + }, + //使用页面滚动时,是否在不满屏时自动填充满屏幕,默认为是 + autoFullHeight: { + type: Boolean, + default: u.gc('autoFullHeight', true) + }, + //是否监听列表触摸方向改变,默认为否 + watchTouchDirectionChange: { + type: Boolean, + default: u.gc('watchTouchDirectionChange', false) + }, + //是否将错误信息打印至控制台,默认为是 + showConsoleError: { + type: Boolean, + default: u.gc('showConsoleError', true) + }, + }, + created(){ + if (this.createdReload && !this.refresherOnly && (this.mountedAutoCallReload && this.auto)) { + this._startLoading(); + this._preReload(); + } + }, + mounted() { + this.wxsPropType = u.getTime().toString(); + this.renderJsIgnore; + if (!this.createdReload && !this.refresherOnly && (this.mountedAutoCallReload && this.auto)) { + this.$nextTick(() => { + this._preReload(); + }) + } + let delay = 0; + // #ifdef H5 || MP + delay = 100; + // #endif + this.$nextTick(() => { + this.systemInfo = uni.getSystemInfoSync(); + if (!this.usePageScroll && this.autoHeight) { + this._setAutoHeight(); + } + this.loaded = true; + }) + this.updatePageScrollTopHeight(); + this.updatePageScrollBottomHeight(); + this._updateLeftAndRightWidth(); + if (this.finalRefresherEnabled && this.useCustomRefresher) { + this.$nextTick(() => { + this.isTouchmoving = true; + }) + } + this._onEmit(); + // #ifdef APP-NVUE + if (!this.isIos && !this.useChatRecordMode) { + this.nLoadingMoreFixedHeight = true; + } + this._nUpdateRefresherWidth(); + // #endif + // #ifndef APP-NVUE + this.finalUseVirtualList && this._virtualListInit(); + // #endif + // #ifndef APP-PLUS + this.$nextTick(() => { + setTimeout(() => { + this._getCssSafeAreaInsetBottom(); + },delay) + }) + // #endif + }, + destroyed() { + this._offEmit(); + }, + // #ifdef VUE3 + unmounted() { + this._offEmit(); + }, + // #endif + watch: { + loadingStatus(newVal, oldVal) { + this.$emit('loadingStatusChange', newVal); + this.$nextTick(()=>{ + this.loadingStatusAfterRender = newVal; + }) + // #ifdef APP-NVUE + if (this.useChatRecordMode) { + if (this.pageNo === this.defaultPageNo && newVal === Enum.More.NoMore) { + this.nIsFirstPageAndNoMore = true; + return; + } + } + this.nIsFirstPageAndNoMore = false; + // #endif + }, + loading(newVal){ + if(newVal){ + this.loadingForNow = newVal; + } + }, + defaultThemeStyle: { + handler(newVal) { + if (newVal.length) { + this.finalRefresherDefaultStyle = newVal; + } + }, + immediate: true + }, + autoHeight(newVal, oldVal) { + if (this.loaded && !this.usePageScroll) { + this._setAutoHeight(newVal); + } + }, + autoHeightAddition(newVal, oldVal) { + if (this.loaded && !this.usePageScroll && this.autoHeight) { + this._setAutoHeight(newVal); + } + }, + }, + computed: { + zScopedSlots() { + return this.$scopedSlots; + }, + finalPagingStyle() { + let pagingStyle = this.pagingStyle; + if (!this.systemInfo) return pagingStyle; + let windowTop = this.systemInfo.windowTop; + //暂时修复vue3中隐藏系统导航栏后windowTop获取不正确的问题,具体bug详见https://ask.dcloud.net.cn/question/141634 + //感谢litangyu!!https://github.com/SmileZXLee/uni-z-paging/issues/25 + // #ifdef VUE3 && H5 + const pageHeadNode = document.getElementsByTagName("uni-page-head"); + if (!pageHeadNode.length) windowTop = 0; + // #endif + const windowBottom = this.systemInfo.windowBottom; + if (!this.usePageScroll && this.fixed) { + if (windowTop && !pagingStyle.top) { + pagingStyle.top = windowTop + 'px'; + } + if (!pagingStyle.bottom) { + let bottom = windowBottom || 0; + if (this.safeAreaInsetBottom && !this.useSafeAreaPlaceholder) { + bottom += this.safeAreaBottom; + } + if(bottom > 0){ + pagingStyle.bottom = bottom + 'px'; + } + } + } + if (this.bgColor.length && !pagingStyle['background']) { + pagingStyle['background'] = this.bgColor; + } + if (this.height.length && !pagingStyle['height']) { + pagingStyle['height'] = this.height; + } + if (this.width.length && !pagingStyle['width']) { + pagingStyle['width'] = this.width; + } + return pagingStyle; + }, + finalLowerThreshold() { + return u.convertTextToPx(this.lowerThreshold); + }, + finalPagingContentStyle() { + if (this.contentZIndex != 1) { + this.pagingContentStyle['z-index'] = this.contentZIndex; + this.pagingContentStyle['position'] = 'relative'; + } + return this.pagingContentStyle; + }, + showLoading() { + if (this.firstPageLoaded || !this.loading || !this.loadingForNow) return false; + if (this.autoHideLoadingAfterFirstLoaded) { + return this.fromEmptyViewReload ? true : !this.pagingLoaded; + } else{ + return this.loadingType === Enum.LoadingType.Refresher; + } + }, + safeAreaBottom() { + if (!this.systemInfo) return 0; + let safeAreaBottom = 0; + // #ifdef APP-PLUS + safeAreaBottom = this.systemInfo.safeAreaInsets.bottom || 0; + // #endif + // #ifndef APP-PLUS + safeAreaBottom = this.cssSafeAreaInsetBottom === -1 ? 0 : this.cssSafeAreaInsetBottom; + // #endif + return safeAreaBottom; + }, + renderJsIgnore() { + if ((this.usePageScroll && this.useChatRecordMode) || !this.refresherEnabled || !this.useCustomRefresher) { + this.$nextTick(() => { + this.renderPropScrollTop = 10; + }) + } + return 0; + }, + windowHeight() { + return !this.systemInfo ? 0 : this.systemInfo.windowHeight || 0; + }, + windowTop() { + return !this.systemInfo ? 0 : this.systemInfo.windowTop || 0; + }, + windowBottom() { + if (!this.systemInfo) return 0; + let windowBottom = this.systemInfo.windowBottom || 0; + if (this.safeAreaInsetBottom && !this.useSafeAreaPlaceholder) { + windowBottom += this.safeAreaBottom; + } + return windowBottom; + }, + isOldWebView() { + // #ifndef APP-NVUE + try { + const systemInfos = systemInfo.system.split(' '); + const deviceType = systemInfos[0]; + const version = parseInt(systemInfos[1].slice(0,1)); + if ((deviceType === 'iOS' && version <= 10) || (deviceType === 'Android' && version <= 6)) { + return true; + } + } catch(e){ + return false; + } + // #endif + return false; + } + }, + methods: { + //当前版本号 + getVersion() { + return `z-paging v${zConstant.version}`; + }, + //设置nvue List的specialEffects + setSpecialEffects(args) { + this.setListSpecialEffects(args); + }, + //与setSpecialEffects等效,兼容旧版本 + setListSpecialEffects(args) { + this.nFixFreezing = args && Object.keys(args).length; + if (this.isIos) { + this.privateRefresherEnabled = 0; + } + if (!this.usePageScroll) { + this.$refs['zp-n-list'].setSpecialEffects(args); + } + }, + //处理开始加载更多状态 + _startLoading(isReload = false) { + if ((this.showLoadingMoreWhenReload && !this.isUserPullDown) || !isReload) { + this.loadingStatus = Enum.More.Loading; + } + this.loading = true; + }, + //检测scrollView是否要铺满屏幕 + _doCheckScrollViewShouldFullHeight(totalData){ + if (this.autoFullHeight && this.usePageScroll && this.isTotalChangeFromAddData) { + // #ifndef APP-NVUE + this.$nextTick(() => { + this._checkScrollViewShouldFullHeight((scrollViewNode, pagingContainerNode) => { + this._preCheckShowLoadingMoreWhenNoMoreAndInsideOfPaging(totalData, scrollViewNode, pagingContainerNode) + }); + }) + // #endif + // #ifdef APP-NVUE + this._preCheckShowLoadingMoreWhenNoMoreAndInsideOfPaging(totalData) + // #endif + } else { + this._preCheckShowLoadingMoreWhenNoMoreAndInsideOfPaging(totalData) + } + }, + //检测z-paging是否要全屏覆盖(当使用页面滚动并且不满全屏时,默认z-paging需要铺满全屏,避免数据过少时内部的empty-view无法正确展示) + async _checkScrollViewShouldFullHeight(callback) { + try { + const scrollViewNode = await this._getNodeClientRect('.zp-scroll-view'); + const pagingContainerNode = await this._getNodeClientRect('.zp-paging-container-content'); + if (!scrollViewNode || !pagingContainerNode) return; + const scrollViewHeight = pagingContainerNode[0].height; + const scrollViewTop = scrollViewNode[0].top; + if (this.isAddedData && scrollViewHeight + scrollViewTop <= this.windowHeight) { + this._setAutoHeight(true, scrollViewNode); + callback(scrollViewNode, pagingContainerNode); + } else { + this._setAutoHeight(false); + callback(null, null); + } + } catch (e) { + callback(null, null); + } + }, + //设置z-paging高度 + async _setAutoHeight(shouldFullHeight = true, scrollViewNode = null) { + let heightKey = 'height'; + // #ifndef APP-NVUE + if (this.usePageScroll) { + heightKey = 'min-height'; + } + // #endif + try { + if (shouldFullHeight) { + let finalScrollViewNode = scrollViewNode ? scrollViewNode : await this._getNodeClientRect('.scroll-view'); + let finalScrollBottomNode = await this._getNodeClientRect('.zp-page-bottom'); + if (finalScrollViewNode) { + const scrollViewTop = finalScrollViewNode[0].top; + let scrollViewHeight = this.windowHeight - scrollViewTop; + if(finalScrollBottomNode){ + scrollViewHeight -= finalScrollBottomNode[0].height; + } + let additionHeight = u.convertTextToPx(this.autoHeightAddition); + this.$set(this.scrollViewStyle, heightKey, scrollViewHeight + additionHeight - (this.insideMore ? 1 : 0) + 'px'); + this.$set(this.scrollViewInStyle, heightKey, scrollViewHeight + additionHeight - (this.insideMore ? 1 : 0) + 'px'); + } + } else { + this.$delete(this.scrollViewStyle, heightKey); + this.$delete(this.scrollViewInStyle, heightKey); + } + } catch (e) {} + }, + //通过获取css设置的底部安全区域占位view高度设置bottom距离 + _getCssSafeAreaInsetBottom(){ + this._getNodeClientRect('.zp-safe-area-inset-bottom').then((res) => { + if (res) { + this.cssSafeAreaInsetBottom = res[0].height; + if (this.safeAreaInsetBottom) { + this.updatePageScrollBottomHeight(); + } + } + }); + }, + //触发更新是否超出页面状态 + _updateInsideOfPaging() { + if (this.insideMore && this.insideOfPaging === true) { + setTimeout(() => { + this.doLoadMore(); + }, 200) + } + }, + //获取节点尺寸 + _getNodeClientRect(select, inThis = true, scrollOffset = false) { + // #ifdef APP-NVUE + select = select.replace('.', '').replace('#', ''); + const ref = this.$refs[select]; + return new Promise((resolve, reject) => { + if (ref) { + weexDom.getComponentRect(ref, option => { + if (option && option.result) { + resolve([option.size]); + } else { + resolve(false); + } + }) + } else { + resolve(false); + } + }); + return; + // #endif + //#ifdef MP-ALIPAY + inThis = false; + //#endif + let res = inThis ? uni.createSelectorQuery().in(this) : uni.createSelectorQuery(); + if (scrollOffset) { + res.select(select).scrollOffset(); + } else { + res.select(select).boundingClientRect(); + } + return new Promise((resolve, reject) => { + res.exec(data => { + resolve((data && data != '' && data != undefined && data.length) ? data : false); + }); + }); + }, + //清除timeout + _cleanTimeout(timeout) { + if (timeout) { + clearTimeout(timeout); + timeout = null; + } + return timeout; + }, + //添加全局emit监听 + _onEmit() { + uni.$on(c.i18nUpdateKey, () => { + this.tempLanguageUpdateKey = u.getTime(); + }) + uni.$on(c.errorUpdateKey, () => { + if (this.loading) { + this.complete(false); + } + }) + uni.$on(c.completeUpdateKey, (data) => { + setTimeout(() => { + if (this.loading) { + if (!this.disabledCompleteEmit) { + const type = data.type || 'normal'; + const list = data.list || data; + const rule = data.rule; + this.fromCompleteEmit = true; + switch (type){ + case 'normal': + this.complete(list); + break; + case 'total': + this.completeByTotal(list, rule); + break; + case 'nomore': + this.completeByNoMore(list, rule); + break; + case 'key': + this.completeByKey(list, rule); + break; + default: + break; + } + } else { + this.disabledCompleteEmit = false; + } + } + }, 1); + }) + }, + //销毁全局emit和listener监听 + _offEmit(){ + uni.$off(c.i18nUpdateKey); + uni.$off(c.errorUpdateKey); + uni.$off(c.completeUpdateKey); + } + }, +}; diff --git a/components/z-paging/js/z-paging-mixin.js b/components/z-paging/js/z-paging-mixin.js new file mode 100644 index 0000000..e5e02cf --- /dev/null +++ b/components/z-paging/js/z-paging-mixin.js @@ -0,0 +1,26 @@ +// [z-paging]使用页面滚动时引入此mixin,用于监听和处理onPullDownRefresh等页面生命周期方法 + +const ZPagingMixin = { + onPullDownRefresh() { + if (this.isPagingRefNotFound()) return; + this.$refs.paging.reload(); + }, + onPageScroll(e) { + if (this.isPagingRefNotFound()) return; + this.$refs.paging.updatePageScrollTop(e.scrollTop); + if (e.scrollTop < 10) { + this.$refs.paging.doChatRecordLoadMore(); + } + }, + onReachBottom() { + if (this.isPagingRefNotFound()) return; + this.$refs.paging.doLoadMore(); + }, + methods: { + isPagingRefNotFound() { + return !this.$refs.paging || this.$refs.paging === undefined; + } + } +} + +export default ZPagingMixin; diff --git a/components/z-paging/js/z-paging-static.js b/components/z-paging/js/z-paging-static.js new file mode 100644 index 0000000..08c4088 --- /dev/null +++ b/components/z-paging/js/z-paging-static.js @@ -0,0 +1,23 @@ +// [z-paging]公用的静态图片资源 + +const base64Arrow = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAD1BMVEVHcExRUVFMTExRUVFRUVE9CdWsAAAABHRSTlMAjjrY9ZnUjwAAAQFJREFUWMPt2MsNgzAMgGEEE1B1gKJmAIRYoCH7z9RCXrabh33iYktcIv35EEg5ZBh07pvxJU6MFSPOSRnjnBUjUsaciRUjMsb4xIoRCWNiYsUInzE5sWKEyxiYWDbyefqHx1zIeiYTk7mQYziTYecxHvEJjwmIT3hMQELCYSISEg4TkZj0mYTEpM8kJCU9JiMp6TEZyUmbAUhO2gxAQNJiIAKSFgMRmNQZhMCkziAEJTUGIyipMRjBSZkhCE7KDEFIUmTeGCHJxWz0zXaE0GTCG8ZFtEaS347r/1fe11YyHYVfubxayfjoHmc0YYwmmmiiiSaaaKLJ7ckyz5ve+dw3Xw2emdwm9xSbAAAAAElFTkSuQmCC'; +const base64ArrowWhite = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAElBMVEVHcEz///////////////////+IGTx/AAAABnRSTlMA/dAkXZOhASU/AAABYElEQVRYw+2YwXLCIBCGsdAHWGbyAKZ4zxi9O017rxLf/1UaWFAgA1m8dcpedNSPf/l/Vh0Ya/Wn6hN0JcGvoCqRM4C8VBFiDwBqqNuJKV0rAnCgy3AUqZE57x0iqTL8Br4U3WBf/YWaIlTKfAcELU/h9w72CSVPa3C3OCDvhpHbRp/s2vq4fHhCeiCl2A3m4Qd71DQR257mFBlMcTlbFnFWzNtHxewYEfSiaLS4el8d8nyhmKJd1CF4eOS0keLMAuSxubLBIeIGQW8YHCFFo7EH9+YDcQt9FMZEswTheaNxTHwHT8SZorJjMrEVwo4Zo0U8HSEyZvJMOg4RjnmmRr8nDYeIz3OMkbfE/QhBo+U9RnZJxjGCRh/WKmHEMWLNkfPKsGh/CWJk1JjG0kcuJggTt34VDP8aWAFhp4nybVb5+9qQhjSkIQ1pSEMa8k+Q5U9rV3dF8MpFBK+/7miVq1/HZ2qmo9D+pAAAAABJRU5ErkJggg=='; +const base64Flower = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAKlBMVEVHcEzDw8Ovr6+pqamUlJTCwsKenp61tbWxsbGysrLNzc2bm5u5ubmjo6MpovhuAAAACnRSTlMA/P79/sHDhiZS0DxZowAABBBJREFUWMPtl89rE0EUx7ctTXatB3MI1SWnDbUKPUgXqh4ED8Uf7KUVSm3ooVSpSii0Fn/gD4j4o+APiEoVmos9FO2celiqZVgwgaKHPQiCCkv+F99kM7Ozm5kxq1dfD91k9pPve9/3ZjbRNHHok/mKli4eIPNgSuRObuN9SqSEzM20iGnm0yIbqCuV7NSSSIV7uyPM6JMBYdeTOanh/QihJYZsUCSby+VkMj2AvOt0rAeQAwqE3lfKMZVlQCZk1QOCKkkVPadITCfIRNKxfoJI5+0OIFtJx14CMSg1mRSDko7VAfksRQzEbGYqxOJcVTWMCH2I1/IACNW0PWU2M8cmAVHtnH5mM1VRWtwKZjOd5JbF6s1IbaYqaotjNlPHgDAnlAizubTR6ovMYn052g/U5qcmOpi0WL8xTS/3IfSet5m8MEr5ajjF5le6dq/OJpobrdY0t3i9QgefWrxW9/1BLhk0E9m8FeUMhhXal499iD0eQRfDF+ts/tttORRerfp+oV7f4xJj82iUYm1Yzod+ZQEAlS/8mMBwKebVmCVp1f0JLS6zKd17+iwRKTARVg2SHtz3iEbBH+Q+U28zW2Jiza8Tjb1YFoYZMsJyjDqp3M9XBQdSdPLFdxEpvOB37JrHcmR/y9+LgoTlCFGZEa2sc6d4PGlweEa2JSVPoVm+IfGG3ZL037iV9oH+P+Jxc4HGVflNq1M0pivao/EopO4b/ojVCP9GjmiXOeS0DOn1o/iiccT4ORnyvBGF3yUywkQajW4Ti0SGuiy/wVSg/L8w+X/8Q+hvUx8Xd90z4oV5a1i88MbFWHz0WZZ1UrTwBGPX3Rat9AFiXRMRjoMdIdJLEOt2h7jrYOzgOamKZSWSNspOS0X8SAqRYmxRL7sg4eLzYmNehcxh3uoyud/BH2Udux4ywxFTc1xC7Mgf4vMhc5S+kSH3Y7yj+qpwIWSoPTVCOOPVthGx9FbGqrwFw6wSFxJr+17zeKcztt3u+2roAEVgUjDd+AHGuxHy2rZHaa8JMkTHEeyi85ANPO9j9BVuBRD2FY5LDMo/Sz/2hReqGIs/KiFin+CsPsYO/yvM3jL2vE8EbX7/Bf8ejtr2GLN65bioAdgLd8Bis/mD5GmP2qeqyo2ZwQEOtAjRIDH7mBKpUcMoApbZJ5UIxkEwxyMZyMxW/uKFvHCFR3SSmerHyDNQ2dF4JG6zIMpBgLfjSF9x1D6smFcYnGApjmSLICO3ecCDWrQ48geba9DI3STy2i7ax6WIB62fSyIZIiO3GFQqSURp8wCo7GhJBGwuSovJBNjb7kT6FPVnIa9qJ2Ko+l9mefGIdinaMp0yC1URYiwsdfNE45EuA5Cx9EhalfvN5s+UyItm81vaB3p4joniN+SCP7Qc1hblAAAAAElFTkSuQmCC'; +const base64FlowerWhite = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAElBMVEX///9HcEz///////////////84chYNAAAABnRSTlP/AGzCOYZj5g1nAAACfklEQVRYw+2YTVPDIBCGtza9Jw25a0bvcax30o73OOr//yvma2F3YWlpPTijXNpAHrK8LLALVPFium2vNIFSbwGKTGQA2GUiHcD29yDNy3sMIdUBQl7r2H8mOEVqAHgPkYZUS6Qc2zYhQqtjyDZEximCZwWZLIBeIgYShs2NzxKpSUehYpMJhURGb+O+w5BpMCAREKPnCDHbIY20SzhM5yxziAXpOiBXydrekT9i5XDEq4NIIHHgyU5mRGqviII4mREJJA4QJzMiILwlRJzpKxJKvCBm8OsBBbLux0tsPl4RKYm5aPu6jw1U4mGxEUR9g8M1PcqBEp/WJliNgYOXueBzS4jZSIcgY5lCtevgDSgyzE+rAfuOTQMq0yzvoGH18qju27Mayzs4fPyMziCx81NJa5RNfW7vPYK9KOfDiVkBxFHG8hAj9txuoBuSWORsFfkpBf7xKFLSeaOefEojh5jz22DJEqMP8fUyaKdQx+RnG+yXMpe8Aars8ueR1pVH/bW3FyyvPRw90upLDHwpgBDtg4aUBNkxRLXMAi03IhcZtr1m+FeI/O/JNyDmmL1djLOauSlNflBpW18RQ2bPqXI22MXXEk75KRHTnkPkYbESbdKP2ZFk0r5sIwffAjy1lx+vx7NLjB6/E7Jfv5ERKhzpN0w8IDE8IGFDv5dhz10s7GFiXRZcUeLCEG5P5nDq9k4PFDcoMpE3GY4OuxuCXhmuyNB6k0RsLIAvqp9NE5r8ZCSS8gxnUp7ODdYhZTqxuiJ9uyJJtPmpqJ7wVj+XVieS903iViHziqAhchLEJAyb7jWU647EpUofQ0ziUuXXXhDddtlllSwjgSQu7r4BRWhQqfDPMVwAAAAASUVORK5CYII=' +const base64Success = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAElBMVEVRUVFHcExTU1NRUVFRUVFRUVFOSlSUAAAABnRSTlP/AI6+VySB3ZENAAACcElEQVRYw+2YyYKCMAyGI8hdpdxdZu7gcpdZ7jL6/s8yYheSNi0aPdqbwOffpGmaFOYPD3gj4bisN7vddv17N/JVgxn5x12IWgIaWTuO/IE3PseQbwjGPo2cgRmHFLJwdm/X643zwiqOKPPJ1nj3sjEP2iiifZWj5bhopSyGaEO2HX5fbQJzwJ+W7x/jw5ZFjsEU0PMph9xE8i5EqprKALW95eJQURkgzw98uJ/JvwGecR7bIjWWsUgVrrIfFZ2HlLy3sKETD1mmRLRMRhGVssRa0xJkdn3SpJBymBkM8+pSSDXMDNyDaToVHd2fgpNt0sjwiUZO19+jGQ+gQEg9Oq+bufmAVGihomNmjQG7UG3020vrlm7lkFnKFGU3kZ0KGAdmKe821pipQ+qEKcrZeTL2g5FsUks4cStjEZWwXg0b0n4GxmEpkWwIs5VBynjgK7xZaz1/0D7OxkVuLpsY5BQNFyLS84VBjjbg0iL2r2EQHBOxBhikuUOkdxODVF1cxHoWtPPsiyXO455Iv34hssCO8EV4ZIYTjS8SR4qYSHRiTiYQ4ZFbHi0iIhhBTi6dTCgSWRcnw4h4yGTuyTAiOGBIWGoZTgSHJQl+LcOJ4OCnW6yX2bMnJ9pidCOXtkTkTrIGpYuOynAiOF14SamMiOCk5Ke+mq8BcOrrvym8d0zKIQnWT+M1WwOQNO4fFiWb18hhERxJPx2fblbPHHyC41VyiAtKBUFBIih7JMWVoIQTFIr3lKPN80WvoLSWFPC653ioTZA0I0FrQ7qU6asaK0H7JmkSJa2ooOGVtNUsc3j9FYHkIkJy3SG6VHnfXKXGP9t4N9Q4Ye98AAAAAElFTkSuQmCC'; +const base64SuccessWhite = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAGFBMVEVHcEz///////////////////////////8dS1W+AAAAB3RSTlMAiVYk6KvDHLfaegAAAo1JREFUWMPtWEtzmzAQNhCTq910ytXpiyvxTNOr60zrayepx9d02gnX4sTm7xcEiJX2gdnkGJ1A4tOnfWqXyeR1vMRYzrcPD9v5h5MBl3/Ldvx4cxIg/FWC8X0xjLjalM54uhhCfCrRuJURX0pi3EmIqZV7O59vrRZmguStHL9b7S7ftfLwOtiZDw7AHMtmquAQ12b5Wwbnordm8g9zLLO49qc/m2n6aKnhwPOGZ08hAiNHhheiHae1lOUPGZpQkPKa3q0mOUjaRzSRaGUjpy/mmWSwySSpllcEteBKAT52KEnSbblA51pJEPxBQoiH1FP4E3s5+FJv07h6/ylD6ui7B+9fq/ehrFB98ghec9EoVtyjK8pqCHLmCBOwMWSCeWFNN4MbPAk55NhsvoFHSSVR0k5TCTTEzlUGcqV/nVp7n9oIVkmtaqbAEqEgfdgHJPwsEAyZ9r4VAZXFjpEwyaw3+H2v42KYxKhs1XvY/gSSGv+IHyUSuHXCeZhLAgVI3EjgSGo1Fb3xO0tGGU9S2/KAIbtjxpJASG73qox6w5LUq0cEOa+iIONIWIilQSQ0pPa2jgaRQAgQP7c0mITRWGxpMAmEQFN2NAQJNCV0mI6GIIEO47hlQ0ORQLd0nL+hoUjg1m6I1TRr8uYEAriBHLcVFQ5UEMiBe3XkTBEG04WXlGKGxPnMS305XQPA1Ocn2JiuAZwE66fxnKwBnDTuXxZTMq85lwW6kt5ndLqZPefiU1yvmktcUSooChJF2aMprhQlnKJQ5FxRKkcVRa+itNYU8Io2oVkY14w0NMWYlqft91Bj9VHq+ca3b43BxjWJmla0sfKohlfTVpPN+93L/yLQ/IjQ/O5Q/VR5HdL4D7mlxmjwVdELAAAAAElFTkSuQmCC'; +const base64Empty = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADIBAMAAABfdrOtAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAbUExURdvc3EdwTMLBwcjIyLSzs/Hx8ff39////19dXXz7IJEAAAAFdFJOU/4A6J9QDyyutAAAB5VJREFUeNrtnM1z4jYYxhUHkR4hdu9eU7Z75Ct7jgPbs9ZZmSuTrUWPmXTA186e+LMrf0uWLMtf2WkHXQgzln88et5XeiVMwPQdGrhCrpAr5Aq5Qv4TkJ07OGQFMLp1B4VYCz+kDblDQhJGeH4eEDLBYdLOHwaDWNBPIeHLYJAJ3meQ83IoCMTHDBKOBoKYGOeM8G0gyD0LObnDQB5ZSCtTNCBfsM9AboaBPLCQcDAIM1zht/dQEkMsd1DjI4hpw2YzMtBJeBbydWpCTJs3YDKGX62YgfGoVwi9KwtZJAzcYHHRm7sYCKD390nQSIoO5JGZIEOYxNoZ4+deISYLyeL5hLHbJ2QK98W0kudMgJe9Qh73odhO+KZHyNYGvgQS9gmJKhUigwSj3iBPUhXxePWmxBqHw0Mej9WQ3qILVjLC177yxNxXQ/7uK+Mn1aNVLsGsBTaWrSAPobYl0aUHt2fIs2Rgz7c9QYL0pSTkSzILLFtAJMH1cidN998T9E0/Sg73/pEEwrgkYRh86wlC949gJsR6EobBcz8hHOVgKYi2m6kZtodIkjEQvF3QjbGpmplB4/lRgJhxgRS2N15iijAvPmByDtCxfQhPJ8J4CR82rgCCBILarScw6X0OcMUyYrFVmbxErl0ZacFIoloOLdJAO42qY+NMDss2kKS8xmiZxcCpFKXWvpRGbQqJp5ixyRfJMmR6x0Fk+z29kmgWDYI5ziFbdug/84HxvduhWhLOJ2StPDQrMJPSjNANklh8QhB7dBO0yTGRwn1fkOk8rbQjiB8Ymww+JuiuN0icmSccK4naLMWYa/euL0+m23GyM8kgAc6sYeL4z04Qa4WjGepcKIliO8EUGSk7d9OGWOsoK31OSdy8TQZ59Y/hWbaV1IVs5/Ed6UzGK4nANAJiyGhRsZPUg2yzLe9hLyiJIyCaDU7udC2uy9pnkKvidlBUEltzFAqxRhBrBZm7HfZnjEQI3boqTsJq15PUDEaKZLgiJYc8OZtCtnM/4G93OFYooXpvdy0guwWWNQkEHl/j7Jw1XRmtlS9HYJkSPjk1IUnyyRqUKQn45NSDlP1mcg9i6En1ZU2IADnEtHF1Q+JwIcS/d5YakPuDUamEShGUHHikAz9oQCaE0CsrpYjDBVkEHQYdyK+EkKPhVErxqh1xbJ/oQf4gEeVsOIEc41WJNAwcd9GBfCZJezXsJhAvH+ImEEIOzlwXgpw5wQ0gH3MIOcsiQAahZuSD69/UQyxcQEggiQARQseVFO/ASAMCgM9gjkHZmhLENzi1AOhA7ullkMWUrfHKfpMiDBHtDIx6yCS6jseEnDUe7zcT6DGCtnrIY3olZw1hrPHkfucIAJa1EDu/lsVEyVmGGA67coKijeogFnMxlEaAV5ghRdDm1kDuuatZTJBGgJdOthIzsvZbDWRRuh6ScgR4EQLgagQvRQIxxQ4sxqcR4GE+c4CkjZQQW9YF89Y4OFAjOCki5KmiDxsBL3PlSJWlAFVogaoIePlYi2ClCJAHRa/cmre5eqTii4uvisqQJxqnip6pNd68DhEvyEs5xIyHBNdh4thCKhU++10kD7Gy1Up1A/o56FKuRJQWSFCuf8dpbisxhqHSKlSSgvG7VTaFKO5TzYD5VMPUxEB2YJNiqq3xYJ0KrroH8mq7xpoXqEZgfgNRUQsDtTVvUOk3sLUKbqrBr7YGvkCkQNC/9SA+vTYtvERrxiKEmcogk4ZqCLUd59MIEiFYHlIoxelCaJWDMmtOPIa80XVLbkb6hzaEwwTcPEmV4AIRlBGNIEmuJBFwLAZoHClJ36J8h+wxihpCqJosAnJrSKwEcQOFAFeWN4RQMYc0Ao4Jhg5gpASzyWcDvjpuDIlTkrGGJEro1rHIjHKR3wJCAj+z5oyi11gJBkXy9QFJIiAu78d+pgSjuWhGN0gUAZAcEncSJf4LRrZ8I94WEmcNCJJqBWYjVbE9bg2JxiyrViBWty6QvO56D8jPVWLA4ZX8dfkxvJJPl8t8aCX+pU/Iz1SCf7lc4OBK0OWfQaKLP0TKjj96VvIp+/BDZjwNKF2ItV2vN7sWStAl87oWkm3dZ+k3lEMoYXe8cT1eq2TOePJDD8KfQdxu6iEPxanUZa4HmZRq3dunGsj3BzFq6yD3wnZNX4n2emI2hXyXQpi6RRZdfSgxHNuxVZBFdyVeBPDmCsiksxKUiDAUEKuzkvRUEs0V08pjVyU2/yqFmF2VZGYop3peitdUiQd1pnrL7qTE01tPzE6eaEKm23dQwh2jNlbiay+/245zl94abw45CzNPyqYQ2++kxHGV1crWzg4A2yvR+BY7wziwnRLN7+O36aA54+ZKGjxZYK3txJpxQyUNn5GwtquII4+ACiWtnvawduu1A3SVtH5uhTvAVSpBG7fDYz6RQ+M6JWjmKm6g+RvTla9UMtspu+s+37VbVCupNqPx43CsNawSb1PbtcmDfQWmUILW7rRXSPHtSq5k5ur0a/hb7DQCUiW3G71ejX/wvV1kSoyNbp8Wvyqn1lCIKvl6gNDkNBYzt0GHdr+Pt9xGl1//ncAVcoVcIVfIFXKFXCFXyP8I8i8SyTW4yTz2lwAAAABJRU5ErkJggg==' +const base64Error = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADIBAMAAABfdrOtAAAAJFBMVEVHcEzo6Oibm5ukpKSbm5uampqbm5ubm5u5ubnn5+fm5ub6+vpGpDPdAAAAC3RSTlMA/v4hb+u20dq8aQhnHL4AAATwSURBVHja7ZvNb+JGGMbdjjdVe3NPodzeMhj1ZMUGujkh28B9wKR7iwwBqafWSbPqsbm0uTWtVlrTS9v0Et9yqLQS/1zHNiTZMMB4bO92d+dRUITt8c/PvPPx2h4URUpKSkpKSkpK6m3K6lFN73Q+S/+es3W3fzabTh2Dl0FAXEM+BgrgeXxRsdILTDU9n7J0vz/+EsCYC9KEiSFc06pf5zouqAkjkGWo0OG5Fq6j2IwZ6I4/4DhyTxc20oUjAj5PRTTrwvGAZ9p+ADzlD4RDctCoLhb7JUP87xeLxS3BZUIQ+YNCFi8wRwc4GIqGRK/GkM+5ILV8kFflOmkkkH/LddJ4c05eSSfSyTvrZPEmnCw+UCeuk84QvTSnUF0uCL68fBle/swF+RL1QZ/EpU6gHtOsAM64pnjPwxgTLsjoBM58ODNaAXYBT5QeGdr0KwcEA8He0TkPBLCjUDNHpG4qlg8eTCzXht1FVd1MxTPHj5LTtUiSrKK+7iDf8wBGxk4If3arLv/HF4Tox0A2nlFIGp+CIA+LzSamgbp4TNvZjECtDAjyMcB5HybLO6NxsRA1vmFCNjguNXDGWygbRPXh/B+zn9zPWK5RCkT18QxA57YgAqE+HGS6/tAoD4JO0ts+M2tbyQJpc95a5oI0xXNhCZGQ/x8E0VSCkUZY6Z6CIE/qdO5eL+yPlW6tMMgefPs3o7Bdt8iguJj4DThlZSY/rJ0yB+RraLDK2jAQCHyr4zIhT9mQ7vowygMZjpgQG+CYUV2E1EWqixyzICr8eFFnBB5ba1Y4IIfeKQvysW7ssZrwQLEFmvCBM2U6oRkdI5Wgm1QnO8RUTDlASoiESIiESMh7BDHKhlhu/LbSNUuEqL3lu1p945vO3BArADiaum7vBGDUKQfSIjBykooyrRPQnTIglHFfSagHeqd4iErwa9duEebpckGQjx/VT4v5fC0XhJHAd1mPRvJAVMZiAeQzTpgHYrPKqkGnUEiX+dCoNS4UgniHMTnUS4iESIiE7IS0x+mnVAidglDwVcmQJpy2WQ8VC4UgogfbA1RE4Nuw3UghEBV2rKl7V5ygAJPSY9KGQbP01mVjA5Fa2f1kQN2U3k+M9POWB8gnJUNMZJioWTMzKwOklyxgDrCXVcMMEF90tXM9C2TiCqmfCdIRi/jeewNpyerKok9WkGuzfCdYC+fXRsmBxxpVGG2zY0ZBbieJKvPrDQce3lxppBhIjGFWGkVoxUEoZt0Mukn2XBQH0bTHZpaMIp2sU/6qasU70W6/eHjM09VmYSc6C6Jpvz+orKvVxot8kL3HkMr9IZ9qeZ2o6RrO9mOI9ufdIR9peZ2gNIW31yC/MpyI9ngUDNIsezPks3vIsWDGdYA7cZa9pbqUVeCr/neiaR3U3R4BfXPg75vwb8I/b7HjxChobDZCO+Ny4wuxxaVxPPowcoNnrzPmzGFlX3RJHz2FafbhJ41n8PLx2DCM7KkwQgpqka1DVzKdJNHfJwBe9l/n0eSZFsIPjVSY8xZKZpSXnogwled98wAx3xRcdBNq1f1fhFVdIcL5tvaDolC7XaqaWStEtLOJHkbhlSauMLrma4yHEa03AVUoIUs/M2NQFkchBZiGUPeKonAnqhLOo4hrKf0WTyZ1FcU0Ki0hVrSr+Mucnvya7jYUKSkpKSkpKSmpD0f/AXq+Umj5XnXDAAAAAElFTkSuQmCC'; +const base64BackToTop = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADIBAMAAABfdrOtAAAAElBMVEVRUVH+/v5HcEyZmZlRUVFRUVGm1ByOAAAABnRSTlPMzADMTZAJBBGsAAAEnElEQVR42t2cS27jMAyGf7/2U+QCQeDsbeQCgZDujaC5/1UmkzaJn+JDFGcw3LdfflKibJkkDnxrL7dbg7sNt6+L4O8OYBM+B0ys+QrGkHZG+OEEQ8g6go8Bx1GIGMdpNOQyIG6XdMgnSPtKhLQDGEZFBgYMkhKFtGBb0EIEjDgFRowoBVaMGAWpMedEfxMiZtwpUsgZCqtlkCNUdpVAWigtCCCDFtLwIWeoreZCWiRYYEKGFEjDg+yRZCUH0iLRAgNyToXUNCRZyMqWhGnUN2IPm3wSlwJ7IUspyCBkIQUZhCykIIeQuRTkEDKXAuM9srrtYbrZN7Y98giZSoFd+t1OxmMITG0dcrSFXFchZ1tIvQZpYWxhBbK3hpQrkMEa0iwh5t4a+QvZvDXyF7J5a+Qv5PPW21/I5623v5DPW29/IaO3Xv5Clrw1y1/Ikrdm+Qs5svw83yNnSJ5BQb4F/F7EIEJSnThGBAXxkFQfLOviQUE8JAUPsosHBfGQfDAtHhREQ1JxIV00KIgmrnRI84S0yAd5BAXxxJUck0f6Qnwr9qmr6xF5xLMjcwn/iudIEAdWnyjkEXlQKZiRVzoqRyLbgeUKKR8Q4alY7cSnoxzSf2ggsqehKr6YVpcXpOd7H93f60cKhOd7Re2LteUF4eLqiVS1mr0ge4io6C2+soaFkJ7MuuuQs1yITEp9hwwKISIpzR2iESKSIoT0rLNwuVHQqoSIpAQJpGce60vIUSdEIuUqgPTsJ5QFZK8UIpBS8iG94GFrDjlrhfCl8CG96Llxmle4kEr6vKWBPIVo9kqDQSRk9/3cWoikcCFPAd33v4dIChPyEvLzBA6RlEYWke4JEUnhKXkLeUEKxRHJFfKCQHGucIW8IdZSRkLeEGMpYyEjiK2UsZARxFTKRMgYYillImQMMZQyFTKB2EmZCplAuFLIHT8TMoWwpQwiIVMIUwqpZP5bp5CCvCTiQKr5f5lCQN+tPCBn2ZvVDFJwIDUP0m1BYAfZYRNSsCB7BqTbhoARePIxtZ9tgwWkoJcwCalmv3MBAemtO4R6dah2HaKQqj8Zvp9sQDjvJ21+SPCBHPJDDk6QITekEV7gqCC19CpKAym9IMfckKv4olMBCeIrWwVEfvkshzQekO9r9P1/ALk+IG1eSPCDiCJfyG+FyU+A6ZCa/piZDinpz7LpkCv5gdkAEshP5emQhv7onw6pGeULyZCSUYiRDAmMkpJkCKs4JhFSq8p8hJBSVbAkhARV6ZUQoisik0FqXTmcDHLVFfbJIEFXoiiCNMpiSxGkVJaNiiBBWQArgTTaUl4JpNQWJUsgQVteXQg+AKkLxQWFGKW+5J2+eVp4S168X3CF1CltCKdTJ8lb84YK2bUBO+wZW0Pqv9nk4tKu49N45NJC5dMM5tLW5tOg59Jq6NM06dL+abFXwr/RkuvTXJwae1abtE/Dt0/ruksTvs84AZ/BCC4jHnyGVfiM3VBQFANEXEah+Ax18RlP4zNox2dkkM/wI58xTn8yDCXGYCDV3W5RGSajtXyGhG1jbpbjzpwGt/0MJft8jqC7iUbQ/QZaxdnKqcIftwAAAABJRU5ErkJggg=='; + +export default { + base64Arrow, + base64ArrowWhite, + base64Flower, + base64FlowerWhite, + base64Success, + base64SuccessWhite, + base64Empty, + base64Error, + base64BackToTop +} diff --git a/components/z-paging/js/z-paging-utils.js b/components/z-paging/js/z-paging-utils.js new file mode 100644 index 0000000..cc5aca7 --- /dev/null +++ b/components/z-paging/js/z-paging-utils.js @@ -0,0 +1,244 @@ +// [z-paging]工具类 + +import zI18n from './z-paging-i18n' +import zConfig from './z-paging-config' +import zLocalConfig from '../config/index' + +const storageKey = 'Z-PAGING-REFRESHER-TIME-STORAGE-KEY' +let config = null; + +/* +当z-paging未使用uni_modules管理时,控制台会有警告:WARNING: Module not found: Error: Can't resolve '@/uni_modules/z-paging'... +此时注释下方try中的代码即可 +*/ +// #ifdef VUE2 +try { + const contextKeys = require.context('@/uni_modules/z-paging', false, /\z-paging-config$/).keys(); + if (contextKeys.length) { + const suffix = '.js'; + config = require('@/uni_modules/z-paging/z-paging-config' + suffix); + } +} catch (e) {} +// #endif + +//获取默认配置信息 +function gc(key, defaultValue) { + if (!config) { + if (zLocalConfig && Object.keys(zLocalConfig).length) { + config = zLocalConfig; + } else { + const temConfig = zConfig.getConfig(); + if (zConfig && temConfig) { + config = temConfig; + } + } + } + if (!config) return defaultValue; + const value = config[_toKebab(key)]; + return value === undefined ? defaultValue : value; +} + +//判断两个数组是否相等 +function arrayIsEqual(arr1, arr2) { + if (arr1 === arr2) return true; + if (arr1.length !== arr2.length) return false; + for (let i = 0; i < arr1.length; i++) { + if (arr1[i] !== arr2[i]) return false; + } + return true; +} + +//获取最终的touch位置 +function getTouch(e) { + let touch = null; + if (e.touches && e.touches.length) { + touch = e.touches[0]; + } else if (e.changedTouches && e.changedTouches.length) { + touch = e.changedTouches[0]; + } else if (e.datail && e.datail != {}) { + touch = e.datail; + } else { + return { + touchX: 0, + touchY: 0 + } + } + return { + touchX: touch.clientX, + touchY: touch.clientY + }; +} + +//判断当前手势是否在z-paging内触发 +function getTouchFromZPaging(target) { + if (target && target.tagName && target.tagName !== 'BODY' && target.tagName !== 'UNI-PAGE-BODY') { + var classList = target.classList; + if (classList && classList.contains('zp-paging-touch-view')) { + return true; + } else { + return getTouchFromZPaging(target.parentNode); + } + } else { + return false; + } +} + +//获取z-paging所在的parent +function getParent(parent) { + if (!parent) return null; + if (parent.$refs.paging) return parent; + return getParent(parent.$parent); +} + +//打印错误信息 +function consoleErr(err) { + console.error(`[z-paging]${err}`); +} + +//打印警告信息 +function consoleWarn(warn) { + console.warn(`[z-paging]${warn}`); +} + +//设置下拉刷新时间 +function setRefesrherTime(time, key) { + try { + let datas = getRefesrherTime(); + if (!datas) { + datas = {}; + } + datas[key] = time; + uni.setStorageSync(storageKey, datas); + } catch (e) {} +} + +//获取下拉刷新时间 +function getRefesrherTime() { + try { + const datas = uni.getStorageSync(storageKey); + return datas; + } catch (e) { + return null; + } +} + +//通过下拉刷新标识key获取下拉刷新时间 +function getRefesrherTimeByKey(key) { + const datas = getRefesrherTime(); + if (datas) { + const data = datas[key]; + if (data) return data; + } + return null; +} + +//通过下拉刷新标识key获取下拉刷新时间(格式化之后) +function getRefesrherFormatTimeByKey(key) { + const time = getRefesrherTimeByKey(key); + let timeText = zI18n.t['refresherUpdateTimeNoneText'][zI18n.getLanguage()]; + if (time) { + timeText = _timeFormat(time); + } + return `${zI18n.t['refresherUpdateTimeText'][zI18n.getLanguage()]}${timeText}`; +} + +//将文本的px或者rpx转为px的值 +function convertTextToPx(text) { + const dataType = Object.prototype.toString.call(text); + if (dataType === '[object Number]') { + return text; + } + let isRpx = false; + if (text.indexOf('rpx') !== -1 || text.indexOf('upx') !== -1) { + text = text.replace('rpx', '').replace('upx', ''); + isRpx = true; + } else if (text.indexOf('px') !== -1) { + text = text.replace('px', ''); + } + if (!isNaN(text)) { + if (isRpx) return Number(uni.upx2px(text)); + return Number(text); + } + return 0; +} + +//获取当前时间 +function getTime() { + return (new Date()).getTime(); +} + +//获取z-paging实例id +function getInstanceId() { + let s = []; + const hexDigits = "0123456789abcdef"; + for (let i = 0; i < 10; i++) { + s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); + } + return s.join('') + getTime(); +} + +//------------------ 私有方法 ------------------------ +//时间格式化 +function _timeFormat(time) { + const date = new Date(time); + const currentDate = new Date(); + const dateDay = new Date(time).setHours(0, 0, 0, 0); + const currentDateDay = new Date().setHours(0, 0, 0, 0); + const disTime = dateDay - currentDateDay; + let dayStr = ''; + const timeStr = _dateTimeFormat(date); + if (disTime === 0) { + dayStr = zI18n.t['refresherUpdateTimeTodayText'][zI18n.getLanguage()]; + } else if (disTime === -86400000) { + dayStr = zI18n.t['refresherUpdateTimeYesterdayText'][zI18n.getLanguage()]; + } else { + dayStr = _dateDayFormat(date, date.getFullYear() !== currentDate.getFullYear()); + } + return `${dayStr} ${timeStr}`; +} + +//date格式化为年月日 +function _dateDayFormat(date, showYear = true) { + const year = date.getFullYear(); + const month = date.getMonth() + 1; + const day = date.getDate(); + if (showYear) { + return `${year}-${_fullZeroToTwo(month)}-${_fullZeroToTwo(day)}`; + } else { + return `${_fullZeroToTwo(month)}-${_fullZeroToTwo(day)}`; + } +} + +//data格式化为时分 +function _dateTimeFormat(date) { + const hour = date.getHours(); + const minute = date.getMinutes(); + return `${_fullZeroToTwo(hour)}:${_fullZeroToTwo(minute)}`; +} + +//不满2位在前面填充0 +function _fullZeroToTwo(str) { + str = str.toString(); + if (str.length === 1) return '0' + str; + return str; +} + +//驼峰转短横线 +function _toKebab(value) { + return value.replace(/([A-Z])/g, "-$1").toLowerCase(); +} + +export default { + gc, + setRefesrherTime, + getRefesrherFormatTimeByKey, + arrayIsEqual, + getTouch, + getTouchFromZPaging, + getParent, + convertTextToPx, + getTime, + getInstanceId, + consoleErr, + consoleWarn +}; diff --git a/components/z-paging/wxs/z-paging-renderjs.js b/components/z-paging/wxs/z-paging-renderjs.js new file mode 100644 index 0000000..705a4a9 --- /dev/null +++ b/components/z-paging/wxs/z-paging-renderjs.js @@ -0,0 +1,63 @@ +// [z-paging]使用renderjs在app-vue和h5中对touchmove事件冒泡进行处理 + +import u from '../js/z-paging-utils' +var data = { + renderScrollTop: 0, + renderUsePageScroll: false, + startY: 0, + isTouchFromZPaging: false +} + +var currentVm = null; + +export default { + mounted() { + this._handleTouch(); + // #ifdef APP-VUE + this.$ownerInstance && this.$ownerInstance.callMethod('_checkVirtualListScroll'); + // #endif + }, + methods: { + //接收逻辑层发送的数据 + renderPropScrollTopChange(newVal, oldVal, ownerVm, vm) { + currentVm = ownerVm; + data.renderScrollTop = newVal; + }, + renderPropUsePageScrollChange(newVal, oldVal, ownerVm, vm) { + if(newVal !== -1){ + data.renderUsePageScroll = newVal; + } + }, + //拦截处理touch事件 + _handleTouch() { + if (window && !window.$zPagingRenderJsInited) { + window.$zPagingRenderJsInited = true; + window.addEventListener('touchstart', this._handleTouchstart, { + passive: true + }) + window.addEventListener('touchmove', this._handleTouchmove, { + passive: false + }) + } + }, + _handleTouchstart(e) { + const touch = u.getTouch(e); + data.startY = touch.touchY; + data.isTouchFromZPaging = u.getTouchFromZPaging(e.target); + }, + _handleTouchmove(e) { + const touch = u.getTouch(e); + var moveY = touch.touchY - data.startY; + //v2.1.4起删除条件:(data.isTouchFromZPaging && data.renderIsIos && !data.renderUsePageScroll && moveY < 0) + if (data.isTouchFromZPaging && data.renderScrollTop < 1 && moveY > 0) { + if (e.cancelable && !e.defaultPrevented) { + e.preventDefault(); + } + } + }, + _removeAllEventListener(){ + window.removeEventListener('touchstart'); + window.removeEventListener('touchmove'); + } + } +}; diff --git a/components/z-paging/wxs/z-paging-wxs.wxs b/components/z-paging/wxs/z-paging-wxs.wxs new file mode 100644 index 0000000..d8867b1 --- /dev/null +++ b/components/z-paging/wxs/z-paging-wxs.wxs @@ -0,0 +1,353 @@ +// [z-paging]微信小程序、QQ小程序、app-vue、h5上使用wxs实现自定义下拉刷新,降低逻辑层与视图层的通信折损,提升性能 + +var currentDis = 0; +var isPCFlag = -1; +var startY = -1; + +function propObserver(newValue, oldValue, ownerIns, ins) { + var state = ownerIns.getState() || {}; + state.currentIns = ins; + var dataset = ins.getDataset(); + var loading = dataset.loading == true; + if (newValue && newValue.indexOf('end') != -1) { + var transition = newValue.split('end')[0]; + _setTransform('translateY(0px)', ins, false, transition); + state.moveDis = 0; + state.oldMoveDis = 0; + currentDis = 0; + } else if (newValue && newValue.indexOf('begin') != -1) { + var refresherThreshold = ins.getDataset().refresherthreshold; + _setTransformValue(refresherThreshold, ins, state, false); + } +} + +function touchstart(e, ownerIns) { + var ins = _getIns(ownerIns); + var state = {}; + var dataset = {}; + if (ins) { + state = ins.getState(); + dataset = ins.getDataset(); + if (_touchDisabled(e, ins, 0)) return; + } + var isTouchEnded = state.isTouchEnded; + state.oldMoveDis = 0; + var touch = _getTouch(e); + var loading = _getIsTrue(dataset.loading); + state.startY = touch.touchY; + startY = state.startY; + state.lastTouch = touch; + if (!loading && isTouchEnded) { + state.isTouchmoving = false; + } + state.isTouchEnded = false; + ownerIns.callMethod('_handleRefresherTouchstart', touch); +} + +function touchmove(e, ownerIns) { + var touch = _getTouch(e); + var ins = _getIns(ownerIns); + var dataset = ins.getDataset(); + var refresherThreshold = dataset.refresherthreshold; + var isIos = _getIsTrue(dataset.isios); + var state = ins.getState(); + var dataset = ins.getDataset(); + var watchTouchDirectionChange = _getIsTrue(dataset.watchtouchdirectionchange); + var moveDisObj = {}; + var moveDis = 0; + var prevent = false; + if (watchTouchDirectionChange) { + moveDisObj = _getMoveDis(e, ins); + moveDis = moveDisObj.currentDis; + prevent = moveDisObj.isDown; + if(state.oldAcceptedIsDown == prevent){ + ownerIns.callMethod('_handleTouchDirectionChange', {direction: prevent ? 'top' : 'bottom'}); + state.oldIsDown = prevent; + } + state.oldAcceptedIsDown = prevent; + } + if (_touchDisabled(e, ins, 1)) { + _handlePullingDown(state, ownerIns, false); + return true; + } + if (!_getAngleIsInRange(e, touch, state, dataset)) { + _handlePullingDown(state, ownerIns, false); + return true; + } + moveDisObj = _getMoveDis(e, ins); + moveDis = moveDisObj.currentDis; + prevent = moveDisObj.isDown; + if (moveDis < 0) { + _setTransformValue(0, ins, state, false); + _handlePullingDown(state, ownerIns, false); + return true; + } + if (prevent && !state.disabledBounce) { + if (isIos) { + ownerIns.callMethod('_handleScrollViewDisableBounce', {bounce: false}); + } + state.disabledBounce = true; + _handlePullingDown(state, ownerIns, prevent); + return !prevent; + } + _setTransformValue(moveDis, ins, state, false); + var oldRefresherStatus = state.refresherStatus; + var oldIsTouchmoving = _getIsTrue(dataset.oldistouchmoving); + var hasTouchmove = _getIsTrue(dataset.hastouchmove); + var isTouchmoving = state.isTouchmoving; + state.refresherStatus = moveDis >= refresherThreshold ? 1 : 0; + if (!isTouchmoving) { + state.isTouchmoving = true; + isTouchmoving = true; + } + if (state.isTouchEnded) { + state.isTouchEnded = false; + } + if (hasTouchmove) { + ownerIns.callMethod('_handleWxsPullingDown', {moveDis:moveDis, diffDis:moveDisObj.diffDis}); + } + if (oldRefresherStatus == undefined || oldRefresherStatus != state.refresherStatus || oldIsTouchmoving != isTouchmoving) { + ownerIns.callMethod('_handleRefresherTouchmove', moveDis, touch); + } + _handlePullingDown(state, ownerIns, prevent); + return !prevent; +} + +function touchend(e, ownerIns) { + var touch = _getTouch(e); + var ins = _getIns(ownerIns); + var dataset = ins.getDataset(); + var state = ins.getState(); + if (_touchDisabled(e, ins, 2)) return; + state.reachMaxAngle = true; + state.hitReachMaxAngleCount = 0; + state.disabledBounce = false; + state.fixedIsTopHitCount = 0; + //ownerIns.callMethod('_handleScrollViewDisableBounce', {bounce:true}); + if (!state.isTouchmoving) return; + var oldRefresherStatus = state.refresherStatus; + var oldMoveDis = state.moveDis; + var refresherThreshold = ins.getDataset().refresherthreshold + var moveDis = _getMoveDis(e, ins).currentDis; + if (!(moveDis >= refresherThreshold && oldRefresherStatus === 1)) { + state.isTouchmoving = false; + } + ownerIns.callMethod('_handleRefresherTouchend', moveDis); + state.isTouchEnded = true; + if (oldMoveDis < refresherThreshold) return; + var animate = false; + if (moveDis >= refresherThreshold) { + moveDis = refresherThreshold; + animate = true; + } + _setTransformValue(moveDis, ins, state, animate); +} + +// #ifdef H5 +function isPC() { + if (isPCFlag != -1) return isPCFlag; + var userAgentInfo = navigator.userAgent; + var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"]; + var flag = true; + for (var i = 0; i < Agents.length; i++) { + if (userAgentInfo.indexOf(Agents[i]) > 0) { + flag = false; + break; + } + } + isPCFlag = flag; + return isPCFlag; +} + +var movable = false; + +function mousedown(e, ins) { + if (!isPC()) return; + touchstart(e, ins); + movable = true; +} + +function mousemove(e, ins) { + if (!isPC()) return; + if (!movable) return; + touchmove(e, ins); +} + +function mouseup(e, ins) { + if (!isPC()) return; + touchend(e, ins); + movable = false; +} + +function mouseleave(e, ins) { + if (!isPC()) return; + movable = false; +} +// #endif + + +function _setTransformValue(value, ins, state, animate) { + value = value || 0; + if (state.moveDis == value) return; + state.moveDis = value; + _setTransform('translateY(' + value + 'px)', ins, animate, ''); +} + +function _setTransform(transform, ins, animate, transition) { + if (transform == 'translateY(0px)') { + transform = 'none'; + } + ins.requestAnimationFrame(function() { + var stl = { 'transform': transform }; + if (animate) { + stl['transition'] = 'transform .1s linear'; + } + if (transition.length) { + stl['transition'] = transition; + } + ins.setStyle(stl); + }) +} + +function _getMoveDis(e, ins) { + var state = ins.getState(); + var refresherThreshold = parseFloat(ins.getDataset().refresherthreshold); + var refresherOutRate = parseFloat(ins.getDataset().refresheroutrate); + var touch = _getTouch(e); + var currentStartY = !state.startY || state.startY == 'NaN' ? startY : state.startY; + var moveDis = touch.touchY - currentStartY; + var oldMoveDis = state.oldMoveDis || 0; + state.oldMoveDis = moveDis; + var diffDis = moveDis - oldMoveDis; + if (diffDis > 0) { + diffDis = diffDis * 0.85; + if (currentDis > refresherThreshold) { + diffDis = diffDis * (1 - refresherOutRate); + } + } + if (diffDis > 200) { + currentDis = 0; + diffDis = 0; + } else { + currentDis += diffDis; + currentDis = Math.max(0, currentDis); + } + return { + currentDis: currentDis, + diffDis: diffDis, + isDown: diffDis > 0 + }; +} + +function _getTouch(e) { + var touch = e; + if (e.touches && e.touches.length) { + touch = e.touches[0]; + } else if (e.changedTouches && e.changedTouches.length) { + touch = e.changedTouches[0]; + } else if (e.datail && e.datail != {}) { + touch = e.datail; + } + return { + touchX: touch.clientX, + touchY: touch.clientY + }; +} + +function _getIns(ownerIns) { + var ins = ownerIns.getState().currentIns; + if (!ins) { + ownerIns.callMethod('_handlePropUpdate'); + } + return ins; +} + +function _touchDisabled(e, ins, processTag) { + var dataset = ins.getDataset(); + var state = ins.getState(); + var loading = _getIsTrue(dataset.loading); + var useChatRecordMode = _getIsTrue(dataset.usechatrecordmode); + var refresherEnabled = _getIsTrue(dataset.refresherenabled); + var useCustomRefresher = _getIsTrue(dataset.usecustomrefresher); + var usePageScroll = _getIsTrue(dataset.usepagescroll); + var pageScrollTop = parseFloat(dataset.pagescrolltop); + var scrollTop = parseFloat(dataset.scrolltop); + var finalScrollTop = usePageScroll ? pageScrollTop : scrollTop; + var fixedIsTop = false; + var isIos = _getIsTrue(dataset.isios); + if (!isIos && finalScrollTop == (state.startScrollTop || 0) && finalScrollTop <= 105) { + fixedIsTop = true; + } + var fixedIsTopHitCount = state.fixedIsTopHitCount || 0; + if (fixedIsTop) { + fixedIsTopHitCount++; + if (fixedIsTopHitCount <= 3) { + fixedIsTop = false; + } + state.fixedIsTopHitCount = fixedIsTopHitCount; + } else { + state.fixedIsTopHitCount = 0; + } + if (!isIos && processTag === 0) { + state.startScrollTop = finalScrollTop || 0; + } + if (!isIos && processTag === 2) { + fixedIsTop = true; + } + var res = loading || useChatRecordMode || !refresherEnabled || !useCustomRefresher || ((usePageScroll && useCustomRefresher && pageScrollTop > 5) && !fixedIsTop) || + ((!usePageScroll && useCustomRefresher && scrollTop > 5) && !fixedIsTop); + return res; +} + +function _getAngleIsInRange(e, touch, state, dataset) { + var maxAngle = dataset.refreshermaxangle; + var refresherAecc = _getIsTrue(dataset.refresheraecc); + var lastTouch = state.lastTouch; + var reachMaxAngle = state.reachMaxAngle; + var moveDis = state.oldMoveDis; + if (!lastTouch) return true; + if (maxAngle >= 0 && maxAngle <= 90 && lastTouch) { + if ((!moveDis || moveDis < 1) && !refresherAecc && reachMaxAngle != null && !reachMaxAngle) return false; + var x = Math.abs(touch.touchX - lastTouch.touchX); + var y = Math.abs(touch.touchY - lastTouch.touchY); + var z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); + if ((x || y) && x > 1) { + var angle = Math.asin(y / z) / Math.PI * 180; + if (angle < maxAngle) { + var hitReachMaxAngleCount = state.hitReachMaxAngleCount || 0; + state.hitReachMaxAngleCount = ++hitReachMaxAngleCount; + if (state.hitReachMaxAngleCount > 2) { + state.lastTouch = touch; + state.reachMaxAngle = false; + } + return false; + } + } + } + state.lastTouch = touch; + return true; +} + +function _handlePullingDown(state, ins, onPullingDown) { + var oldOnPullingDown = state.onPullingDown || false; + if (oldOnPullingDown != onPullingDown) { + ins.callMethod('_handleWxsPullingDownStatusChange', onPullingDown); + } + state.onPullingDown = onPullingDown; +} + +function _getIsTrue(value) { + value = (typeof(value) === 'string' ? JSON.parse(value) : value) || false; + return value == true || value == 'true'; +} + +module.exports = { + touchstart: touchstart, + touchmove: touchmove, + touchend: touchend, + mousedown: mousedown, + mousemove: mousemove, + mouseup: mouseup, + mouseleave: mouseleave, + propObserver: propObserver +} diff --git a/components/z-paging/z-paging.vue b/components/z-paging/z-paging.vue new file mode 100644 index 0000000..741ab5d --- /dev/null +++ b/components/z-paging/z-paging.vue @@ -0,0 +1,359 @@ + + + + + + + + + + + + + + + + + +
+ + + diff --git a/index.js b/index.js new file mode 100644 index 0000000..d38a3bf --- /dev/null +++ b/index.js @@ -0,0 +1,141 @@ +// 引入全局mixin +import mixin from './libs/mixin/mixin.js' +// 引入关于是否mixin集成小程序分享的配置 +// import wxshare from './libs/mixin/mpShare.js' +// 全局挂载引入http相关请求拦截插件 +import http from './libs/request' + +function wranning(str) { + // 开发环境进行信息输出,主要是一些报错信息 + // 这个环境的来由是在程序编写时候,点击hx编辑器运行调试代码的时候,详见: + // https://uniapp.dcloud.io/frame?id=%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e5%92%8c%e7%94%9f%e4%ba%a7%e7%8e%af%e5%a2%83 + if (process.env.NODE_ENV === 'development') { + console.warn(str) + } +} + +// 尝试判断在根目录的/store中是否有$u.mixin.js,此文件uView默认为需要挂在到全局的vuex的state变量 +// HX2.6.11版本,放到try中,控制台依然会警告,暂时不用此方式, +// let vuexStore = {}; +// try { +// vuexStore = require("@/store/$u.mixin.js"); +// } catch (e) { +// //TODO handle the exception +// } + +// post类型对象参数转为get类型url参数 +import queryParams from './libs/function/queryParams.js' +// 路由封装 +import route from './libs/function/route.js' +// 时间格式化 +import timeFormat from './libs/function/timeFormat.js' +// 时间戳格式化,返回多久之前 +import timeFrom from './libs/function/timeFrom.js' +// 颜色渐变相关,colorGradient-颜色渐变,hexToRgb-十六进制颜色转rgb颜色,rgbToHex-rgb转十六进制 +import colorGradient from './libs/function/colorGradient.js' +// 生成全局唯一guid字符串 +import guid from './libs/function/guid.js' +// 主题相关颜色,info|success|warning|primary|default|error,此颜色已在uview.scss中定义,但是为js中也能使用,故也定义一份 +import color from './libs/function/color.js' +// 根据type获取图标名称 +import type2icon from './libs/function/type2icon.js' +// 打乱数组的顺序 +import randomArray from './libs/function/randomArray.js' +// 对象和数组的深度克隆 +import deepClone from './libs/function/deepClone.js' +// 对象深度拷贝 +import deepMerge from './libs/function/deepMerge.js' +// 添加单位 +import addUnit from './libs/function/addUnit.js' + +// 规则检验 +import test from './libs/function/test.js' +// 随机数 +import random from './libs/function/random.js' +// 去除空格 +import trim from './libs/function/trim.js' +// toast提示,对uni.showToast的封装 +import toast from './libs/function/toast.js' +// 获取父组件参数 +import getParent from './libs/function/getParent.js' +// 获取整个父组件 +import $parent from './libs/function/$parent.js' +// 获取sys()和os()工具方法 +// 获取设备信息,挂载到$u的sys()(system的缩写)属性中, +// 同时把安卓和ios平台的名称"ios"和"android"挂到$u.os()中,方便取用 +import {sys, os} from './libs/function/sys.js' +// 防抖方法 +import debounce from './libs/function/debounce.js' +// 节流方法 +import throttle from './libs/function/throttle.js' + + +// 配置信息 +import config from './libs/config/config.js' +// 各个需要fixed的地方的z-index配置文件 +import zIndex from './libs/config/zIndex.js' + +const $u = { + queryParams: queryParams, + route: route, + timeFormat: timeFormat, + date: timeFormat, // 另名date + timeFrom, + colorGradient: colorGradient.colorGradient, + colorToRgba: colorGradient.colorToRgba, + guid, + color, + sys, + os, + type2icon, + randomArray, + wranning, + get: http.get, + post: http.post, + put: http.put, + 'delete': http.delete, + hexToRgb: colorGradient.hexToRgb, + rgbToHex: colorGradient.rgbToHex, + test, + random, + deepClone, + deepMerge, + getParent, + $parent, + addUnit, + trim, + type: ['primary', 'success', 'error', 'warning', 'info'], + http, + toast, + config, // uView配置信息相关,比如版本号 + zIndex, + debounce, + throttle, +} + +// $u挂载到uni对象上 +uni.$u = $u + +const install = Vue => { + Vue.mixin(mixin) + if (Vue.prototype.openShare) { + Vue.mixin(mpShare); + } + // Vue.mixin(vuexStore); + // 时间格式化,同时两个名称,date和timeFormat + Vue.filter('timeFormat', (timestamp, format) => { + return timeFormat(timestamp, format) + }) + Vue.filter('date', (timestamp, format) => { + return timeFormat(timestamp, format) + }) + // 将多久以前的方法,注入到全局过滤器 + Vue.filter('timeFrom', (timestamp, format) => { + return timeFrom(timestamp, format) + }) + Vue.prototype.$u = $u +} + +export default { + install +} \ No newline at end of file diff --git a/index.scss b/index.scss new file mode 100644 index 0000000..84daa72 --- /dev/null +++ b/index.scss @@ -0,0 +1,23 @@ +// 引入公共基础类 +@import "./libs/css/common.scss"; +@import "./libs/css/color.scss"; + +// 非nvue的样式 +/* #ifndef APP-NVUE */ +@import "./libs/css/style.vue.scss"; +/* #endif */ + +// nvue的特有样式 +/* #ifdef APP-NVUE */ +@import "./libs/css/style.nvue.scss"; +/* #endif */ + +// 小程序特有的样式 +/* #ifdef MP */ +@import "./libs/css/style.mp.scss"; +/* #endif */ + +// H5特有的样式 +/* #ifdef H5 */ +@import "./libs/css/style.h5.scss"; +/* #endif */ \ No newline at end of file diff --git a/libs/config/config.js b/libs/config/config.js new file mode 100644 index 0000000..34dab30 --- /dev/null +++ b/libs/config/config.js @@ -0,0 +1,17 @@ +// 此版本发布于2022-04-19 +let version = '1.8.6'; + +export default { + //api:'http://work.ii999.live:19011', + api:'http://222.132.51.82:18088', + v: version, + version: version, + // 主题名称 + type: [ + 'primary', + 'success', + 'info', + 'error', + 'warning' + ] +} diff --git a/libs/config/zIndex.js b/libs/config/zIndex.js new file mode 100644 index 0000000..d60e5bd --- /dev/null +++ b/libs/config/zIndex.js @@ -0,0 +1,20 @@ +// uniapp在H5中各API的z-index值如下: +/** + * actionsheet: 999 + * modal: 999 + * navigate: 998 + * tabbar: 998 + * toast: 999 + */ + +export default { + toast: 10090, + noNetwork: 10080, + // popup包含popup,actionsheet,keyboard,picker的值 + popup: 10075, + mask: 10070, + navbar: 980, + topTips: 975, + sticky: 970, + indexListSticky: 965, +} \ No newline at end of file diff --git a/libs/css/color.scss b/libs/css/color.scss new file mode 100644 index 0000000..279bc40 --- /dev/null +++ b/libs/css/color.scss @@ -0,0 +1,155 @@ +.u-type-primary-light { + color: $u-type-primary-light; +} + +.u-type-warning-light { + color: $u-type-warning-light; +} + +.u-type-success-light { + color: $u-type-success-light; +} + +.u-type-error-light { + color: $u-type-error-light; +} + +.u-type-info-light { + color: $u-type-info-light; +} + +.u-type-primary-light-bg { + background-color: $u-type-primary-light; +} + +.u-type-warning-light-bg { + background-color: $u-type-warning-light; +} + +.u-type-success-light-bg { + background-color: $u-type-success-light; +} + +.u-type-error-light-bg { + background-color: $u-type-error-light; +} + +.u-type-info-light-bg { + background-color: $u-type-info-light; +} + +.u-type-primary-dark { + color: $u-type-primary-dark; +} + +.u-type-warning-dark { + color: $u-type-warning-dark; +} + +.u-type-success-dark { + color: $u-type-success-dark; +} + +.u-type-error-dark { + color: $u-type-error-dark; +} + +.u-type-info-dark { + color: $u-type-info-dark; +} + +.u-type-primary-dark-bg { + background-color: $u-type-primary-dark; +} + +.u-type-warning-dark-bg { + background-color: $u-type-warning-dark; +} + +.u-type-success-dark-bg { + background-color: $u-type-success-dark; +} + +.u-type-error-dark-bg { + background-color: $u-type-error-dark; +} + +.u-type-info-dark-bg { + background-color: $u-type-info-dark; +} + +.u-type-primary-disabled { + color: $u-type-primary-disabled; +} + +.u-type-warning-disabled { + color: $u-type-warning-disabled; +} + +.u-type-success-disabled { + color: $u-type-success-disabled; +} + +.u-type-error-disabled { + color: $u-type-error-disabled; +} + +.u-type-info-disabled { + color: $u-type-info-disabled; +} + +.u-type-primary { + color: $u-type-primary; +} + +.u-type-warning { + color: $u-type-warning; +} + +.u-type-success { + color: $u-type-success; +} + +.u-type-error { + color: $u-type-error; +} + +.u-type-info { + color: $u-type-info; +} + +.u-type-primary-bg { + background-color: $u-type-primary; +} + +.u-type-warning-bg { + background-color: $u-type-warning; +} + +.u-type-success-bg { + background-color: $u-type-success; +} + +.u-type-error-bg { + background-color: $u-type-error; +} + +.u-type-info-bg { + background-color: $u-type-info; +} + +.u-main-color { + color: $u-main-color; +} + +.u-content-color { + color: $u-content-color; +} + +.u-tips-color { + color: $u-tips-color; +} + +.u-light-color { + color: $u-light-color; +} diff --git a/libs/css/common.scss b/libs/css/common.scss new file mode 100644 index 0000000..29eb7f4 --- /dev/null +++ b/libs/css/common.scss @@ -0,0 +1,176 @@ +.u-relative, +.u-rela { + position: relative; +} + +.u-absolute, +.u-abso { + position: absolute; +} + +// nvue不能用标签命名样式,不能放在微信组件中,否则微信开发工具会报警告,无法使用标签名当做选择器 +/* #ifndef APP-NVUE */ +image { + display: inline-block; +} + +// 在weex,也即nvue中,所有元素默认为border-box +view, +text { + box-sizing: border-box; +} +/* #endif */ + +.u-font-xs { + font-size: 22rpx; +} + +.u-font-sm { + font-size: 26rpx; +} + +.u-font-md { + font-size: 28rpx; +} + +.u-font-lg { + font-size: 30rpx; +} + +.u-font-xl { + font-size: 34rpx; +} + +.u-flex { + /* #ifndef APP-NVUE */ + display: flex; + /* #endif */ + flex-direction: row; + align-items: center; +} + +.u-flex-wrap { + flex-wrap: wrap; +} + +.u-flex-nowrap { + flex-wrap: nowrap; +} + +.u-col-center { + align-items: center; +} + +.u-col-top { + align-items: flex-start; +} + +.u-col-bottom { + align-items: flex-end; +} + +.u-row-center { + justify-content: center; +} + +.u-row-left { + justify-content: flex-start; +} + +.u-row-right { + justify-content: flex-end; +} + +.u-row-between { + justify-content: space-between; +} + +.u-row-around { + justify-content: space-around; +} + +.u-text-left { + text-align: left; +} + +.u-text-center { + text-align: center; +} + +.u-text-right { + text-align: right; +} + +.u-flex-col { + /* #ifndef APP-NVUE */ + display: flex; + /* #endif */ + flex-direction: column; +} + +// 定义flex等分 +@for $i from 0 through 12 { + .u-flex-#{$i} { + flex: $i; + } +} + +// 定义字体(px)单位,小于20都为px单位字体 +@for $i from 9 to 20 { + .u-font-#{$i} { + font-size: $i + px; + } +} + +// 定义字体(rpx)单位,大于或等于20的都为rpx单位字体 +@for $i from 20 through 40 { + .u-font-#{$i} { + font-size: $i + rpx; + } +} + +// 定义内外边距,历遍1-80 +@for $i from 0 through 80 { + // 只要双数和能被5除尽的数 + @if $i % 2 == 0 or $i % 5 == 0 { + // 得出:u-margin-30或者u-m-30 + .u-margin-#{$i}, .u-m-#{$i} { + margin: $i + rpx!important; + } + + // 得出:u-padding-30或者u-p-30 + .u-padding-#{$i}, .u-p-#{$i} { + padding: $i + rpx!important; + } + + @each $short, $long in l left, t top, r right, b bottom { + // 缩写版,结果如: u-m-l-30 + // 定义外边距 + .u-m-#{$short}-#{$i} { + margin-#{$long}: $i + rpx!important; + } + + // 定义内边距 + .u-p-#{$short}-#{$i} { + padding-#{$long}: $i + rpx!important; + } + + // 完整版,结果如:u-margin-left-30 + // 定义外边距 + .u-margin-#{$long}-#{$i} { + margin-#{$long}: $i + rpx!important; + } + + // 定义内边距 + .u-padding-#{$long}-#{$i} { + padding-#{$long}: $i + rpx!important; + } + } + } +} + +// 重置nvue的默认关于flex的样式 +.u-reset-nvue { + flex-direction: row; + align-items: center; +} \ No newline at end of file diff --git a/libs/css/style.components.scss b/libs/css/style.components.scss new file mode 100644 index 0000000..6835876 --- /dev/null +++ b/libs/css/style.components.scss @@ -0,0 +1,7 @@ +// 定义混入指令,用于在非nvue环境下的flex定义,因为nvue没有display属性,会报错 +@mixin vue-flex($direction: row) { + /* #ifndef APP-NVUE */ + display: flex; + flex-direction: $direction; + /* #endif */ +} \ No newline at end of file diff --git a/libs/css/style.h5.scss b/libs/css/style.h5.scss new file mode 100644 index 0000000..62839eb --- /dev/null +++ b/libs/css/style.h5.scss @@ -0,0 +1,8 @@ +/* H5的时候,隐藏滚动条 */ +::-webkit-scrollbar { + display: none; + width: 0 !important; + height: 0 !important; + -webkit-appearance: none; + background: transparent; +} diff --git a/libs/css/style.mp.scss b/libs/css/style.mp.scss new file mode 100644 index 0000000..ca1d3e0 --- /dev/null +++ b/libs/css/style.mp.scss @@ -0,0 +1,72 @@ +/* start--微信小程序编译后页面有组件名的元素,特别处理--start */ +/* #ifdef MP-WEIXIN || MP-QQ */ +u-td, u-th { + flex: 1; + align-self: stretch; +} + +.u-td { + height: 100%; +} + +u-icon { + display: inline-flex; + align-items: center; +} + +// 各家小程序宫格组件外层设置为100%,避免受到父元素display: flex;的影响 +u-grid { + width: 100%; + flex: 0 0 100%; +} + +// 避免小程序线条组件因为父组件display: flex;而失效 +u-line { + flex: 1; +} + +u-switch { + display: inline-flex; + align-items: center; +} + +u-dropdown { + flex: 1; +} +/* #endif */ +/* end-微信小程序编译后页面有组件名的元素,特别处理--end */ + + +/* #ifdef MP-QQ || MP-TOUTIAO */ +// 需要做这一切额外的兼容,都是因为TX的无能 +u-icon { + line-height: 0; +} +/* #endif */ + +/* start--头条小程序编译后页面有组件名的元素,特别处理--start */ +// 由于头条小程序不支持直接组件名形式写样式,目前只能在写组件的时候给组件加上对应的类名 +/* #ifdef MP-TOUTIAO */ +.u-td, .u-th, .u-tr { + flex: 1; + align-self: stretch; +} + +.u-row, .u-col { + flex: 1; + align-self: stretch; +} + +// 避免小程序线条组件因为父组件display: flex;而失效 +.u-line { + flex: 1; +} + +.u-dropdown { + flex: 1; +} +/* #endif */ +/* end-头条小程序编译后页面有组件名的元素,特别处理--end */ + + + diff --git a/libs/css/style.nvue.scss b/libs/css/style.nvue.scss new file mode 100644 index 0000000..4a6192a --- /dev/null +++ b/libs/css/style.nvue.scss @@ -0,0 +1,3 @@ +.nvue { + font-size: 24rpx; +} \ No newline at end of file diff --git a/libs/css/style.vue.scss b/libs/css/style.vue.scss new file mode 100644 index 0000000..1ab3707 --- /dev/null +++ b/libs/css/style.vue.scss @@ -0,0 +1,175 @@ +page { + color: $u-main-color; + font-size: 28rpx; +} + +/* start--去除webkit的默认样式--start */ +.u-fix-ios-appearance { + -webkit-appearance:none; +} +/* end--去除webkit的默认样式--end */ + +/* start--icon图标外层套一个view,让其达到更好的垂直居中的效果--start */ +.u-icon-wrap { + display: flex; + align-items: center; +} +/* end-icon图标外层套一个view,让其达到更好的垂直居中的效果--end */ + +/* start--iPhoneX底部安全区定义--start */ +.safe-area-inset-bottom { + padding-bottom: 0; + padding-bottom: constant(safe-area-inset-bottom); + padding-bottom: env(safe-area-inset-bottom); +} +/* end-iPhoneX底部安全区定义--end */ + +/* start--各种hover点击反馈相关的类名-start */ +.u-hover-class { + // background-color: #f7f8f9!important; + opacity: 0.6; +} + +.u-cell-hover { + background-color: #f7f8f9!important; +} +/* end--各种hover点击反馈相关的类名--end */ + +/* start--文本行数限制--start */ +.u-line-1 { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.u-line-2 { + -webkit-line-clamp: 2; +} + +.u-line-3 { + -webkit-line-clamp: 3; +} + +.u-line-4 { + -webkit-line-clamp: 4; +} + +.u-line-5 { + -webkit-line-clamp: 5; +} + +.u-line-2, .u-line-3, .u-line-4, .u-line-5 { + overflow: hidden; + word-break: break-all; + text-overflow: ellipsis; + display: -webkit-box; // 弹性伸缩盒 + -webkit-box-orient: vertical; // 设置伸缩盒子元素排列方式 +} + +/* end--文本行数限制--end */ + + +/* start--Retina 屏幕下的 1px 边框--start */ +.u-border, +.u-border-bottom, +.u-border-left, +.u-border-right, +.u-border-top, +.u-border-top-bottom { + position: relative +} + +.u-border-bottom:after, +.u-border-left:after, +.u-border-right:after, +.u-border-top-bottom:after, +.u-border-top:after, +.u-border:after { + /* #ifndef APP-NVUE */ + content: ' '; + /* #endif */ + position: absolute; + left: 0; + top: 0; + pointer-events: none; + box-sizing: border-box; + -webkit-transform-origin: 0 0; + transform-origin: 0 0; + // 多加0.1%,能解决有时候边框缺失的问题 + width: 199.8%; + height: 199.7%; + transform: scale(0.5, 0.5); + border: 0 solid $u-border-color; + z-index: 2; +} + +.u-border-top:after { + border-top-width: 1px +} + +.u-border-left:after { + border-left-width: 1px +} + +.u-border-right:after { + border-right-width: 1px +} + +.u-border-bottom:after { + border-bottom-width: 1px +} + +.u-border-top-bottom:after { + border-width: 1px 0 +} + +.u-border:after { + border-width: 1px +} +/* end--Retina 屏幕下的 1px 边框--end */ + + +/* start--clearfix--start */ +.u-clearfix:after, +.clearfix:after { + /* #ifndef APP-NVUE */ + content: ''; + /* #endif */ + display: table; + clear: both +} +/* end--clearfix--end */ + +/* start--高斯模糊tabbar底部处理--start */ +.u-blur-effect-inset { + width: 750rpx; + height: var(--window-bottom); + background-color: #FFFFFF; +} +/* end--高斯模糊tabbar底部处理--end */ + +/* start--提升H5端uni.toast()的层级,避免被uView的modal等遮盖--start */ +/* #ifdef H5 */ +uni-toast { + z-index: 10090; +} +uni-toast .uni-toast { + z-index: 10090; +} +/* #endif */ +/* end--提升H5端uni.toast()的层级,避免被uView的modal等遮盖--end */ + +/* start--去除button的所有默认样式--start */ +.u-reset-button { + padding: 0; + font-size: inherit; + line-height: inherit; + background-color: transparent; + color: inherit; +} + +.u-reset-button::after { + border: none; +} +/* end--去除button的所有默认样式--end */ + diff --git a/libs/function/$parent.js b/libs/function/$parent.js new file mode 100644 index 0000000..80515c4 --- /dev/null +++ b/libs/function/$parent.js @@ -0,0 +1,18 @@ +// 获取父组件的参数,因为支付宝小程序不支持provide/inject的写法 +// this.$parent在非H5中,可以准确获取到父组件,但是在H5中,需要多次this.$parent.$parent.xxx +// 这里默认值等于undefined有它的含义,因为最顶层元素(组件)的$parent就是undefined,意味着不传name +// 值(默认为undefined),就是查找最顶层的$parent +export default function $parent(name = undefined) { + let parent = this.$parent; + // 通过while历遍,这里主要是为了H5需要多层解析的问题 + while (parent) { + // 父组件 + if (parent.$options && parent.$options.name !== name) { + // 如果组件的name不相等,继续上一级寻找 + parent = parent.$parent; + } else { + return parent; + } + } + return false; +} \ No newline at end of file diff --git a/libs/function/addUnit.js b/libs/function/addUnit.js new file mode 100644 index 0000000..247fae2 --- /dev/null +++ b/libs/function/addUnit.js @@ -0,0 +1,8 @@ +import validation from './test.js'; + +// 添加单位,如果有rpx,%,px等单位结尾或者值为auto,直接返回,否则加上rpx单位结尾 +export default function addUnit(value = 'auto', unit = 'rpx') { + value = String(value); + // 用uView内置验证规则中的number判断是否为数值 + return validation.number(value) ? `${value}${unit}` : value; +} \ No newline at end of file diff --git a/libs/function/bem.js b/libs/function/bem.js new file mode 100644 index 0000000..05d1a36 --- /dev/null +++ b/libs/function/bem.js @@ -0,0 +1,5 @@ +function bem(name, conf) { + +} + +module.exports.bem = bem; diff --git a/libs/function/color.js b/libs/function/color.js new file mode 100644 index 0000000..dafb8c1 --- /dev/null +++ b/libs/function/color.js @@ -0,0 +1,37 @@ +// 为了让用户能够自定义主题,会逐步弃用此文件,各颜色通过css提供 +// 为了给某些特殊场景使用和向后兼容,无需删除此文件(2020-06-20) +let color = { + primary: "#2979ff", + primaryDark: "#2b85e4", + primaryDisabled: "#a0cfff", + primaryLight: "#ecf5ff", + bgColor: "#f3f4f6", + + info: "#909399", + infoDark: "#82848a", + infoDisabled: "#c8c9cc", + infoLight: "#f4f4f5", + + warning: "#ff9900", + warningDark: "#f29100", + warningDisabled: "#fcbd71", + warningLight: "#fdf6ec", + + error: "#fa3534", + errorDark: "#dd6161", + errorDisabled: "#fab6b6", + errorLight: "#fef0f0", + + success: "#19be6b", + successDark: "#18b566", + successDisabled: "#71d5a1", + successLight: "#dbf1e1", + + mainColor: "#303133", + contentColor: "#606266", + tipsColor: "#909399", + lightColor: "#c0c4cc", + borderColor: "#e4e7ed" +} + +export default color; \ No newline at end of file diff --git a/libs/function/colorGradient.js b/libs/function/colorGradient.js new file mode 100644 index 0000000..eca30a2 --- /dev/null +++ b/libs/function/colorGradient.js @@ -0,0 +1,134 @@ +/** + * 求两个颜色之间的渐变值 + * @param {string} startColor 开始的颜色 + * @param {string} endColor 结束的颜色 + * @param {number} step 颜色等分的份额 + * */ +function colorGradient(startColor = 'rgb(0, 0, 0)', endColor = 'rgb(255, 255, 255)', step = 10) { + let startRGB = hexToRgb(startColor, false); //转换为rgb数组模式 + let startR = startRGB[0]; + let startG = startRGB[1]; + let startB = startRGB[2]; + + let endRGB = hexToRgb(endColor, false); + let endR = endRGB[0]; + let endG = endRGB[1]; + let endB = endRGB[2]; + + let sR = (endR - startR) / step; //总差值 + let sG = (endG - startG) / step; + let sB = (endB - startB) / step; + let colorArr = []; + for (let i = 0; i < step; i++) { + //计算每一步的hex值 + let hex = rgbToHex('rgb(' + Math.round((sR * i + startR)) + ',' + Math.round((sG * i + startG)) + ',' + Math.round((sB * + i + startB)) + ')'); + colorArr.push(hex); + } + return colorArr; +} + +// 将hex表示方式转换为rgb表示方式(这里返回rgb数组模式) +function hexToRgb(sColor, str = true) { + let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/; + sColor = sColor.toLowerCase(); + if (sColor && reg.test(sColor)) { + if (sColor.length === 4) { + let sColorNew = "#"; + for (let i = 1; i < 4; i += 1) { + sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1)); + } + sColor = sColorNew; + } + //处理六位的颜色值 + let sColorChange = []; + for (let i = 1; i < 7; i += 2) { + sColorChange.push(parseInt("0x" + sColor.slice(i, i + 2))); + } + if(!str) { + return sColorChange; + } else { + return `rgb(${sColorChange[0]},${sColorChange[1]},${sColorChange[2]})`; + } + } else if (/^(rgb|RGB)/.test(sColor)) { + let arr = sColor.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(",") + return arr.map(val => Number(val)); + } else { + return sColor; + } +}; + +// 将rgb表示方式转换为hex表示方式 +function rgbToHex(rgb) { + let _this = rgb; + let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/; + if (/^(rgb|RGB)/.test(_this)) { + let aColor = _this.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(","); + let strHex = "#"; + for (let i = 0; i < aColor.length; i++) { + let hex = Number(aColor[i]).toString(16); + hex = String(hex).length == 1 ? 0 + '' + hex : hex; // 保证每个rgb的值为2位 + if (hex === "0") { + hex += hex; + } + strHex += hex; + } + if (strHex.length !== 7) { + strHex = _this; + } + return strHex; + } else if (reg.test(_this)) { + let aNum = _this.replace(/#/, "").split(""); + if (aNum.length === 6) { + return _this; + } else if (aNum.length === 3) { + let numHex = "#"; + for (let i = 0; i < aNum.length; i += 1) { + numHex += (aNum[i] + aNum[i]); + } + return numHex; + } + } else { + return _this; + } +} + + +/** +* JS颜色十六进制转换为rgb或rgba,返回的格式为 rgba(255,255,255,0.5)字符串 +* sHex为传入的十六进制的色值 +* alpha为rgba的透明度 +*/ +function colorToRgba(color, alpha = 0.3) { + color = rgbToHex(color) + // 十六进制颜色值的正则表达式 + var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/ + /* 16进制颜色转为RGB格式 */ + let sColor = color.toLowerCase() + if (sColor && reg.test(sColor)) { + if (sColor.length === 4) { + var sColorNew = '#' + for (let i = 1; i < 4; i += 1) { + sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1)) + } + sColor = sColorNew + } + // 处理六位的颜色值 + var sColorChange = [] + for (let i = 1; i < 7; i += 2) { + sColorChange.push(parseInt('0x' + sColor.slice(i, i + 2))) + } + // return sColorChange.join(',') + return 'rgba(' + sColorChange.join(',') + ',' + alpha + ')' + } + else { + return sColor + } +} + +export default { + colorGradient, + hexToRgb, + rgbToHex, + colorToRgba +} \ No newline at end of file diff --git a/libs/function/debounce.js b/libs/function/debounce.js new file mode 100644 index 0000000..4f1027b --- /dev/null +++ b/libs/function/debounce.js @@ -0,0 +1,29 @@ +let timeout = null; + +/** + * 防抖原理:一定时间内,只有最后一次操作,再过wait毫秒后才执行函数 + * + * @param {Function} func 要执行的回调函数 + * @param {Number} wait 延时的时间 + * @param {Boolean} immediate 是否立即执行 + * @return null + */ +function debounce(func, wait = 500, immediate = false) { + // 清除定时器 + if (timeout !== null) clearTimeout(timeout); + // 立即执行,此类情况一般用不到 + if (immediate) { + var callNow = !timeout; + timeout = setTimeout(function() { + timeout = null; + }, wait); + if (callNow) typeof func === 'function' && func(); + } else { + // 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法 + timeout = setTimeout(function() { + typeof func === 'function' && func(); + }, wait); + } +} + +export default debounce diff --git a/libs/function/deepClone.js b/libs/function/deepClone.js new file mode 100644 index 0000000..3db999a --- /dev/null +++ b/libs/function/deepClone.js @@ -0,0 +1,23 @@ +// 判断arr是否为一个数组,返回一个bool值 +function isArray (arr) { + return Object.prototype.toString.call(arr) === '[object Array]'; +} + +// 深度克隆 +function deepClone (obj) { + // 对常见的“非”值,直接返回原来值 + if([null, undefined, NaN, false].includes(obj)) return obj; + if(typeof obj !== "object" && typeof obj !== 'function') { + //原始类型直接返回 + return obj; + } + var o = isArray(obj) ? [] : {}; + for(let i in obj) { + if(obj.hasOwnProperty(i)){ + o[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i]; + } + } + return o; +} + +export default deepClone; diff --git a/libs/function/deepMerge.js b/libs/function/deepMerge.js new file mode 100644 index 0000000..81d2d18 --- /dev/null +++ b/libs/function/deepMerge.js @@ -0,0 +1,30 @@ +import deepClone from "./deepClone"; + +// JS对象深度合并 +function deepMerge(target = {}, source = {}) { + target = deepClone(target); + if (typeof target !== 'object' || typeof source !== 'object') return false; + for (var prop in source) { + if (!source.hasOwnProperty(prop)) continue; + if (prop in target) { + if (typeof target[prop] !== 'object') { + target[prop] = source[prop]; + } else { + if (typeof source[prop] !== 'object') { + target[prop] = source[prop]; + } else { + if (target[prop].concat && source[prop].concat) { + target[prop] = target[prop].concat(source[prop]); + } else { + target[prop] = deepMerge(target[prop], source[prop]); + } + } + } + } else { + target[prop] = source[prop]; + } + } + return target; +} + +export default deepMerge; \ No newline at end of file diff --git a/libs/function/getParent.js b/libs/function/getParent.js new file mode 100644 index 0000000..9cb45c4 --- /dev/null +++ b/libs/function/getParent.js @@ -0,0 +1,47 @@ +// 获取父组件的参数,因为支付宝小程序不支持provide/inject的写法 +// this.$parent在非H5中,可以准确获取到父组件,但是在H5中,需要多次this.$parent.$parent.xxx +export default function getParent(name, keys) { + let parent = this.$parent; + // 通过while历遍,这里主要是为了H5需要多层解析的问题 + while (parent) { + // 父组件 + if (parent.$options.name !== name) { + // 如果组件的name不相等,继续上一级寻找 + parent = parent.$parent; + } else { + let data = {}; + // 判断keys是否数组,如果传过来的是一个数组,那么直接使用数组元素值当做键值去父组件寻找 + if(Array.isArray(keys)) { + keys.map(val => { + data[val] = parent[val] ? parent[val] : ''; + }) + } else { + // 历遍传过来的对象参数 + for(let i in keys) { + // 如果子组件有此值则用,无此值则用父组件的值 + // 判断是否空数组,如果是,则用父组件的值,否则用子组件的值 + if(Array.isArray(keys[i])) { + if(keys[i].length) { + data[i] = keys[i]; + } else { + data[i] = parent[i]; + } + } else if(keys[i].constructor === Object) { + // 判断是否对象,如果是对象,且有属性,那么使用子组件的值,否则使用父组件的值 + if(Object.keys(keys[i]).length) { + data[i] = keys[i]; + } else { + data[i] = parent[i]; + } + } else { + // 只要子组件有传值,即使是false值,也是“传值”了,也需要覆盖父组件的同名参数 + data[i] = (keys[i] || keys[i] === false) ? keys[i] : parent[i]; + } + } + } + return data; + } + } + + return {}; +} \ No newline at end of file diff --git a/libs/function/guid.js b/libs/function/guid.js new file mode 100644 index 0000000..e04190a --- /dev/null +++ b/libs/function/guid.js @@ -0,0 +1,41 @@ +/** + * 本算法来源于简书开源代码,详见:https://www.jianshu.com/p/fdbf293d0a85 + * 全局唯一标识符(uuid,Globally Unique Identifier),也称作 uuid(Universally Unique IDentifier) + * 一般用于多个组件之间,给它一个唯一的标识符,或者v-for循环的时候,如果使用数组的index可能会导致更新列表出现问题 + * 最可能的情况是左滑删除item或者对某条信息流"不喜欢"并去掉它的时候,会导致组件内的数据可能出现错乱 + * v-for的时候,推荐使用后端返回的id而不是循环的index + * @param {Number} len uuid的长度 + * @param {Boolean} firstU 将返回的首字母置为"u" + * @param {Number} radix 生成uuid的基数(意味着返回的字符串都是这个基数),2-二进制,8-八进制,10-十进制,16-十六进制 + */ +function guid(len = 32, firstU = true, radix = null) { + let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''); + let uuid = []; + radix = radix || chars.length; + + if (len) { + // 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位 + for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]; + } else { + let r; + // rfc4122标准要求返回的uuid中,某些位为固定的字符 + uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'; + uuid[14] = '4'; + + for (let i = 0; i < 36; i++) { + if (!uuid[i]) { + r = 0 | Math.random() * 16; + uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]; + } + } + } + // 移除第一个字符,并用u替代,因为第一个字符为数值时,该guid不能用作id或者class + if (firstU) { + uuid.shift(); + return 'u' + uuid.join(''); + } else { + return uuid.join(''); + } +} + +export default guid; diff --git a/libs/function/md5.js b/libs/function/md5.js new file mode 100644 index 0000000..8d541a1 --- /dev/null +++ b/libs/function/md5.js @@ -0,0 +1,385 @@ +/* + * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message + * Digest Algorithm, as defined in RFC 1321. + * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for more info. + */ + +/* + * Configurable variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + */ +var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ +var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ + +/* + * These are the functions you'll usually want to call + * They take string arguments and return either hex or base-64 encoded strings + */ +function hex_md5(s) { return rstr2hex(rstr_md5(str2rstr_utf8(s))); } +function b64_md5(s) { return rstr2b64(rstr_md5(str2rstr_utf8(s))); } +function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); } +function hex_hmac_md5(k, d) + { return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); } +function b64_hmac_md5(k, d) + { return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); } +function any_hmac_md5(k, d, e) + { return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); } + +/* + * Perform a simple self-test to see if the VM is working + */ +function md5_vm_test() +{ + return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72"; +} + +/* + * Calculate the MD5 of a raw string + */ +function rstr_md5(s) +{ + return binl2rstr(binl_md5(rstr2binl(s), s.length * 8)); +} + +/* + * Calculate the HMAC-MD5, of a key and some data (raw strings) + */ +function rstr_hmac_md5(key, data) +{ + var bkey = rstr2binl(key); + if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8); + + var ipad = Array(16), opad = Array(16); + for(var i = 0; i < 16; i++) + { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + + var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8); + return binl2rstr(binl_md5(opad.concat(hash), 512 + 128)); +} + +/* + * Convert a raw string to a hex string + */ +function rstr2hex(input) +{ + try { hexcase } catch(e) { hexcase=0; } + var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; + var output = ""; + var x; + for(var i = 0; i < input.length; i++) + { + x = input.charCodeAt(i); + output += hex_tab.charAt((x >>> 4) & 0x0F) + + hex_tab.charAt( x & 0x0F); + } + return output; +} + +/* + * Convert a raw string to a base-64 string + */ +function rstr2b64(input) +{ + try { b64pad } catch(e) { b64pad=''; } + var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var output = ""; + var len = input.length; + for(var i = 0; i < len; i += 3) + { + var triplet = (input.charCodeAt(i) << 16) + | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0) + | (i + 2 < len ? input.charCodeAt(i+2) : 0); + for(var j = 0; j < 4; j++) + { + if(i * 8 + j * 6 > input.length * 8) output += b64pad; + else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F); + } + } + return output; +} + +/* + * Convert a raw string to an arbitrary string encoding + */ +function rstr2any(input, encoding) +{ + var divisor = encoding.length; + var i, j, q, x, quotient; + + /* Convert to an array of 16-bit big-endian values, forming the dividend */ + var dividend = Array(Math.ceil(input.length / 2)); + for(i = 0; i < dividend.length; i++) + { + dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); + } + + /* + * Repeatedly perform a long division. The binary array forms the dividend, + * the length of the encoding is the divisor. Once computed, the quotient + * forms the dividend for the next step. All remainders are stored for later + * use. + */ + var full_length = Math.ceil(input.length * 8 / + (Math.log(encoding.length) / Math.log(2))); + var remainders = Array(full_length); + for(j = 0; j < full_length; j++) + { + quotient = Array(); + x = 0; + for(i = 0; i < dividend.length; i++) + { + x = (x << 16) + dividend[i]; + q = Math.floor(x / divisor); + x -= q * divisor; + if(quotient.length > 0 || q > 0) + quotient[quotient.length] = q; + } + remainders[j] = x; + dividend = quotient; + } + + /* Convert the remainders to the output string */ + var output = ""; + for(i = remainders.length - 1; i >= 0; i--) + output += encoding.charAt(remainders[i]); + + return output; +} + +/* + * Encode a string as utf-8. + * For efficiency, this assumes the input is valid utf-16. + */ +function str2rstr_utf8(input) +{ + var output = ""; + var i = -1; + var x, y; + + while(++i < input.length) + { + /* Decode utf-16 surrogate pairs */ + x = input.charCodeAt(i); + y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0; + if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) + { + x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); + i++; + } + + /* Encode output as utf-8 */ + if(x <= 0x7F) + output += String.fromCharCode(x); + else if(x <= 0x7FF) + output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F), + 0x80 | ( x & 0x3F)); + else if(x <= 0xFFFF) + output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), + 0x80 | ((x >>> 6 ) & 0x3F), + 0x80 | ( x & 0x3F)); + else if(x <= 0x1FFFFF) + output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), + 0x80 | ((x >>> 12) & 0x3F), + 0x80 | ((x >>> 6 ) & 0x3F), + 0x80 | ( x & 0x3F)); + } + return output; +} + +/* + * Encode a string as utf-16 + */ +function str2rstr_utf16le(input) +{ + var output = ""; + for(var i = 0; i < input.length; i++) + output += String.fromCharCode( input.charCodeAt(i) & 0xFF, + (input.charCodeAt(i) >>> 8) & 0xFF); + return output; +} + +function str2rstr_utf16be(input) +{ + var output = ""; + for(var i = 0; i < input.length; i++) + output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, + input.charCodeAt(i) & 0xFF); + return output; +} + +/* + * Convert a raw string to an array of little-endian words + * Characters >255 have their high-byte silently ignored. + */ +function rstr2binl(input) +{ + var output = Array(input.length >> 2); + for(var i = 0; i < output.length; i++) + output[i] = 0; + for(var i = 0; i < input.length * 8; i += 8) + output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32); + return output; +} + +/* + * Convert an array of little-endian words to a string + */ +function binl2rstr(input) +{ + var output = ""; + for(var i = 0; i < input.length * 32; i += 8) + output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF); + return output; +} + +/* + * Calculate the MD5 of an array of little-endian words, and a bit length. + */ +function binl_md5(x, len) +{ + /* append padding */ + x[len >> 5] |= 0x80 << ((len) % 32); + x[(((len + 64) >>> 9) << 4) + 14] = len; + + var a = 1732584193; + var b = -271733879; + var c = -1732584194; + var d = 271733878; + + for(var i = 0; i < x.length; i += 16) + { + var olda = a; + var oldb = b; + var oldc = c; + var oldd = d; + + a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); + d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); + c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); + b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); + a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); + d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); + c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); + b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); + a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); + d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); + c = md5_ff(c, d, a, b, x[i+10], 17, -42063); + b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); + a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); + d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); + c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); + b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); + + a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); + d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); + c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); + b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); + a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); + d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); + c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); + b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); + a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); + d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); + c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); + b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); + a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); + d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); + c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); + b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); + + a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); + d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); + c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); + b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); + a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); + d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); + c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); + b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); + a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); + d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); + c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); + b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); + a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); + d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); + c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); + b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); + + a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); + d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); + c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); + b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); + a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); + d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); + c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); + b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); + a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); + d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); + c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); + b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); + a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); + d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); + c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); + b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + } + return Array(a, b, c, d); +} + +/* + * These functions implement the four basic operations the algorithm uses. + */ +function md5_cmn(q, a, b, x, s, t) +{ + return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); +} +function md5_ff(a, b, c, d, x, s, t) +{ + return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); +} +function md5_gg(a, b, c, d, x, s, t) +{ + return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); +} +function md5_hh(a, b, c, d, x, s, t) +{ + return md5_cmn(b ^ c ^ d, a, b, x, s, t); +} +function md5_ii(a, b, c, d, x, s, t) +{ + return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); +} + +/* + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ +function safe_add(x, y) +{ + var lsw = (x & 0xFFFF) + (y & 0xFFFF); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); +} + +/* + * Bitwise rotate a 32-bit number to the left. + */ +function bit_rol(num, cnt) +{ + return (num << cnt) | (num >>> (32 - cnt)); +} + +module.exports = { + md5 : function(str){ + return hex_md5(str); + } +} \ No newline at end of file diff --git a/libs/function/queryParams.js b/libs/function/queryParams.js new file mode 100644 index 0000000..81c7e5e --- /dev/null +++ b/libs/function/queryParams.js @@ -0,0 +1,58 @@ +/** + * 对象转url参数 + * @param {*} data,对象 + * @param {*} isPrefix,是否自动加上"?" + */ +function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') { + let prefix = isPrefix ? '?' : '' + let _result = [] + if (['indices', 'brackets', 'repeat', 'comma'].indexOf(arrayFormat) == -1) arrayFormat = 'brackets'; + for (let key in data) { + let value = data[key] + // 去掉为空的参数 + if (['', undefined, null].indexOf(value) >= 0) { + continue; + } + // 如果值为数组,另行处理 + if (value.constructor === Array) { + // e.g. {ids: [1, 2, 3]} + switch (arrayFormat) { + case 'indices': + // 结果: ids[0]=1&ids[1]=2&ids[2]=3 + for (let i = 0; i < value.length; i++) { + _result.push(key + '[' + i + ']=' + value[i]) + } + break; + case 'brackets': + // 结果: ids[]=1&ids[]=2&ids[]=3 + value.forEach(_value => { + _result.push(key + '[]=' + _value) + }) + break; + case 'repeat': + // 结果: ids=1&ids=2&ids=3 + value.forEach(_value => { + _result.push(key + '=' + _value) + }) + break; + case 'comma': + // 结果: ids=1,2,3 + let commaStr = ""; + value.forEach(_value => { + commaStr += (commaStr ? "," : "") + _value; + }) + _result.push(key + '=' + commaStr) + break; + default: + value.forEach(_value => { + _result.push(key + '[]=' + _value) + }) + } + } else { + _result.push(key + '=' + value) + } + } + return _result.length ? prefix + _result.join('&') : '' +} + +export default queryParams; diff --git a/libs/function/random.js b/libs/function/random.js new file mode 100644 index 0000000..e155279 --- /dev/null +++ b/libs/function/random.js @@ -0,0 +1,10 @@ +function random(min, max) { + if (min >= 0 && max > 0 && max >= min) { + let gab = max - min + 1; + return Math.floor(Math.random() * gab + min); + } else { + return 0; + } +} + +export default random; diff --git a/libs/function/randomArray.js b/libs/function/randomArray.js new file mode 100644 index 0000000..590a048 --- /dev/null +++ b/libs/function/randomArray.js @@ -0,0 +1,7 @@ +// 打乱数组 +function randomArray(array = []) { + // 原理是sort排序,Math.random()产生0<= x < 1之间的数,会导致x-0.05大于或者小于0 + return array.sort(() => Math.random() - 0.5); +} + +export default randomArray diff --git a/libs/function/route.js b/libs/function/route.js new file mode 100644 index 0000000..28a81b7 --- /dev/null +++ b/libs/function/route.js @@ -0,0 +1,122 @@ +/** + * 路由跳转方法,该方法相对于直接使用uni.xxx的好处是使用更加简单快捷 + * 并且带有路由拦截功能 + */ + +class Router { + constructor() { + // 原始属性定义 + this.config = { + type: 'navigateTo', + url: '', + delta: 1, // navigateBack页面后退时,回退的层数 + params: {}, // 传递的参数 + animationType: 'pop-in', // 窗口动画,只在APP有效 + animationDuration: 300, // 窗口动画持续时间,单位毫秒,只在APP有效 + intercept: false, // 是否需要拦截 + } + // 因为route方法是需要对外赋值给另外的对象使用,同时route内部有使用this,会导致route失去上下文 + // 这里在构造函数中进行this绑定 + this.route = this.route.bind(this) + } + + // 判断url前面是否有"/",如果没有则加上,否则无法跳转 + addRootPath(url) { + return url[0] === '/' ? url : `/${url}` + } + + // 整合路由参数 + mixinParam(url, params) { + url = url && this.addRootPath(url) + + // 使用正则匹配,主要依据是判断是否有"/","?","="等,如“/page/index/index?name=mary" + // 如果有url中有get参数,转换后无需带上"?" + let query = '' + if (/.*\/.*\?.*=.*/.test(url)) { + // object对象转为get类型的参数 + query = uni.$u.queryParams(params, false); + // 因为已有get参数,所以后面拼接的参数需要带上"&"隔开 + return url += "&" + query + } else { + // 直接拼接参数,因为此处url中没有后面的query参数,也就没有"?/&"之类的符号 + query = uni.$u.queryParams(params); + return url += query + } + } + + // 对外的方法名称 + async route(options = {}, params = {}) { + // 合并用户的配置和内部的默认配置 + let mergeConfig = {} + + if (typeof options === 'string') { + // 如果options为字符串,则为route(url, params)的形式 + mergeConfig.url = this.mixinParam(options, params) + mergeConfig.type = 'navigateTo' + } else { + mergeConfig = uni.$u.deepClone(options, this.config) + // 否则正常使用mergeConfig中的url和params进行拼接 + mergeConfig.url = this.mixinParam(options.url, options.params) + } + + if(params.intercept) { + this.config.intercept = params.intercept + } + // params参数也带给拦截器 + mergeConfig.params = params + // 合并内外部参数 + mergeConfig = uni.$u.deepMerge(this.config, mergeConfig) + // 判断用户是否定义了拦截器 + if (typeof uni.$u.routeIntercept === 'function') { + // 定一个promise,根据用户执行resolve(true)或者resolve(false)来决定是否进行路由跳转 + const isNext = await new Promise((resolve, reject) => { + uni.$u.routeIntercept(mergeConfig, resolve) + }) + // 如果isNext为true,则执行路由跳转 + isNext && this.openPage(mergeConfig) + } else { + this.openPage(mergeConfig) + } + } + + // 执行路由跳转 + openPage(config) { + // 解构参数 + const { + url, + type, + delta, + animationType, + animationDuration + } = config + if (config.type == 'navigateTo' || config.type == 'to') { + uni.navigateTo({ + url, + animationType, + animationDuration + }); + } + if (config.type == 'redirectTo' || config.type == 'redirect') { + uni.redirectTo({ + url + }); + } + if (config.type == 'switchTab' || config.type == 'tab') { + uni.switchTab({ + url + }); + } + if (config.type == 'reLaunch' || config.type == 'launch') { + uni.reLaunch({ + url + }); + } + if (config.type == 'navigateBack' || config.type == 'back') { + uni.navigateBack({ + delta + }); + } + } +} + +export default (new Router()).route \ No newline at end of file diff --git a/libs/function/sys.js b/libs/function/sys.js new file mode 100644 index 0000000..00f6a28 --- /dev/null +++ b/libs/function/sys.js @@ -0,0 +1,9 @@ +export function os() { + return uni.getSystemInfoSync().platform; +}; + +export function sys() { + return uni.getSystemInfoSync(); +} + + diff --git a/libs/function/test.js b/libs/function/test.js new file mode 100644 index 0000000..1fde462 --- /dev/null +++ b/libs/function/test.js @@ -0,0 +1,232 @@ +/** + * 验证电子邮箱格式 + */ +function email(value) { + return /[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?/.test(value); +} + +/** + * 验证手机格式 + */ +function mobile(value) { + return /^1[3-9]\d{9}$/.test(value) +} + +/** + * 验证URL格式 + */ +function url(value) { + return /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w-.\/?%&=]*)?/.test(value) +} + +/** + * 验证日期格式 + */ +function date(value) { + return !/Invalid|NaN/.test(new Date(value).toString()) +} + +/** + * 验证ISO类型的日期格式 + */ +function dateISO(value) { + return /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value) +} + +/** + * 验证十进制数字 + */ +function number(value) { + return /^[\+-]?(\d+\.?\d*|\.\d+|\d\.\d+e\+\d+)$/.test(value) +} + +/** + * 验证整数 + */ +function digits(value) { + return /^\d+$/.test(value) +} + +/** + * 验证身份证号码 + */ +function idCard(value) { + return /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test( + value) +} + +/** + * 是否车牌号 + */ +function carNo(value) { + // 新能源车牌 + const xreg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/; + // 旧车牌 + const creg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/; + if (value.length === 7) { + return creg.test(value); + } else if (value.length === 8) { + return xreg.test(value); + } else { + return false; + } +} + +/** + * 金额,只允许2位小数 + */ +function amount(value) { + //金额,只允许保留两位小数 + return /^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0\.\d{1,2}$/.test(value); +} + +/** + * 中文 + */ +function chinese(value) { + let reg = /^[\u4e00-\u9fa5]+$/gi; + return reg.test(value); +} + +/** + * 只能输入字母 + */ +function letter(value) { + return /^[a-zA-Z]*$/.test(value); +} + +/** + * 只能是字母或者数字 + */ +function enOrNum(value) { + //英文或者数字 + let reg = /^[0-9a-zA-Z]*$/g; + return reg.test(value); +} + +/** + * 验证是否包含某个值 + */ +function contains(value, param) { + return value.indexOf(param) >= 0 +} + +/** + * 验证一个值范围[min, max] + */ +function range(value, param) { + return value >= param[0] && value <= param[1] +} + +/** + * 验证一个长度范围[min, max] + */ +function rangeLength(value, param) { + return value.length >= param[0] && value.length <= param[1] +} + +/** + * 是否固定电话 + */ +function landline(value) { + let reg = /^\d{3,4}-\d{7,8}(-\d{3,4})?$/; + return reg.test(value); +} + +/** + * 判断是否为空 + */ +function empty(value) { + switch (typeof value) { + case 'undefined': + return true; + case 'string': + if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true; + break; + case 'boolean': + if (!value) return true; + break; + case 'number': + if (0 === value || isNaN(value)) return true; + break; + case 'object': + if (null === value || value.length === 0) return true; + for (var i in value) { + return false; + } + return true; + } + return false; +} + +/** + * 是否json字符串 + */ +function jsonString(value) { + if (typeof value == 'string') { + try { + var obj = JSON.parse(value); + if (typeof obj == 'object' && obj) { + return true; + } else { + return false; + } + } catch (e) { + return false; + } + } + return false; +} + + +/** + * 是否数组 + */ +function array(value) { + if (typeof Array.isArray === "function") { + return Array.isArray(value); + } else { + return Object.prototype.toString.call(value) === "[object Array]"; + } +} + +/** + * 是否对象 + */ +function object(value) { + return Object.prototype.toString.call(value) === '[object Object]'; +} + +/** + * 是否短信验证码 + */ +function code(value, len = 6) { + return new RegExp(`^\\d{${len}}$`).test(value); +} + + +export default { + email, + mobile, + url, + date, + dateISO, + number, + digits, + idCard, + carNo, + amount, + chinese, + letter, + enOrNum, + contains, + range, + rangeLength, + empty, + isEmpty: empty, + jsonString, + landline, + object, + array, + code +} diff --git a/libs/function/throttle.js b/libs/function/throttle.js new file mode 100644 index 0000000..ad830b2 --- /dev/null +++ b/libs/function/throttle.js @@ -0,0 +1,32 @@ +let timer, flag; +/** + * 节流原理:在一定时间内,只能触发一次 + * + * @param {Function} func 要执行的回调函数 + * @param {Number} wait 延时的时间 + * @param {Boolean} immediate 是否立即执行 + * @return null + */ +function throttle(func, wait = 500, immediate = true) { + if (immediate) { + if (!flag) { + flag = true; + // 如果是立即执行,则在wait毫秒内开始时执行 + typeof func === 'function' && func(); + timer = setTimeout(() => { + flag = false; + }, wait); + } + } else { + if (!flag) { + flag = true + // 如果是非立即执行,则在wait毫秒内的结束处执行 + timer = setTimeout(() => { + flag = false + typeof func === 'function' && func(); + }, wait); + } + + } +}; +export default throttle diff --git a/libs/function/timeFormat.js b/libs/function/timeFormat.js new file mode 100644 index 0000000..0372f2f --- /dev/null +++ b/libs/function/timeFormat.js @@ -0,0 +1,51 @@ +// padStart 的 polyfill,因为某些机型或情况,还无法支持es7的padStart,比如电脑版的微信小程序 +// 所以这里做一个兼容polyfill的兼容处理 +if (!String.prototype.padStart) { + // 为了方便表示这里 fillString 用了ES6 的默认参数,不影响理解 + String.prototype.padStart = function(maxLength, fillString = ' ') { + if (Object.prototype.toString.call(fillString) !== "[object String]") throw new TypeError( + 'fillString must be String') + let str = this + // 返回 String(str) 这里是为了使返回的值是字符串字面量,在控制台中更符合直觉 + if (str.length >= maxLength) return String(str) + + let fillLength = maxLength - str.length, + times = Math.ceil(fillLength / fillString.length) + while (times >>= 1) { + fillString += fillString + if (times === 1) { + fillString += fillString + } + } + return fillString.slice(0, fillLength) + str; + } +} + +// 其他更多是格式化有如下: +// yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合 +function timeFormat(dateTime = null, fmt = 'yyyy-mm-dd') { + // 如果为null,则格式化当前时间 + if (!dateTime) dateTime = Number(new Date()); + // 如果dateTime长度为10或者13,则为秒和毫秒的时间戳,如果超过13位,则为其他的时间格式 + if (dateTime.toString().length == 10) dateTime *= 1000; + let date = new Date(dateTime); + let ret; + let opt = { + "y+": date.getFullYear().toString(), // 年 + "m+": (date.getMonth() + 1).toString(), // 月 + "d+": date.getDate().toString(), // 日 + "h+": date.getHours().toString(), // 时 + "M+": date.getMinutes().toString(), // 分 + "s+": date.getSeconds().toString() // 秒 + // 有其他格式化字符需求可以继续添加,必须转化成字符串 + }; + for (let k in opt) { + ret = new RegExp("(" + k + ")").exec(fmt); + if (ret) { + fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0"))) + }; + }; + return fmt; +} + +export default timeFormat diff --git a/libs/function/timeFrom.js b/libs/function/timeFrom.js new file mode 100644 index 0000000..68cd990 --- /dev/null +++ b/libs/function/timeFrom.js @@ -0,0 +1,47 @@ +import timeFormat from '../../libs/function/timeFormat.js'; + +/** + * 时间戳转为多久之前 + * @param String timestamp 时间戳 + * @param String | Boolean format 如果为时间格式字符串,超出一定时间范围,返回固定的时间格式; + * 如果为布尔值false,无论什么时间,都返回多久以前的格式 + */ +function timeFrom(dateTime = null, format = 'yyyy-mm-dd') { + // 如果为null,则格式化当前时间 + if (!dateTime) dateTime = Number(new Date()); + // 如果dateTime长度为10或者13,则为秒和毫秒的时间戳,如果超过13位,则为其他的时间格式 + if (dateTime.toString().length == 10) dateTime *= 1000; + let timestamp = + new Date(Number(dateTime)); + + let timer = (Number(new Date()) - timestamp) / 1000; + // 如果小于5分钟,则返回"刚刚",其他以此类推 + let tips = ''; + switch (true) { + case timer < 300: + tips = '刚刚'; + break; + case timer >= 300 && timer < 3600: + tips = parseInt(timer / 60) + '分钟前'; + break; + case timer >= 3600 && timer < 86400: + tips = parseInt(timer / 3600) + '小时前'; + break; + case timer >= 86400 && timer < 2592000: + tips = parseInt(timer / 86400) + '天前'; + break; + default: + // 如果format为false,则无论什么时间戳,都显示xx之前 + if(format === false) { + if(timer >= 2592000 && timer < 365 * 86400) { + tips = parseInt(timer / (86400 * 30)) + '个月前'; + } else { + tips = parseInt(timer / (86400 * 365)) + '年前'; + } + } else { + tips = timeFormat(timestamp, format); + } + } + return tips; +} + +export default timeFrom; diff --git a/libs/function/toast.js b/libs/function/toast.js new file mode 100644 index 0000000..91afa73 --- /dev/null +++ b/libs/function/toast.js @@ -0,0 +1,9 @@ +function toast(title, duration = 1500) { + uni.showToast({ + title: title, + icon: 'none', + duration: duration + }) +} + +export default toast diff --git a/libs/function/trim.js b/libs/function/trim.js new file mode 100644 index 0000000..72adc37 --- /dev/null +++ b/libs/function/trim.js @@ -0,0 +1,15 @@ +function trim(str, pos = 'both') { + if (pos == 'both') { + return str.replace(/^\s+|\s+$/g, ""); + } else if (pos == "left") { + return str.replace(/^\s*/, ''); + } else if (pos == 'right') { + return str.replace(/(\s*$)/g, ""); + } else if (pos == 'all') { + return str.replace(/\s+/g, ""); + } else { + return str; + } +} + +export default trim diff --git a/libs/function/type2icon.js b/libs/function/type2icon.js new file mode 100644 index 0000000..23cb40e --- /dev/null +++ b/libs/function/type2icon.js @@ -0,0 +1,35 @@ +/** + * 根据主题type值,获取对应的图标 + * @param String type 主题名称,primary|info|error|warning|success + * @param String fill 是否使用fill填充实体的图标 + */ +function type2icon(type = 'success', fill = false) { + // 如果非预置值,默认为success + if (['primary', 'info', 'error', 'warning', 'success'].indexOf(type) == -1) type = 'success'; + let iconName = ''; + // 目前(2019-12-12),info和primary使用同一个图标 + switch (type) { + case 'primary': + iconName = 'info-circle'; + break; + case 'info': + iconName = 'info-circle'; + break; + case 'error': + iconName = 'close-circle'; + break; + case 'warning': + iconName = 'error-circle'; + break; + case 'success': + iconName = 'checkmark-circle'; + break; + default: + iconName = 'checkmark-circle'; + } + // 是否是实体类型,加上-fill,在icon组件库中,实体的类名是后面加-fill的 + if (fill) iconName += '-fill'; + return iconName; +} + +export default type2icon diff --git a/libs/mixin/mixin.js b/libs/mixin/mixin.js new file mode 100644 index 0000000..cb64545 --- /dev/null +++ b/libs/mixin/mixin.js @@ -0,0 +1,64 @@ +module.exports = { + data() { + return {} + }, + onLoad() { + // getRect挂载到$u上,因为这方法需要使用in(this),所以无法把它独立成一个单独的文件导出 + this.$u.getRect = this.$uGetRect + }, + methods: { + // 查询节点信息 + // 目前此方法在支付宝小程序中无法获取组件跟接点的尺寸,为支付宝的bug(2020-07-21) + // 解决办法为在组件根部再套一个没有任何作用的view元素 + $uGetRect(selector, all) { + return new Promise(resolve => { + uni.createSelectorQuery(). + in(this)[all ? 'selectAll' : 'select'](selector) + .boundingClientRect(rect => { + if (all && Array.isArray(rect) && rect.length) { + resolve(rect) + } + if (!all && rect) { + resolve(rect) + } + }) + .exec() + }) + }, + getParentData(parentName = '') { + // 避免在created中去定义parent变量 + if(!this.parent) this.parent = false; + // 这里的本质原理是,通过获取父组件实例(也即u-radio-group的this) + // 将父组件this中对应的参数,赋值给本组件(u-radio的this)的parentData对象中对应的属性 + // 之所以需要这么做,是因为所有端中,头条小程序不支持通过this.parent.xxx去监听父组件参数的变化 + this.parent = this.$u.$parent.call(this, parentName); + if(this.parent) { + // 历遍parentData中的属性,将parent中的同名属性赋值给parentData + Object.keys(this.parentData).map(key => { + this.parentData[key] = this.parent[key]; + }); + } + }, + // 阻止事件冒泡 + preventEvent(e) { + e && e.stopPropagation && e.stopPropagation() + } + }, + onReachBottom() { + uni.$emit('uOnReachBottom') + }, + beforeDestroy() { + // 判断当前页面是否存在parent和children,一般在checkbox和checkbox-group父子联动的场景会有此情况 + // 组件销毁时,移除子组件在父组件children数组中的实例,释放资源,避免数据混乱 + if(this.parent && uni.$u.test.array(this.parent.children)) { + // 组件销毁时,移除父组件中的children数组中对应的实例 + const childrenList = this.parent.children + childrenList.map((child, index) => { + // 如果相等,则移除 + if(child === this) { + childrenList.splice(index, 1) + } + }) + } + } +} diff --git a/libs/mixin/mpShare.js b/libs/mixin/mpShare.js new file mode 100644 index 0000000..057d369 --- /dev/null +++ b/libs/mixin/mpShare.js @@ -0,0 +1,18 @@ +module.exports = { + onLoad() { + // 设置默认的转发参数 + this.$u.mpShare = { + title: '', // 默认为小程序名称 + path: '', // 默认为当前页面路径 + imageUrl: '' // 默认为当前页面的截图 + } + }, + onShareAppMessage() { + return this.$u.mpShare + }, + // #ifdef MP-WEIXIN + onShareTimeline() { + return this.$u.mpShare + } + // #endif +} diff --git a/libs/request/index.js b/libs/request/index.js new file mode 100644 index 0000000..1f5f471 --- /dev/null +++ b/libs/request/index.js @@ -0,0 +1,169 @@ +import deepMerge from "../function/deepMerge"; +import validate from "../function/test"; +class Request { + // 设置全局默认配置 + setConfig(customConfig) { + // 深度合并对象,否则会造成对象深层属性丢失 + this.config = deepMerge(this.config, customConfig); + } + + // 主要请求部分 + request(options = {}) { + // 检查请求拦截 + if (this.interceptor.request && typeof this.interceptor.request === 'function') { + let tmpConfig = {}; + let interceptorRequest = this.interceptor.request(options); + if (interceptorRequest === false) { + // 返回一个处于pending状态中的Promise,来取消原promise,避免进入then()回调 + return new Promise(()=>{}); + } + this.options = interceptorRequest; + } + options.dataType = options.dataType || this.config.dataType; + options.responseType = options.responseType || this.config.responseType; + options.url = options.url || ''; + options.params = options.params || {}; + options.header = Object.assign({}, this.config.header, options.header); + options.method = options.method || this.config.method; + + return new Promise((resolve, reject) => { + options.complete = (response) => { + // 请求返回后,隐藏loading(如果请求返回快的话,可能会没有loading) + uni.hideLoading(); + // 清除定时器,如果请求回来了,就无需loading + clearTimeout(this.config.timer); + this.config.timer = null; + // 判断用户对拦截返回数据的要求,如果originalData为true,返回所有的数据(response)到拦截器,否则只返回response.data + if(this.config.originalData) { + // 判断是否存在拦截器 + if (this.interceptor.response && typeof this.interceptor.response === 'function') { + let resInterceptors = this.interceptor.response(response); + // 如果拦截器不返回false,就将拦截器返回的内容给this.$u.post的then回调 + if (resInterceptors !== false) { + resolve(resInterceptors); + } else { + // 如果拦截器返回false,意味着拦截器定义者认为返回有问题,直接接入catch回调 + reject(response); + } + } else { + // 如果要求返回原始数据,就算没有拦截器,也返回最原始的数据 + resolve(response); + } + } else { + if (response.statusCode == 200) { + if (this.interceptor.response && typeof this.interceptor.response === 'function') { + let resInterceptors = this.interceptor.response(response.data); + if (resInterceptors !== false) { + resolve(resInterceptors); + } else { + reject(response.data); + } + } else { + // 如果不是返回原始数据(originalData=false),且没有拦截器的情况下,返回纯数据给then回调 + resolve(response.data); + } + } else { + // 不返回原始数据的情况下,服务器状态码不为200,modal弹框提示 + // if(response.errMsg) { + // uni.showModal({ + // title: response.errMsg + // }); + // } + reject(response) + } + } + } + + // 判断用户传递的URL是否/开头,如果不是,加上/,这里使用了uView的test.js验证库的url()方法 + options.url = validate.url(options.url) ? options.url : (this.config.baseUrl + (options.url.indexOf('/') == 0 ? + options.url : '/' + options.url)); + + // 是否显示loading + // 加一个是否已有timer定时器的判断,否则有两个同时请求的时候,后者会清除前者的定时器id + // 而没有清除前者的定时器,导致前者超时,一直显示loading + if(this.config.showLoading && !this.config.timer) { + this.config.timer = setTimeout(() => { + uni.showLoading({ + title: this.config.loadingText, + mask: this.config.loadingMask + }) + this.config.timer = null; + }, this.config.loadingTime); + } + uni.request(options); + }) + // .catch(res => { + // // 如果返回reject(),不让其进入this.$u.post().then().catch()后面的catct() + // // 因为很多人都会忘了写后面的catch(),导致报错捕获不到catch + // return new Promise(()=>{}); + // }) + } + + constructor() { + this.config = { + baseUrl: '', // 请求的根域名 + // 默认的请求头 + header: {}, + method: 'POST', + // 设置为json,返回后uni.request会对数据进行一次JSON.parse + dataType: 'json', + // 此参数无需处理,因为5+和支付宝小程序不支持,默认为text即可 + responseType: 'text', + showLoading: true, // 是否显示请求中的loading + loadingText: '请求中...', + loadingTime: 800, // 在此时间内,请求还没回来的话,就显示加载中动画,单位ms + timer: null, // 定时器 + originalData: false, // 是否在拦截器中返回服务端的原始数据,见文档说明 + loadingMask: true, // 展示loading的时候,是否给一个透明的蒙层,防止触摸穿透 + } + + // 拦截器 + this.interceptor = { + // 请求前的拦截 + request: null, + // 请求后的拦截 + response: null + } + + // get请求 + this.get = (url, data = {}, header = {}) => { + return this.request({ + method: 'GET', + url, + header, + data + }) + } + + // post请求 + this.post = (url, data = {}, header = {}) => { + return this.request({ + url, + method: 'POST', + header, + data + }) + } + + // put请求,不支持支付宝小程序(HX2.6.15) + this.put = (url, data = {}, header = {}) => { + return this.request({ + url, + method: 'PUT', + header, + data + }) + } + + // delete请求,不支持支付宝和头条小程序(HX2.6.15) + this.delete = (url, data = {}, header = {}) => { + return this.request({ + url, + method: 'DELETE', + header, + data + }) + } + } +} +export default new Request diff --git a/libs/store/index.js b/libs/store/index.js new file mode 100644 index 0000000..a5927b3 --- /dev/null +++ b/libs/store/index.js @@ -0,0 +1,19 @@ +// 暂时不用vuex模块方式实现,将该方法直接放入到/store/index.js中 +const module = { + actions: { + $uStore({rootState}, params) { + let nameArr = params.name.split('.'); + if(nameArr.length >= 2) { + let obj = rootState[nameArr[0]]; + for(let i = 1; i < nameArr.length - 1; i ++) { + obj = obj[nameArr[i]]; + } + obj[nameArr[nameArr.length - 1]] = params.value; + } else { + rootState[params.name] = params.value; + } + } + } +} + +export default module \ No newline at end of file diff --git a/libs/util/area.js b/libs/util/area.js new file mode 100644 index 0000000..0d602e9 --- /dev/null +++ b/libs/util/area.js @@ -0,0 +1 @@ +var areaData=[[[{"label":"东城区","value":"110101"},{"label":"西城区","value":"110102"},{"label":"朝阳区","value":"110105"},{"label":"丰台区","value":"110106"},{"label":"石景山区","value":"110107"},{"label":"海淀区","value":"110108"},{"label":"门头沟区","value":"110109"},{"label":"房山区","value":"110111"},{"label":"通州区","value":"110112"},{"label":"顺义区","value":"110113"},{"label":"昌平区","value":"110114"},{"label":"大兴区","value":"110115"},{"label":"怀柔区","value":"110116"},{"label":"平谷区","value":"110117"},{"label":"密云区","value":"110118"},{"label":"延庆区","value":"110119"}]],[[{"label":"和平区","value":"120101"},{"label":"河东区","value":"120102"},{"label":"河西区","value":"120103"},{"label":"南开区","value":"120104"},{"label":"河北区","value":"120105"},{"label":"红桥区","value":"120106"},{"label":"东丽区","value":"120110"},{"label":"西青区","value":"120111"},{"label":"津南区","value":"120112"},{"label":"北辰区","value":"120113"},{"label":"武清区","value":"120114"},{"label":"宝坻区","value":"120115"},{"label":"滨海新区","value":"120116"},{"label":"宁河区","value":"120117"},{"label":"静海区","value":"120118"},{"label":"蓟州区","value":"120119"}]],[[{"label":"长安区","value":"130102"},{"label":"桥西区","value":"130104"},{"label":"新华区","value":"130105"},{"label":"井陉矿区","value":"130107"},{"label":"裕华区","value":"130108"},{"label":"藁城区","value":"130109"},{"label":"鹿泉区","value":"130110"},{"label":"栾城区","value":"130111"},{"label":"井陉县","value":"130121"},{"label":"正定县","value":"130123"},{"label":"行唐县","value":"130125"},{"label":"灵寿县","value":"130126"},{"label":"高邑县","value":"130127"},{"label":"深泽县","value":"130128"},{"label":"赞皇县","value":"130129"},{"label":"无极县","value":"130130"},{"label":"平山县","value":"130131"},{"label":"元氏县","value":"130132"},{"label":"赵县","value":"130133"},{"label":"石家庄高新技术产业开发区","value":"130171"},{"label":"石家庄循环化工园区","value":"130172"},{"label":"辛集市","value":"130181"},{"label":"晋州市","value":"130183"},{"label":"新乐市","value":"130184"}],[{"label":"路南区","value":"130202"},{"label":"路北区","value":"130203"},{"label":"古冶区","value":"130204"},{"label":"开平区","value":"130205"},{"label":"丰南区","value":"130207"},{"label":"丰润区","value":"130208"},{"label":"曹妃甸区","value":"130209"},{"label":"滦县","value":"130223"},{"label":"滦南县","value":"130224"},{"label":"乐亭县","value":"130225"},{"label":"迁西县","value":"130227"},{"label":"玉田县","value":"130229"},{"label":"唐山市芦台经济技术开发区","value":"130271"},{"label":"唐山市汉沽管理区","value":"130272"},{"label":"唐山高新技术产业开发区","value":"130273"},{"label":"河北唐山海港经济开发区","value":"130274"},{"label":"遵化市","value":"130281"},{"label":"迁安市","value":"130283"}],[{"label":"海港区","value":"130302"},{"label":"山海关区","value":"130303"},{"label":"北戴河区","value":"130304"},{"label":"抚宁区","value":"130306"},{"label":"青龙满族自治县","value":"130321"},{"label":"昌黎县","value":"130322"},{"label":"卢龙县","value":"130324"},{"label":"秦皇岛市经济技术开发区","value":"130371"},{"label":"北戴河新区","value":"130372"}],[{"label":"邯山区","value":"130402"},{"label":"丛台区","value":"130403"},{"label":"复兴区","value":"130404"},{"label":"峰峰矿区","value":"130406"},{"label":"肥乡区","value":"130407"},{"label":"永年区","value":"130408"},{"label":"临漳县","value":"130423"},{"label":"成安县","value":"130424"},{"label":"大名县","value":"130425"},{"label":"涉县","value":"130426"},{"label":"磁县","value":"130427"},{"label":"邱县","value":"130430"},{"label":"鸡泽县","value":"130431"},{"label":"广平县","value":"130432"},{"label":"馆陶县","value":"130433"},{"label":"魏县","value":"130434"},{"label":"曲周县","value":"130435"},{"label":"邯郸经济技术开发区","value":"130471"},{"label":"邯郸冀南新区","value":"130473"},{"label":"武安市","value":"130481"}],[{"label":"桥东区","value":"130502"},{"label":"桥西区","value":"130503"},{"label":"邢台县","value":"130521"},{"label":"临城县","value":"130522"},{"label":"内丘县","value":"130523"},{"label":"柏乡县","value":"130524"},{"label":"隆尧县","value":"130525"},{"label":"任县","value":"130526"},{"label":"南和县","value":"130527"},{"label":"宁晋县","value":"130528"},{"label":"巨鹿县","value":"130529"},{"label":"新河县","value":"130530"},{"label":"广宗县","value":"130531"},{"label":"平乡县","value":"130532"},{"label":"威县","value":"130533"},{"label":"清河县","value":"130534"},{"label":"临西县","value":"130535"},{"label":"河北邢台经济开发区","value":"130571"},{"label":"南宫市","value":"130581"},{"label":"沙河市","value":"130582"}],[{"label":"竞秀区","value":"130602"},{"label":"莲池区","value":"130606"},{"label":"满城区","value":"130607"},{"label":"清苑区","value":"130608"},{"label":"徐水区","value":"130609"},{"label":"涞水县","value":"130623"},{"label":"阜平县","value":"130624"},{"label":"定兴县","value":"130626"},{"label":"唐县","value":"130627"},{"label":"高阳县","value":"130628"},{"label":"容城县","value":"130629"},{"label":"涞源县","value":"130630"},{"label":"望都县","value":"130631"},{"label":"安新县","value":"130632"},{"label":"易县","value":"130633"},{"label":"曲阳县","value":"130634"},{"label":"蠡县","value":"130635"},{"label":"顺平县","value":"130636"},{"label":"博野县","value":"130637"},{"label":"雄县","value":"130638"},{"label":"保定高新技术产业开发区","value":"130671"},{"label":"保定白沟新城","value":"130672"},{"label":"涿州市","value":"130681"},{"label":"定州市","value":"130682"},{"label":"安国市","value":"130683"},{"label":"高碑店市","value":"130684"}],[{"label":"桥东区","value":"130702"},{"label":"桥西区","value":"130703"},{"label":"宣化区","value":"130705"},{"label":"下花园区","value":"130706"},{"label":"万全区","value":"130708"},{"label":"崇礼区","value":"130709"},{"label":"张北县","value":"130722"},{"label":"康保县","value":"130723"},{"label":"沽源县","value":"130724"},{"label":"尚义县","value":"130725"},{"label":"蔚县","value":"130726"},{"label":"阳原县","value":"130727"},{"label":"怀安县","value":"130728"},{"label":"怀来县","value":"130730"},{"label":"涿鹿县","value":"130731"},{"label":"赤城县","value":"130732"},{"label":"张家口市高新技术产业开发区","value":"130771"},{"label":"张家口市察北管理区","value":"130772"},{"label":"张家口市塞北管理区","value":"130773"}],[{"label":"双桥区","value":"130802"},{"label":"双滦区","value":"130803"},{"label":"鹰手营子矿区","value":"130804"},{"label":"承德县","value":"130821"},{"label":"兴隆县","value":"130822"},{"label":"滦平县","value":"130824"},{"label":"隆化县","value":"130825"},{"label":"丰宁满族自治县","value":"130826"},{"label":"宽城满族自治县","value":"130827"},{"label":"围场满族蒙古族自治县","value":"130828"},{"label":"承德高新技术产业开发区","value":"130871"},{"label":"平泉市","value":"130881"}],[{"label":"新华区","value":"130902"},{"label":"运河区","value":"130903"},{"label":"沧县","value":"130921"},{"label":"青县","value":"130922"},{"label":"东光县","value":"130923"},{"label":"海兴县","value":"130924"},{"label":"盐山县","value":"130925"},{"label":"肃宁县","value":"130926"},{"label":"南皮县","value":"130927"},{"label":"吴桥县","value":"130928"},{"label":"献县","value":"130929"},{"label":"孟村回族自治县","value":"130930"},{"label":"河北沧州经济开发区","value":"130971"},{"label":"沧州高新技术产业开发区","value":"130972"},{"label":"沧州渤海新区","value":"130973"},{"label":"泊头市","value":"130981"},{"label":"任丘市","value":"130982"},{"label":"黄骅市","value":"130983"},{"label":"河间市","value":"130984"}],[{"label":"安次区","value":"131002"},{"label":"广阳区","value":"131003"},{"label":"固安县","value":"131022"},{"label":"永清县","value":"131023"},{"label":"香河县","value":"131024"},{"label":"大城县","value":"131025"},{"label":"文安县","value":"131026"},{"label":"大厂回族自治县","value":"131028"},{"label":"廊坊经济技术开发区","value":"131071"},{"label":"霸州市","value":"131081"},{"label":"三河市","value":"131082"}],[{"label":"桃城区","value":"131102"},{"label":"冀州区","value":"131103"},{"label":"枣强县","value":"131121"},{"label":"武邑县","value":"131122"},{"label":"武强县","value":"131123"},{"label":"饶阳县","value":"131124"},{"label":"安平县","value":"131125"},{"label":"故城县","value":"131126"},{"label":"景县","value":"131127"},{"label":"阜城县","value":"131128"},{"label":"河北衡水经济开发区","value":"131171"},{"label":"衡水滨湖新区","value":"131172"},{"label":"深州市","value":"131182"}]],[[{"label":"小店区","value":"140105"},{"label":"迎泽区","value":"140106"},{"label":"杏花岭区","value":"140107"},{"label":"尖草坪区","value":"140108"},{"label":"万柏林区","value":"140109"},{"label":"晋源区","value":"140110"},{"label":"清徐县","value":"140121"},{"label":"阳曲县","value":"140122"},{"label":"娄烦县","value":"140123"},{"label":"山西转型综合改革示范区","value":"140171"},{"label":"古交市","value":"140181"}],[{"label":"城区","value":"140202"},{"label":"矿区","value":"140203"},{"label":"南郊区","value":"140211"},{"label":"新荣区","value":"140212"},{"label":"阳高县","value":"140221"},{"label":"天镇县","value":"140222"},{"label":"广灵县","value":"140223"},{"label":"灵丘县","value":"140224"},{"label":"浑源县","value":"140225"},{"label":"左云县","value":"140226"},{"label":"大同县","value":"140227"},{"label":"山西大同经济开发区","value":"140271"}],[{"label":"城区","value":"140302"},{"label":"矿区","value":"140303"},{"label":"郊区","value":"140311"},{"label":"平定县","value":"140321"},{"label":"盂县","value":"140322"},{"label":"山西阳泉经济开发区","value":"140371"}],[{"label":"城区","value":"140402"},{"label":"郊区","value":"140411"},{"label":"长治县","value":"140421"},{"label":"襄垣县","value":"140423"},{"label":"屯留县","value":"140424"},{"label":"平顺县","value":"140425"},{"label":"黎城县","value":"140426"},{"label":"壶关县","value":"140427"},{"label":"长子县","value":"140428"},{"label":"武乡县","value":"140429"},{"label":"沁县","value":"140430"},{"label":"沁源县","value":"140431"},{"label":"山西长治高新技术产业园区","value":"140471"},{"label":"潞城市","value":"140481"}],[{"label":"城区","value":"140502"},{"label":"沁水县","value":"140521"},{"label":"阳城县","value":"140522"},{"label":"陵川县","value":"140524"},{"label":"泽州县","value":"140525"},{"label":"高平市","value":"140581"}],[{"label":"朔城区","value":"140602"},{"label":"平鲁区","value":"140603"},{"label":"山阴县","value":"140621"},{"label":"应县","value":"140622"},{"label":"右玉县","value":"140623"},{"label":"怀仁县","value":"140624"},{"label":"山西朔州经济开发区","value":"140671"}],[{"label":"榆次区","value":"140702"},{"label":"榆社县","value":"140721"},{"label":"左权县","value":"140722"},{"label":"和顺县","value":"140723"},{"label":"昔阳县","value":"140724"},{"label":"寿阳县","value":"140725"},{"label":"太谷县","value":"140726"},{"label":"祁县","value":"140727"},{"label":"平遥县","value":"140728"},{"label":"灵石县","value":"140729"},{"label":"介休市","value":"140781"}],[{"label":"盐湖区","value":"140802"},{"label":"临猗县","value":"140821"},{"label":"万荣县","value":"140822"},{"label":"闻喜县","value":"140823"},{"label":"稷山县","value":"140824"},{"label":"新绛县","value":"140825"},{"label":"绛县","value":"140826"},{"label":"垣曲县","value":"140827"},{"label":"夏县","value":"140828"},{"label":"平陆县","value":"140829"},{"label":"芮城县","value":"140830"},{"label":"永济市","value":"140881"},{"label":"河津市","value":"140882"}],[{"label":"忻府区","value":"140902"},{"label":"定襄县","value":"140921"},{"label":"五台县","value":"140922"},{"label":"代县","value":"140923"},{"label":"繁峙县","value":"140924"},{"label":"宁武县","value":"140925"},{"label":"静乐县","value":"140926"},{"label":"神池县","value":"140927"},{"label":"五寨县","value":"140928"},{"label":"岢岚县","value":"140929"},{"label":"河曲县","value":"140930"},{"label":"保德县","value":"140931"},{"label":"偏关县","value":"140932"},{"label":"五台山风景名胜区","value":"140971"},{"label":"原平市","value":"140981"}],[{"label":"尧都区","value":"141002"},{"label":"曲沃县","value":"141021"},{"label":"翼城县","value":"141022"},{"label":"襄汾县","value":"141023"},{"label":"洪洞县","value":"141024"},{"label":"古县","value":"141025"},{"label":"安泽县","value":"141026"},{"label":"浮山县","value":"141027"},{"label":"吉县","value":"141028"},{"label":"乡宁县","value":"141029"},{"label":"大宁县","value":"141030"},{"label":"隰县","value":"141031"},{"label":"永和县","value":"141032"},{"label":"蒲县","value":"141033"},{"label":"汾西县","value":"141034"},{"label":"侯马市","value":"141081"},{"label":"霍州市","value":"141082"}],[{"label":"离石区","value":"141102"},{"label":"文水县","value":"141121"},{"label":"交城县","value":"141122"},{"label":"兴县","value":"141123"},{"label":"临县","value":"141124"},{"label":"柳林县","value":"141125"},{"label":"石楼县","value":"141126"},{"label":"岚县","value":"141127"},{"label":"方山县","value":"141128"},{"label":"中阳县","value":"141129"},{"label":"交口县","value":"141130"},{"label":"孝义市","value":"141181"},{"label":"汾阳市","value":"141182"}]],[[{"label":"新城区","value":"150102"},{"label":"回民区","value":"150103"},{"label":"玉泉区","value":"150104"},{"label":"赛罕区","value":"150105"},{"label":"土默特左旗","value":"150121"},{"label":"托克托县","value":"150122"},{"label":"和林格尔县","value":"150123"},{"label":"清水河县","value":"150124"},{"label":"武川县","value":"150125"},{"label":"呼和浩特金海工业园区","value":"150171"},{"label":"呼和浩特经济技术开发区","value":"150172"}],[{"label":"东河区","value":"150202"},{"label":"昆都仑区","value":"150203"},{"label":"青山区","value":"150204"},{"label":"石拐区","value":"150205"},{"label":"白云鄂博矿区","value":"150206"},{"label":"九原区","value":"150207"},{"label":"土默特右旗","value":"150221"},{"label":"固阳县","value":"150222"},{"label":"达尔罕茂明安联合旗","value":"150223"},{"label":"包头稀土高新技术产业开发区","value":"150271"}],[{"label":"海勃湾区","value":"150302"},{"label":"海南区","value":"150303"},{"label":"乌达区","value":"150304"}],[{"label":"红山区","value":"150402"},{"label":"元宝山区","value":"150403"},{"label":"松山区","value":"150404"},{"label":"阿鲁科尔沁旗","value":"150421"},{"label":"巴林左旗","value":"150422"},{"label":"巴林右旗","value":"150423"},{"label":"林西县","value":"150424"},{"label":"克什克腾旗","value":"150425"},{"label":"翁牛特旗","value":"150426"},{"label":"喀喇沁旗","value":"150428"},{"label":"宁城县","value":"150429"},{"label":"敖汉旗","value":"150430"}],[{"label":"科尔沁区","value":"150502"},{"label":"科尔沁左翼中旗","value":"150521"},{"label":"科尔沁左翼后旗","value":"150522"},{"label":"开鲁县","value":"150523"},{"label":"库伦旗","value":"150524"},{"label":"奈曼旗","value":"150525"},{"label":"扎鲁特旗","value":"150526"},{"label":"通辽经济技术开发区","value":"150571"},{"label":"霍林郭勒市","value":"150581"}],[{"label":"东胜区","value":"150602"},{"label":"康巴什区","value":"150603"},{"label":"达拉特旗","value":"150621"},{"label":"准格尔旗","value":"150622"},{"label":"鄂托克前旗","value":"150623"},{"label":"鄂托克旗","value":"150624"},{"label":"杭锦旗","value":"150625"},{"label":"乌审旗","value":"150626"},{"label":"伊金霍洛旗","value":"150627"}],[{"label":"海拉尔区","value":"150702"},{"label":"扎赉诺尔区","value":"150703"},{"label":"阿荣旗","value":"150721"},{"label":"莫力达瓦达斡尔族自治旗","value":"150722"},{"label":"鄂伦春自治旗","value":"150723"},{"label":"鄂温克族自治旗","value":"150724"},{"label":"陈巴尔虎旗","value":"150725"},{"label":"新巴尔虎左旗","value":"150726"},{"label":"新巴尔虎右旗","value":"150727"},{"label":"满洲里市","value":"150781"},{"label":"牙克石市","value":"150782"},{"label":"扎兰屯市","value":"150783"},{"label":"额尔古纳市","value":"150784"},{"label":"根河市","value":"150785"}],[{"label":"临河区","value":"150802"},{"label":"五原县","value":"150821"},{"label":"磴口县","value":"150822"},{"label":"乌拉特前旗","value":"150823"},{"label":"乌拉特中旗","value":"150824"},{"label":"乌拉特后旗","value":"150825"},{"label":"杭锦后旗","value":"150826"}],[{"label":"集宁区","value":"150902"},{"label":"卓资县","value":"150921"},{"label":"化德县","value":"150922"},{"label":"商都县","value":"150923"},{"label":"兴和县","value":"150924"},{"label":"凉城县","value":"150925"},{"label":"察哈尔右翼前旗","value":"150926"},{"label":"察哈尔右翼中旗","value":"150927"},{"label":"察哈尔右翼后旗","value":"150928"},{"label":"四子王旗","value":"150929"},{"label":"丰镇市","value":"150981"}],[{"label":"乌兰浩特市","value":"152201"},{"label":"阿尔山市","value":"152202"},{"label":"科尔沁右翼前旗","value":"152221"},{"label":"科尔沁右翼中旗","value":"152222"},{"label":"扎赉特旗","value":"152223"},{"label":"突泉县","value":"152224"}],[{"label":"二连浩特市","value":"152501"},{"label":"锡林浩特市","value":"152502"},{"label":"阿巴嘎旗","value":"152522"},{"label":"苏尼特左旗","value":"152523"},{"label":"苏尼特右旗","value":"152524"},{"label":"东乌珠穆沁旗","value":"152525"},{"label":"西乌珠穆沁旗","value":"152526"},{"label":"太仆寺旗","value":"152527"},{"label":"镶黄旗","value":"152528"},{"label":"正镶白旗","value":"152529"},{"label":"正蓝旗","value":"152530"},{"label":"多伦县","value":"152531"},{"label":"乌拉盖管委会","value":"152571"}],[{"label":"阿拉善左旗","value":"152921"},{"label":"阿拉善右旗","value":"152922"},{"label":"额济纳旗","value":"152923"},{"label":"内蒙古阿拉善经济开发区","value":"152971"}]],[[{"label":"和平区","value":"210102"},{"label":"沈河区","value":"210103"},{"label":"大东区","value":"210104"},{"label":"皇姑区","value":"210105"},{"label":"铁西区","value":"210106"},{"label":"苏家屯区","value":"210111"},{"label":"浑南区","value":"210112"},{"label":"沈北新区","value":"210113"},{"label":"于洪区","value":"210114"},{"label":"辽中区","value":"210115"},{"label":"康平县","value":"210123"},{"label":"法库县","value":"210124"},{"label":"新民市","value":"210181"}],[{"label":"中山区","value":"210202"},{"label":"西岗区","value":"210203"},{"label":"沙河口区","value":"210204"},{"label":"甘井子区","value":"210211"},{"label":"旅顺口区","value":"210212"},{"label":"金州区","value":"210213"},{"label":"普兰店区","value":"210214"},{"label":"长海县","value":"210224"},{"label":"瓦房店市","value":"210281"},{"label":"庄河市","value":"210283"}],[{"label":"铁东区","value":"210302"},{"label":"铁西区","value":"210303"},{"label":"立山区","value":"210304"},{"label":"千山区","value":"210311"},{"label":"台安县","value":"210321"},{"label":"岫岩满族自治县","value":"210323"},{"label":"海城市","value":"210381"}],[{"label":"新抚区","value":"210402"},{"label":"东洲区","value":"210403"},{"label":"望花区","value":"210404"},{"label":"顺城区","value":"210411"},{"label":"抚顺县","value":"210421"},{"label":"新宾满族自治县","value":"210422"},{"label":"清原满族自治县","value":"210423"}],[{"label":"平山区","value":"210502"},{"label":"溪湖区","value":"210503"},{"label":"明山区","value":"210504"},{"label":"南芬区","value":"210505"},{"label":"本溪满族自治县","value":"210521"},{"label":"桓仁满族自治县","value":"210522"}],[{"label":"元宝区","value":"210602"},{"label":"振兴区","value":"210603"},{"label":"振安区","value":"210604"},{"label":"宽甸满族自治县","value":"210624"},{"label":"东港市","value":"210681"},{"label":"凤城市","value":"210682"}],[{"label":"古塔区","value":"210702"},{"label":"凌河区","value":"210703"},{"label":"太和区","value":"210711"},{"label":"黑山县","value":"210726"},{"label":"义县","value":"210727"},{"label":"凌海市","value":"210781"},{"label":"北镇市","value":"210782"}],[{"label":"站前区","value":"210802"},{"label":"西市区","value":"210803"},{"label":"鲅鱼圈区","value":"210804"},{"label":"老边区","value":"210811"},{"label":"盖州市","value":"210881"},{"label":"大石桥市","value":"210882"}],[{"label":"海州区","value":"210902"},{"label":"新邱区","value":"210903"},{"label":"太平区","value":"210904"},{"label":"清河门区","value":"210905"},{"label":"细河区","value":"210911"},{"label":"阜新蒙古族自治县","value":"210921"},{"label":"彰武县","value":"210922"}],[{"label":"白塔区","value":"211002"},{"label":"文圣区","value":"211003"},{"label":"宏伟区","value":"211004"},{"label":"弓长岭区","value":"211005"},{"label":"太子河区","value":"211011"},{"label":"辽阳县","value":"211021"},{"label":"灯塔市","value":"211081"}],[{"label":"双台子区","value":"211102"},{"label":"兴隆台区","value":"211103"},{"label":"大洼区","value":"211104"},{"label":"盘山县","value":"211122"}],[{"label":"银州区","value":"211202"},{"label":"清河区","value":"211204"},{"label":"铁岭县","value":"211221"},{"label":"西丰县","value":"211223"},{"label":"昌图县","value":"211224"},{"label":"调兵山市","value":"211281"},{"label":"开原市","value":"211282"}],[{"label":"双塔区","value":"211302"},{"label":"龙城区","value":"211303"},{"label":"朝阳县","value":"211321"},{"label":"建平县","value":"211322"},{"label":"喀喇沁左翼蒙古族自治县","value":"211324"},{"label":"北票市","value":"211381"},{"label":"凌源市","value":"211382"}],[{"label":"连山区","value":"211402"},{"label":"龙港区","value":"211403"},{"label":"南票区","value":"211404"},{"label":"绥中县","value":"211421"},{"label":"建昌县","value":"211422"},{"label":"兴城市","value":"211481"}]],[[{"label":"南关区","value":"220102"},{"label":"宽城区","value":"220103"},{"label":"朝阳区","value":"220104"},{"label":"二道区","value":"220105"},{"label":"绿园区","value":"220106"},{"label":"双阳区","value":"220112"},{"label":"九台区","value":"220113"},{"label":"农安县","value":"220122"},{"label":"长春经济技术开发区","value":"220171"},{"label":"长春净月高新技术产业开发区","value":"220172"},{"label":"长春高新技术产业开发区","value":"220173"},{"label":"长春汽车经济技术开发区","value":"220174"},{"label":"榆树市","value":"220182"},{"label":"德惠市","value":"220183"}],[{"label":"昌邑区","value":"220202"},{"label":"龙潭区","value":"220203"},{"label":"船营区","value":"220204"},{"label":"丰满区","value":"220211"},{"label":"永吉县","value":"220221"},{"label":"吉林经济开发区","value":"220271"},{"label":"吉林高新技术产业开发区","value":"220272"},{"label":"吉林中国新加坡食品区","value":"220273"},{"label":"蛟河市","value":"220281"},{"label":"桦甸市","value":"220282"},{"label":"舒兰市","value":"220283"},{"label":"磐石市","value":"220284"}],[{"label":"铁西区","value":"220302"},{"label":"铁东区","value":"220303"},{"label":"梨树县","value":"220322"},{"label":"伊通满族自治县","value":"220323"},{"label":"公主岭市","value":"220381"},{"label":"双辽市","value":"220382"}],[{"label":"龙山区","value":"220402"},{"label":"西安区","value":"220403"},{"label":"东丰县","value":"220421"},{"label":"东辽县","value":"220422"}],[{"label":"东昌区","value":"220502"},{"label":"二道江区","value":"220503"},{"label":"通化县","value":"220521"},{"label":"辉南县","value":"220523"},{"label":"柳河县","value":"220524"},{"label":"梅河口市","value":"220581"},{"label":"集安市","value":"220582"}],[{"label":"浑江区","value":"220602"},{"label":"江源区","value":"220605"},{"label":"抚松县","value":"220621"},{"label":"靖宇县","value":"220622"},{"label":"长白朝鲜族自治县","value":"220623"},{"label":"临江市","value":"220681"}],[{"label":"宁江区","value":"220702"},{"label":"前郭尔罗斯蒙古族自治县","value":"220721"},{"label":"长岭县","value":"220722"},{"label":"乾安县","value":"220723"},{"label":"吉林松原经济开发区","value":"220771"},{"label":"扶余市","value":"220781"}],[{"label":"洮北区","value":"220802"},{"label":"镇赉县","value":"220821"},{"label":"通榆县","value":"220822"},{"label":"吉林白城经济开发区","value":"220871"},{"label":"洮南市","value":"220881"},{"label":"大安市","value":"220882"}],[{"label":"延吉市","value":"222401"},{"label":"图们市","value":"222402"},{"label":"敦化市","value":"222403"},{"label":"珲春市","value":"222404"},{"label":"龙井市","value":"222405"},{"label":"和龙市","value":"222406"},{"label":"汪清县","value":"222424"},{"label":"安图县","value":"222426"}]],[[{"label":"道里区","value":"230102"},{"label":"南岗区","value":"230103"},{"label":"道外区","value":"230104"},{"label":"平房区","value":"230108"},{"label":"松北区","value":"230109"},{"label":"香坊区","value":"230110"},{"label":"呼兰区","value":"230111"},{"label":"阿城区","value":"230112"},{"label":"双城区","value":"230113"},{"label":"依兰县","value":"230123"},{"label":"方正县","value":"230124"},{"label":"宾县","value":"230125"},{"label":"巴彦县","value":"230126"},{"label":"木兰县","value":"230127"},{"label":"通河县","value":"230128"},{"label":"延寿县","value":"230129"},{"label":"尚志市","value":"230183"},{"label":"五常市","value":"230184"}],[{"label":"龙沙区","value":"230202"},{"label":"建华区","value":"230203"},{"label":"铁锋区","value":"230204"},{"label":"昂昂溪区","value":"230205"},{"label":"富拉尔基区","value":"230206"},{"label":"碾子山区","value":"230207"},{"label":"梅里斯达斡尔族区","value":"230208"},{"label":"龙江县","value":"230221"},{"label":"依安县","value":"230223"},{"label":"泰来县","value":"230224"},{"label":"甘南县","value":"230225"},{"label":"富裕县","value":"230227"},{"label":"克山县","value":"230229"},{"label":"克东县","value":"230230"},{"label":"拜泉县","value":"230231"},{"label":"讷河市","value":"230281"}],[{"label":"鸡冠区","value":"230302"},{"label":"恒山区","value":"230303"},{"label":"滴道区","value":"230304"},{"label":"梨树区","value":"230305"},{"label":"城子河区","value":"230306"},{"label":"麻山区","value":"230307"},{"label":"鸡东县","value":"230321"},{"label":"虎林市","value":"230381"},{"label":"密山市","value":"230382"}],[{"label":"向阳区","value":"230402"},{"label":"工农区","value":"230403"},{"label":"南山区","value":"230404"},{"label":"兴安区","value":"230405"},{"label":"东山区","value":"230406"},{"label":"兴山区","value":"230407"},{"label":"萝北县","value":"230421"},{"label":"绥滨县","value":"230422"}],[{"label":"尖山区","value":"230502"},{"label":"岭东区","value":"230503"},{"label":"四方台区","value":"230505"},{"label":"宝山区","value":"230506"},{"label":"集贤县","value":"230521"},{"label":"友谊县","value":"230522"},{"label":"宝清县","value":"230523"},{"label":"饶河县","value":"230524"}],[{"label":"萨尔图区","value":"230602"},{"label":"龙凤区","value":"230603"},{"label":"让胡路区","value":"230604"},{"label":"红岗区","value":"230605"},{"label":"大同区","value":"230606"},{"label":"肇州县","value":"230621"},{"label":"肇源县","value":"230622"},{"label":"林甸县","value":"230623"},{"label":"杜尔伯特蒙古族自治县","value":"230624"},{"label":"大庆高新技术产业开发区","value":"230671"}],[{"label":"伊春区","value":"230702"},{"label":"南岔区","value":"230703"},{"label":"友好区","value":"230704"},{"label":"西林区","value":"230705"},{"label":"翠峦区","value":"230706"},{"label":"新青区","value":"230707"},{"label":"美溪区","value":"230708"},{"label":"金山屯区","value":"230709"},{"label":"五营区","value":"230710"},{"label":"乌马河区","value":"230711"},{"label":"汤旺河区","value":"230712"},{"label":"带岭区","value":"230713"},{"label":"乌伊岭区","value":"230714"},{"label":"红星区","value":"230715"},{"label":"上甘岭区","value":"230716"},{"label":"嘉荫县","value":"230722"},{"label":"铁力市","value":"230781"}],[{"label":"向阳区","value":"230803"},{"label":"前进区","value":"230804"},{"label":"东风区","value":"230805"},{"label":"郊区","value":"230811"},{"label":"桦南县","value":"230822"},{"label":"桦川县","value":"230826"},{"label":"汤原县","value":"230828"},{"label":"同江市","value":"230881"},{"label":"富锦市","value":"230882"},{"label":"抚远市","value":"230883"}],[{"label":"新兴区","value":"230902"},{"label":"桃山区","value":"230903"},{"label":"茄子河区","value":"230904"},{"label":"勃利县","value":"230921"}],[{"label":"东安区","value":"231002"},{"label":"阳明区","value":"231003"},{"label":"爱民区","value":"231004"},{"label":"西安区","value":"231005"},{"label":"林口县","value":"231025"},{"label":"牡丹江经济技术开发区","value":"231071"},{"label":"绥芬河市","value":"231081"},{"label":"海林市","value":"231083"},{"label":"宁安市","value":"231084"},{"label":"穆棱市","value":"231085"},{"label":"东宁市","value":"231086"}],[{"label":"爱辉区","value":"231102"},{"label":"嫩江县","value":"231121"},{"label":"逊克县","value":"231123"},{"label":"孙吴县","value":"231124"},{"label":"北安市","value":"231181"},{"label":"五大连池市","value":"231182"}],[{"label":"北林区","value":"231202"},{"label":"望奎县","value":"231221"},{"label":"兰西县","value":"231222"},{"label":"青冈县","value":"231223"},{"label":"庆安县","value":"231224"},{"label":"明水县","value":"231225"},{"label":"绥棱县","value":"231226"},{"label":"安达市","value":"231281"},{"label":"肇东市","value":"231282"},{"label":"海伦市","value":"231283"}],[{"label":"加格达奇区","value":"232701"},{"label":"松岭区","value":"232702"},{"label":"新林区","value":"232703"},{"label":"呼中区","value":"232704"},{"label":"呼玛县","value":"232721"},{"label":"塔河县","value":"232722"},{"label":"漠河县","value":"232723"}]],[[{"label":"黄浦区","value":"310101"},{"label":"徐汇区","value":"310104"},{"label":"长宁区","value":"310105"},{"label":"静安区","value":"310106"},{"label":"普陀区","value":"310107"},{"label":"虹口区","value":"310109"},{"label":"杨浦区","value":"310110"},{"label":"闵行区","value":"310112"},{"label":"宝山区","value":"310113"},{"label":"嘉定区","value":"310114"},{"label":"浦东新区","value":"310115"},{"label":"金山区","value":"310116"},{"label":"松江区","value":"310117"},{"label":"青浦区","value":"310118"},{"label":"奉贤区","value":"310120"},{"label":"崇明区","value":"310151"}]],[[{"label":"玄武区","value":"320102"},{"label":"秦淮区","value":"320104"},{"label":"建邺区","value":"320105"},{"label":"鼓楼区","value":"320106"},{"label":"浦口区","value":"320111"},{"label":"栖霞区","value":"320113"},{"label":"雨花台区","value":"320114"},{"label":"江宁区","value":"320115"},{"label":"六合区","value":"320116"},{"label":"溧水区","value":"320117"},{"label":"高淳区","value":"320118"}],[{"label":"锡山区","value":"320205"},{"label":"惠山区","value":"320206"},{"label":"滨湖区","value":"320211"},{"label":"梁溪区","value":"320213"},{"label":"新吴区","value":"320214"},{"label":"江阴市","value":"320281"},{"label":"宜兴市","value":"320282"}],[{"label":"鼓楼区","value":"320302"},{"label":"云龙区","value":"320303"},{"label":"贾汪区","value":"320305"},{"label":"泉山区","value":"320311"},{"label":"铜山区","value":"320312"},{"label":"丰县","value":"320321"},{"label":"沛县","value":"320322"},{"label":"睢宁县","value":"320324"},{"label":"徐州经济技术开发区","value":"320371"},{"label":"新沂市","value":"320381"},{"label":"邳州市","value":"320382"}],[{"label":"天宁区","value":"320402"},{"label":"钟楼区","value":"320404"},{"label":"新北区","value":"320411"},{"label":"武进区","value":"320412"},{"label":"金坛区","value":"320413"},{"label":"溧阳市","value":"320481"}],[{"label":"虎丘区","value":"320505"},{"label":"吴中区","value":"320506"},{"label":"相城区","value":"320507"},{"label":"姑苏区","value":"320508"},{"label":"吴江区","value":"320509"},{"label":"苏州工业园区","value":"320571"},{"label":"常熟市","value":"320581"},{"label":"张家港市","value":"320582"},{"label":"昆山市","value":"320583"},{"label":"太仓市","value":"320585"}],[{"label":"崇川区","value":"320602"},{"label":"港闸区","value":"320611"},{"label":"通州区","value":"320612"},{"label":"海安县","value":"320621"},{"label":"如东县","value":"320623"},{"label":"南通经济技术开发区","value":"320671"},{"label":"启东市","value":"320681"},{"label":"如皋市","value":"320682"},{"label":"海门市","value":"320684"}],[{"label":"连云区","value":"320703"},{"label":"海州区","value":"320706"},{"label":"赣榆区","value":"320707"},{"label":"东海县","value":"320722"},{"label":"灌云县","value":"320723"},{"label":"灌南县","value":"320724"},{"label":"连云港经济技术开发区","value":"320771"},{"label":"连云港高新技术产业开发区","value":"320772"}],[{"label":"淮安区","value":"320803"},{"label":"淮阴区","value":"320804"},{"label":"清江浦区","value":"320812"},{"label":"洪泽区","value":"320813"},{"label":"涟水县","value":"320826"},{"label":"盱眙县","value":"320830"},{"label":"金湖县","value":"320831"},{"label":"淮安经济技术开发区","value":"320871"}],[{"label":"亭湖区","value":"320902"},{"label":"盐都区","value":"320903"},{"label":"大丰区","value":"320904"},{"label":"响水县","value":"320921"},{"label":"滨海县","value":"320922"},{"label":"阜宁县","value":"320923"},{"label":"射阳县","value":"320924"},{"label":"建湖县","value":"320925"},{"label":"盐城经济技术开发区","value":"320971"},{"label":"东台市","value":"320981"}],[{"label":"广陵区","value":"321002"},{"label":"邗江区","value":"321003"},{"label":"江都区","value":"321012"},{"label":"宝应县","value":"321023"},{"label":"扬州经济技术开发区","value":"321071"},{"label":"仪征市","value":"321081"},{"label":"高邮市","value":"321084"}],[{"label":"京口区","value":"321102"},{"label":"润州区","value":"321111"},{"label":"丹徒区","value":"321112"},{"label":"镇江新区","value":"321171"},{"label":"丹阳市","value":"321181"},{"label":"扬中市","value":"321182"},{"label":"句容市","value":"321183"}],[{"label":"海陵区","value":"321202"},{"label":"高港区","value":"321203"},{"label":"姜堰区","value":"321204"},{"label":"泰州医药高新技术产业开发区","value":"321271"},{"label":"兴化市","value":"321281"},{"label":"靖江市","value":"321282"},{"label":"泰兴市","value":"321283"}],[{"label":"宿城区","value":"321302"},{"label":"宿豫区","value":"321311"},{"label":"沭阳县","value":"321322"},{"label":"泗阳县","value":"321323"},{"label":"泗洪县","value":"321324"},{"label":"宿迁经济技术开发区","value":"321371"}]],[[{"label":"上城区","value":"330102"},{"label":"下城区","value":"330103"},{"label":"江干区","value":"330104"},{"label":"拱墅区","value":"330105"},{"label":"西湖区","value":"330106"},{"label":"滨江区","value":"330108"},{"label":"萧山区","value":"330109"},{"label":"余杭区","value":"330110"},{"label":"富阳区","value":"330111"},{"label":"临安区","value":"330112"},{"label":"桐庐县","value":"330122"},{"label":"淳安县","value":"330127"},{"label":"建德市","value":"330182"}],[{"label":"海曙区","value":"330203"},{"label":"江北区","value":"330205"},{"label":"北仑区","value":"330206"},{"label":"镇海区","value":"330211"},{"label":"鄞州区","value":"330212"},{"label":"奉化区","value":"330213"},{"label":"象山县","value":"330225"},{"label":"宁海县","value":"330226"},{"label":"余姚市","value":"330281"},{"label":"慈溪市","value":"330282"}],[{"label":"鹿城区","value":"330302"},{"label":"龙湾区","value":"330303"},{"label":"瓯海区","value":"330304"},{"label":"洞头区","value":"330305"},{"label":"永嘉县","value":"330324"},{"label":"平阳县","value":"330326"},{"label":"苍南县","value":"330327"},{"label":"文成县","value":"330328"},{"label":"泰顺县","value":"330329"},{"label":"温州经济技术开发区","value":"330371"},{"label":"瑞安市","value":"330381"},{"label":"乐清市","value":"330382"}],[{"label":"南湖区","value":"330402"},{"label":"秀洲区","value":"330411"},{"label":"嘉善县","value":"330421"},{"label":"海盐县","value":"330424"},{"label":"海宁市","value":"330481"},{"label":"平湖市","value":"330482"},{"label":"桐乡市","value":"330483"}],[{"label":"吴兴区","value":"330502"},{"label":"南浔区","value":"330503"},{"label":"德清县","value":"330521"},{"label":"长兴县","value":"330522"},{"label":"安吉县","value":"330523"}],[{"label":"越城区","value":"330602"},{"label":"柯桥区","value":"330603"},{"label":"上虞区","value":"330604"},{"label":"新昌县","value":"330624"},{"label":"诸暨市","value":"330681"},{"label":"嵊州市","value":"330683"}],[{"label":"婺城区","value":"330702"},{"label":"金东区","value":"330703"},{"label":"武义县","value":"330723"},{"label":"浦江县","value":"330726"},{"label":"磐安县","value":"330727"},{"label":"兰溪市","value":"330781"},{"label":"义乌市","value":"330782"},{"label":"东阳市","value":"330783"},{"label":"永康市","value":"330784"}],[{"label":"柯城区","value":"330802"},{"label":"衢江区","value":"330803"},{"label":"常山县","value":"330822"},{"label":"开化县","value":"330824"},{"label":"龙游县","value":"330825"},{"label":"江山市","value":"330881"}],[{"label":"定海区","value":"330902"},{"label":"普陀区","value":"330903"},{"label":"岱山县","value":"330921"},{"label":"嵊泗县","value":"330922"}],[{"label":"椒江区","value":"331002"},{"label":"黄岩区","value":"331003"},{"label":"路桥区","value":"331004"},{"label":"三门县","value":"331022"},{"label":"天台县","value":"331023"},{"label":"仙居县","value":"331024"},{"label":"温岭市","value":"331081"},{"label":"临海市","value":"331082"},{"label":"玉环市","value":"331083"}],[{"label":"莲都区","value":"331102"},{"label":"青田县","value":"331121"},{"label":"缙云县","value":"331122"},{"label":"遂昌县","value":"331123"},{"label":"松阳县","value":"331124"},{"label":"云和县","value":"331125"},{"label":"庆元县","value":"331126"},{"label":"景宁畲族自治县","value":"331127"},{"label":"龙泉市","value":"331181"}]],[[{"label":"瑶海区","value":"340102"},{"label":"庐阳区","value":"340103"},{"label":"蜀山区","value":"340104"},{"label":"包河区","value":"340111"},{"label":"长丰县","value":"340121"},{"label":"肥东县","value":"340122"},{"label":"肥西县","value":"340123"},{"label":"庐江县","value":"340124"},{"label":"合肥高新技术产业开发区","value":"340171"},{"label":"合肥经济技术开发区","value":"340172"},{"label":"合肥新站高新技术产业开发区","value":"340173"},{"label":"巢湖市","value":"340181"}],[{"label":"镜湖区","value":"340202"},{"label":"弋江区","value":"340203"},{"label":"鸠江区","value":"340207"},{"label":"三山区","value":"340208"},{"label":"芜湖县","value":"340221"},{"label":"繁昌县","value":"340222"},{"label":"南陵县","value":"340223"},{"label":"无为县","value":"340225"},{"label":"芜湖经济技术开发区","value":"340271"},{"label":"安徽芜湖长江大桥经济开发区","value":"340272"}],[{"label":"龙子湖区","value":"340302"},{"label":"蚌山区","value":"340303"},{"label":"禹会区","value":"340304"},{"label":"淮上区","value":"340311"},{"label":"怀远县","value":"340321"},{"label":"五河县","value":"340322"},{"label":"固镇县","value":"340323"},{"label":"蚌埠市高新技术开发区","value":"340371"},{"label":"蚌埠市经济开发区","value":"340372"}],[{"label":"大通区","value":"340402"},{"label":"田家庵区","value":"340403"},{"label":"谢家集区","value":"340404"},{"label":"八公山区","value":"340405"},{"label":"潘集区","value":"340406"},{"label":"凤台县","value":"340421"},{"label":"寿县","value":"340422"}],[{"label":"花山区","value":"340503"},{"label":"雨山区","value":"340504"},{"label":"博望区","value":"340506"},{"label":"当涂县","value":"340521"},{"label":"含山县","value":"340522"},{"label":"和县","value":"340523"}],[{"label":"杜集区","value":"340602"},{"label":"相山区","value":"340603"},{"label":"烈山区","value":"340604"},{"label":"濉溪县","value":"340621"}],[{"label":"铜官区","value":"340705"},{"label":"义安区","value":"340706"},{"label":"郊区","value":"340711"},{"label":"枞阳县","value":"340722"}],[{"label":"迎江区","value":"340802"},{"label":"大观区","value":"340803"},{"label":"宜秀区","value":"340811"},{"label":"怀宁县","value":"340822"},{"label":"潜山县","value":"340824"},{"label":"太湖县","value":"340825"},{"label":"宿松县","value":"340826"},{"label":"望江县","value":"340827"},{"label":"岳西县","value":"340828"},{"label":"安徽安庆经济开发区","value":"340871"},{"label":"桐城市","value":"340881"}],[{"label":"屯溪区","value":"341002"},{"label":"黄山区","value":"341003"},{"label":"徽州区","value":"341004"},{"label":"歙县","value":"341021"},{"label":"休宁县","value":"341022"},{"label":"黟县","value":"341023"},{"label":"祁门县","value":"341024"}],[{"label":"琅琊区","value":"341102"},{"label":"南谯区","value":"341103"},{"label":"来安县","value":"341122"},{"label":"全椒县","value":"341124"},{"label":"定远县","value":"341125"},{"label":"凤阳县","value":"341126"},{"label":"苏滁现代产业园","value":"341171"},{"label":"滁州经济技术开发区","value":"341172"},{"label":"天长市","value":"341181"},{"label":"明光市","value":"341182"}],[{"label":"颍州区","value":"341202"},{"label":"颍东区","value":"341203"},{"label":"颍泉区","value":"341204"},{"label":"临泉县","value":"341221"},{"label":"太和县","value":"341222"},{"label":"阜南县","value":"341225"},{"label":"颍上县","value":"341226"},{"label":"阜阳合肥现代产业园区","value":"341271"},{"label":"阜阳经济技术开发区","value":"341272"},{"label":"界首市","value":"341282"}],[{"label":"埇桥区","value":"341302"},{"label":"砀山县","value":"341321"},{"label":"萧县","value":"341322"},{"label":"灵璧县","value":"341323"},{"label":"泗县","value":"341324"},{"label":"宿州马鞍山现代产业园区","value":"341371"},{"label":"宿州经济技术开发区","value":"341372"}],[{"label":"金安区","value":"341502"},{"label":"裕安区","value":"341503"},{"label":"叶集区","value":"341504"},{"label":"霍邱县","value":"341522"},{"label":"舒城县","value":"341523"},{"label":"金寨县","value":"341524"},{"label":"霍山县","value":"341525"}],[{"label":"谯城区","value":"341602"},{"label":"涡阳县","value":"341621"},{"label":"蒙城县","value":"341622"},{"label":"利辛县","value":"341623"}],[{"label":"贵池区","value":"341702"},{"label":"东至县","value":"341721"},{"label":"石台县","value":"341722"},{"label":"青阳县","value":"341723"}],[{"label":"宣州区","value":"341802"},{"label":"郎溪县","value":"341821"},{"label":"广德县","value":"341822"},{"label":"泾县","value":"341823"},{"label":"绩溪县","value":"341824"},{"label":"旌德县","value":"341825"},{"label":"宣城市经济开发区","value":"341871"},{"label":"宁国市","value":"341881"}]],[[{"label":"鼓楼区","value":"350102"},{"label":"台江区","value":"350103"},{"label":"仓山区","value":"350104"},{"label":"马尾区","value":"350105"},{"label":"晋安区","value":"350111"},{"label":"闽侯县","value":"350121"},{"label":"连江县","value":"350122"},{"label":"罗源县","value":"350123"},{"label":"闽清县","value":"350124"},{"label":"永泰县","value":"350125"},{"label":"平潭县","value":"350128"},{"label":"福清市","value":"350181"},{"label":"长乐市","value":"350182"}],[{"label":"思明区","value":"350203"},{"label":"海沧区","value":"350205"},{"label":"湖里区","value":"350206"},{"label":"集美区","value":"350211"},{"label":"同安区","value":"350212"},{"label":"翔安区","value":"350213"}],[{"label":"城厢区","value":"350302"},{"label":"涵江区","value":"350303"},{"label":"荔城区","value":"350304"},{"label":"秀屿区","value":"350305"},{"label":"仙游县","value":"350322"}],[{"label":"梅列区","value":"350402"},{"label":"三元区","value":"350403"},{"label":"明溪县","value":"350421"},{"label":"清流县","value":"350423"},{"label":"宁化县","value":"350424"},{"label":"大田县","value":"350425"},{"label":"尤溪县","value":"350426"},{"label":"沙县","value":"350427"},{"label":"将乐县","value":"350428"},{"label":"泰宁县","value":"350429"},{"label":"建宁县","value":"350430"},{"label":"永安市","value":"350481"}],[{"label":"鲤城区","value":"350502"},{"label":"丰泽区","value":"350503"},{"label":"洛江区","value":"350504"},{"label":"泉港区","value":"350505"},{"label":"惠安县","value":"350521"},{"label":"安溪县","value":"350524"},{"label":"永春县","value":"350525"},{"label":"德化县","value":"350526"},{"label":"金门县","value":"350527"},{"label":"石狮市","value":"350581"},{"label":"晋江市","value":"350582"},{"label":"南安市","value":"350583"}],[{"label":"芗城区","value":"350602"},{"label":"龙文区","value":"350603"},{"label":"云霄县","value":"350622"},{"label":"漳浦县","value":"350623"},{"label":"诏安县","value":"350624"},{"label":"长泰县","value":"350625"},{"label":"东山县","value":"350626"},{"label":"南靖县","value":"350627"},{"label":"平和县","value":"350628"},{"label":"华安县","value":"350629"},{"label":"龙海市","value":"350681"}],[{"label":"延平区","value":"350702"},{"label":"建阳区","value":"350703"},{"label":"顺昌县","value":"350721"},{"label":"浦城县","value":"350722"},{"label":"光泽县","value":"350723"},{"label":"松溪县","value":"350724"},{"label":"政和县","value":"350725"},{"label":"邵武市","value":"350781"},{"label":"武夷山市","value":"350782"},{"label":"建瓯市","value":"350783"}],[{"label":"新罗区","value":"350802"},{"label":"永定区","value":"350803"},{"label":"长汀县","value":"350821"},{"label":"上杭县","value":"350823"},{"label":"武平县","value":"350824"},{"label":"连城县","value":"350825"},{"label":"漳平市","value":"350881"}],[{"label":"蕉城区","value":"350902"},{"label":"霞浦县","value":"350921"},{"label":"古田县","value":"350922"},{"label":"屏南县","value":"350923"},{"label":"寿宁县","value":"350924"},{"label":"周宁县","value":"350925"},{"label":"柘荣县","value":"350926"},{"label":"福安市","value":"350981"},{"label":"福鼎市","value":"350982"}]],[[{"label":"东湖区","value":"360102"},{"label":"西湖区","value":"360103"},{"label":"青云谱区","value":"360104"},{"label":"湾里区","value":"360105"},{"label":"青山湖区","value":"360111"},{"label":"新建区","value":"360112"},{"label":"南昌县","value":"360121"},{"label":"安义县","value":"360123"},{"label":"进贤县","value":"360124"}],[{"label":"昌江区","value":"360202"},{"label":"珠山区","value":"360203"},{"label":"浮梁县","value":"360222"},{"label":"乐平市","value":"360281"}],[{"label":"安源区","value":"360302"},{"label":"湘东区","value":"360313"},{"label":"莲花县","value":"360321"},{"label":"上栗县","value":"360322"},{"label":"芦溪县","value":"360323"}],[{"label":"濂溪区","value":"360402"},{"label":"浔阳区","value":"360403"},{"label":"柴桑区","value":"360404"},{"label":"武宁县","value":"360423"},{"label":"修水县","value":"360424"},{"label":"永修县","value":"360425"},{"label":"德安县","value":"360426"},{"label":"都昌县","value":"360428"},{"label":"湖口县","value":"360429"},{"label":"彭泽县","value":"360430"},{"label":"瑞昌市","value":"360481"},{"label":"共青城市","value":"360482"},{"label":"庐山市","value":"360483"}],[{"label":"渝水区","value":"360502"},{"label":"分宜县","value":"360521"}],[{"label":"月湖区","value":"360602"},{"label":"余江县","value":"360622"},{"label":"贵溪市","value":"360681"}],[{"label":"章贡区","value":"360702"},{"label":"南康区","value":"360703"},{"label":"赣县区","value":"360704"},{"label":"信丰县","value":"360722"},{"label":"大余县","value":"360723"},{"label":"上犹县","value":"360724"},{"label":"崇义县","value":"360725"},{"label":"安远县","value":"360726"},{"label":"龙南县","value":"360727"},{"label":"定南县","value":"360728"},{"label":"全南县","value":"360729"},{"label":"宁都县","value":"360730"},{"label":"于都县","value":"360731"},{"label":"兴国县","value":"360732"},{"label":"会昌县","value":"360733"},{"label":"寻乌县","value":"360734"},{"label":"石城县","value":"360735"},{"label":"瑞金市","value":"360781"}],[{"label":"吉州区","value":"360802"},{"label":"青原区","value":"360803"},{"label":"吉安县","value":"360821"},{"label":"吉水县","value":"360822"},{"label":"峡江县","value":"360823"},{"label":"新干县","value":"360824"},{"label":"永丰县","value":"360825"},{"label":"泰和县","value":"360826"},{"label":"遂川县","value":"360827"},{"label":"万安县","value":"360828"},{"label":"安福县","value":"360829"},{"label":"永新县","value":"360830"},{"label":"井冈山市","value":"360881"}],[{"label":"袁州区","value":"360902"},{"label":"奉新县","value":"360921"},{"label":"万载县","value":"360922"},{"label":"上高县","value":"360923"},{"label":"宜丰县","value":"360924"},{"label":"靖安县","value":"360925"},{"label":"铜鼓县","value":"360926"},{"label":"丰城市","value":"360981"},{"label":"樟树市","value":"360982"},{"label":"高安市","value":"360983"}],[{"label":"临川区","value":"361002"},{"label":"东乡区","value":"361003"},{"label":"南城县","value":"361021"},{"label":"黎川县","value":"361022"},{"label":"南丰县","value":"361023"},{"label":"崇仁县","value":"361024"},{"label":"乐安县","value":"361025"},{"label":"宜黄县","value":"361026"},{"label":"金溪县","value":"361027"},{"label":"资溪县","value":"361028"},{"label":"广昌县","value":"361030"}],[{"label":"信州区","value":"361102"},{"label":"广丰区","value":"361103"},{"label":"上饶县","value":"361121"},{"label":"玉山县","value":"361123"},{"label":"铅山县","value":"361124"},{"label":"横峰县","value":"361125"},{"label":"弋阳县","value":"361126"},{"label":"余干县","value":"361127"},{"label":"鄱阳县","value":"361128"},{"label":"万年县","value":"361129"},{"label":"婺源县","value":"361130"},{"label":"德兴市","value":"361181"}]],[[{"label":"历下区","value":"370102"},{"label":"市中区","value":"370103"},{"label":"槐荫区","value":"370104"},{"label":"天桥区","value":"370105"},{"label":"历城区","value":"370112"},{"label":"长清区","value":"370113"},{"label":"章丘区","value":"370114"},{"label":"平阴县","value":"370124"},{"label":"济阳县","value":"370125"},{"label":"商河县","value":"370126"},{"label":"济南高新技术产业开发区","value":"370171"}],[{"label":"市南区","value":"370202"},{"label":"市北区","value":"370203"},{"label":"黄岛区","value":"370211"},{"label":"崂山区","value":"370212"},{"label":"李沧区","value":"370213"},{"label":"城阳区","value":"370214"},{"label":"即墨区","value":"370215"},{"label":"青岛高新技术产业开发区","value":"370271"},{"label":"胶州市","value":"370281"},{"label":"平度市","value":"370283"},{"label":"莱西市","value":"370285"}],[{"label":"淄川区","value":"370302"},{"label":"张店区","value":"370303"},{"label":"博山区","value":"370304"},{"label":"临淄区","value":"370305"},{"label":"周村区","value":"370306"},{"label":"桓台县","value":"370321"},{"label":"高青县","value":"370322"},{"label":"沂源县","value":"370323"}],[{"label":"市中区","value":"370402"},{"label":"薛城区","value":"370403"},{"label":"峄城区","value":"370404"},{"label":"台儿庄区","value":"370405"},{"label":"山亭区","value":"370406"},{"label":"滕州市","value":"370481"}],[{"label":"东营区","value":"370502"},{"label":"河口区","value":"370503"},{"label":"垦利区","value":"370505"},{"label":"利津县","value":"370522"},{"label":"广饶县","value":"370523"},{"label":"东营经济技术开发区","value":"370571"},{"label":"东营港经济开发区","value":"370572"}],[{"label":"芝罘区","value":"370602"},{"label":"福山区","value":"370611"},{"label":"牟平区","value":"370612"},{"label":"莱山区","value":"370613"},{"label":"长岛县","value":"370634"},{"label":"烟台高新技术产业开发区","value":"370671"},{"label":"烟台经济技术开发区","value":"370672"},{"label":"龙口市","value":"370681"},{"label":"莱阳市","value":"370682"},{"label":"莱州市","value":"370683"},{"label":"蓬莱市","value":"370684"},{"label":"招远市","value":"370685"},{"label":"栖霞市","value":"370686"},{"label":"海阳市","value":"370687"}],[{"label":"潍城区","value":"370702"},{"label":"寒亭区","value":"370703"},{"label":"坊子区","value":"370704"},{"label":"奎文区","value":"370705"},{"label":"临朐县","value":"370724"},{"label":"昌乐县","value":"370725"},{"label":"潍坊滨海经济技术开发区","value":"370772"},{"label":"青州市","value":"370781"},{"label":"诸城市","value":"370782"},{"label":"寿光市","value":"370783"},{"label":"安丘市","value":"370784"},{"label":"高密市","value":"370785"},{"label":"昌邑市","value":"370786"}],[{"label":"任城区","value":"370811"},{"label":"兖州区","value":"370812"},{"label":"微山县","value":"370826"},{"label":"鱼台县","value":"370827"},{"label":"金乡县","value":"370828"},{"label":"嘉祥县","value":"370829"},{"label":"汶上县","value":"370830"},{"label":"泗水县","value":"370831"},{"label":"梁山县","value":"370832"},{"label":"济宁高新技术产业开发区","value":"370871"},{"label":"曲阜市","value":"370881"},{"label":"邹城市","value":"370883"}],[{"label":"泰山区","value":"370902"},{"label":"岱岳区","value":"370911"},{"label":"宁阳县","value":"370921"},{"label":"东平县","value":"370923"},{"label":"新泰市","value":"370982"},{"label":"肥城市","value":"370983"}],[{"label":"环翠区","value":"371002"},{"label":"文登区","value":"371003"},{"label":"威海火炬高技术产业开发区","value":"371071"},{"label":"威海经济技术开发区","value":"371072"},{"label":"威海临港经济技术开发区","value":"371073"},{"label":"荣成市","value":"371082"},{"label":"乳山市","value":"371083"}],[{"label":"东港区","value":"371102"},{"label":"岚山区","value":"371103"},{"label":"五莲县","value":"371121"},{"label":"莒县","value":"371122"},{"label":"日照经济技术开发区","value":"371171"},{"label":"日照国际海洋城","value":"371172"}],[{"label":"莱城区","value":"371202"},{"label":"钢城区","value":"371203"}],[{"label":"兰山区","value":"371302"},{"label":"罗庄区","value":"371311"},{"label":"河东区","value":"371312"},{"label":"沂南县","value":"371321"},{"label":"郯城县","value":"371322"},{"label":"沂水县","value":"371323"},{"label":"兰陵县","value":"371324"},{"label":"费县","value":"371325"},{"label":"平邑县","value":"371326"},{"label":"莒南县","value":"371327"},{"label":"蒙阴县","value":"371328"},{"label":"临沭县","value":"371329"},{"label":"临沂高新技术产业开发区","value":"371371"},{"label":"临沂经济技术开发区","value":"371372"},{"label":"临沂临港经济开发区","value":"371373"}],[{"label":"德城区","value":"371402"},{"label":"陵城区","value":"371403"},{"label":"宁津县","value":"371422"},{"label":"庆云县","value":"371423"},{"label":"临邑县","value":"371424"},{"label":"齐河县","value":"371425"},{"label":"平原县","value":"371426"},{"label":"夏津县","value":"371427"},{"label":"武城县","value":"371428"},{"label":"德州经济技术开发区","value":"371471"},{"label":"德州运河经济开发区","value":"371472"},{"label":"乐陵市","value":"371481"},{"label":"禹城市","value":"371482"}],[{"label":"东昌府区","value":"371502"},{"label":"阳谷县","value":"371521"},{"label":"莘县","value":"371522"},{"label":"茌平县","value":"371523"},{"label":"东阿县","value":"371524"},{"label":"冠县","value":"371525"},{"label":"高唐县","value":"371526"},{"label":"临清市","value":"371581"}],[{"label":"滨城区","value":"371602"},{"label":"沾化区","value":"371603"},{"label":"惠民县","value":"371621"},{"label":"阳信县","value":"371622"},{"label":"无棣县","value":"371623"},{"label":"博兴县","value":"371625"},{"label":"邹平县","value":"371626"}],[{"label":"牡丹区","value":"371702"},{"label":"定陶区","value":"371703"},{"label":"曹县","value":"371721"},{"label":"单县","value":"371722"},{"label":"成武县","value":"371723"},{"label":"巨野县","value":"371724"},{"label":"郓城县","value":"371725"},{"label":"鄄城县","value":"371726"},{"label":"东明县","value":"371728"},{"label":"菏泽经济技术开发区","value":"371771"},{"label":"菏泽高新技术开发区","value":"371772"}]],[[{"label":"中原区","value":"410102"},{"label":"二七区","value":"410103"},{"label":"管城回族区","value":"410104"},{"label":"金水区","value":"410105"},{"label":"上街区","value":"410106"},{"label":"惠济区","value":"410108"},{"label":"中牟县","value":"410122"},{"label":"郑州经济技术开发区","value":"410171"},{"label":"郑州高新技术产业开发区","value":"410172"},{"label":"郑州航空港经济综合实验区","value":"410173"},{"label":"巩义市","value":"410181"},{"label":"荥阳市","value":"410182"},{"label":"新密市","value":"410183"},{"label":"新郑市","value":"410184"},{"label":"登封市","value":"410185"}],[{"label":"龙亭区","value":"410202"},{"label":"顺河回族区","value":"410203"},{"label":"鼓楼区","value":"410204"},{"label":"禹王台区","value":"410205"},{"label":"祥符区","value":"410212"},{"label":"杞县","value":"410221"},{"label":"通许县","value":"410222"},{"label":"尉氏县","value":"410223"},{"label":"兰考县","value":"410225"}],[{"label":"老城区","value":"410302"},{"label":"西工区","value":"410303"},{"label":"瀍河回族区","value":"410304"},{"label":"涧西区","value":"410305"},{"label":"吉利区","value":"410306"},{"label":"洛龙区","value":"410311"},{"label":"孟津县","value":"410322"},{"label":"新安县","value":"410323"},{"label":"栾川县","value":"410324"},{"label":"嵩县","value":"410325"},{"label":"汝阳县","value":"410326"},{"label":"宜阳县","value":"410327"},{"label":"洛宁县","value":"410328"},{"label":"伊川县","value":"410329"},{"label":"洛阳高新技术产业开发区","value":"410371"},{"label":"偃师市","value":"410381"}],[{"label":"新华区","value":"410402"},{"label":"卫东区","value":"410403"},{"label":"石龙区","value":"410404"},{"label":"湛河区","value":"410411"},{"label":"宝丰县","value":"410421"},{"label":"叶县","value":"410422"},{"label":"鲁山县","value":"410423"},{"label":"郏县","value":"410425"},{"label":"平顶山高新技术产业开发区","value":"410471"},{"label":"平顶山市新城区","value":"410472"},{"label":"舞钢市","value":"410481"},{"label":"汝州市","value":"410482"}],[{"label":"文峰区","value":"410502"},{"label":"北关区","value":"410503"},{"label":"殷都区","value":"410505"},{"label":"龙安区","value":"410506"},{"label":"安阳县","value":"410522"},{"label":"汤阴县","value":"410523"},{"label":"滑县","value":"410526"},{"label":"内黄县","value":"410527"},{"label":"安阳高新技术产业开发区","value":"410571"},{"label":"林州市","value":"410581"}],[{"label":"鹤山区","value":"410602"},{"label":"山城区","value":"410603"},{"label":"淇滨区","value":"410611"},{"label":"浚县","value":"410621"},{"label":"淇县","value":"410622"},{"label":"鹤壁经济技术开发区","value":"410671"}],[{"label":"红旗区","value":"410702"},{"label":"卫滨区","value":"410703"},{"label":"凤泉区","value":"410704"},{"label":"牧野区","value":"410711"},{"label":"新乡县","value":"410721"},{"label":"获嘉县","value":"410724"},{"label":"原阳县","value":"410725"},{"label":"延津县","value":"410726"},{"label":"封丘县","value":"410727"},{"label":"长垣县","value":"410728"},{"label":"新乡高新技术产业开发区","value":"410771"},{"label":"新乡经济技术开发区","value":"410772"},{"label":"新乡市平原城乡一体化示范区","value":"410773"},{"label":"卫辉市","value":"410781"},{"label":"辉县市","value":"410782"}],[{"label":"解放区","value":"410802"},{"label":"中站区","value":"410803"},{"label":"马村区","value":"410804"},{"label":"山阳区","value":"410811"},{"label":"修武县","value":"410821"},{"label":"博爱县","value":"410822"},{"label":"武陟县","value":"410823"},{"label":"温县","value":"410825"},{"label":"焦作城乡一体化示范区","value":"410871"},{"label":"沁阳市","value":"410882"},{"label":"孟州市","value":"410883"}],[{"label":"华龙区","value":"410902"},{"label":"清丰县","value":"410922"},{"label":"南乐县","value":"410923"},{"label":"范县","value":"410926"},{"label":"台前县","value":"410927"},{"label":"濮阳县","value":"410928"},{"label":"河南濮阳工业园区","value":"410971"},{"label":"濮阳经济技术开发区","value":"410972"}],[{"label":"魏都区","value":"411002"},{"label":"建安区","value":"411003"},{"label":"鄢陵县","value":"411024"},{"label":"襄城县","value":"411025"},{"label":"许昌经济技术开发区","value":"411071"},{"label":"禹州市","value":"411081"},{"label":"长葛市","value":"411082"}],[{"label":"源汇区","value":"411102"},{"label":"郾城区","value":"411103"},{"label":"召陵区","value":"411104"},{"label":"舞阳县","value":"411121"},{"label":"临颍县","value":"411122"},{"label":"漯河经济技术开发区","value":"411171"}],[{"label":"湖滨区","value":"411202"},{"label":"陕州区","value":"411203"},{"label":"渑池县","value":"411221"},{"label":"卢氏县","value":"411224"},{"label":"河南三门峡经济开发区","value":"411271"},{"label":"义马市","value":"411281"},{"label":"灵宝市","value":"411282"}],[{"label":"宛城区","value":"411302"},{"label":"卧龙区","value":"411303"},{"label":"南召县","value":"411321"},{"label":"方城县","value":"411322"},{"label":"西峡县","value":"411323"},{"label":"镇平县","value":"411324"},{"label":"内乡县","value":"411325"},{"label":"淅川县","value":"411326"},{"label":"社旗县","value":"411327"},{"label":"唐河县","value":"411328"},{"label":"新野县","value":"411329"},{"label":"桐柏县","value":"411330"},{"label":"南阳高新技术产业开发区","value":"411371"},{"label":"南阳市城乡一体化示范区","value":"411372"},{"label":"邓州市","value":"411381"}],[{"label":"梁园区","value":"411402"},{"label":"睢阳区","value":"411403"},{"label":"民权县","value":"411421"},{"label":"睢县","value":"411422"},{"label":"宁陵县","value":"411423"},{"label":"柘城县","value":"411424"},{"label":"虞城县","value":"411425"},{"label":"夏邑县","value":"411426"},{"label":"豫东综合物流产业聚集区","value":"411471"},{"label":"河南商丘经济开发区","value":"411472"},{"label":"永城市","value":"411481"}],[{"label":"浉河区","value":"411502"},{"label":"平桥区","value":"411503"},{"label":"罗山县","value":"411521"},{"label":"光山县","value":"411522"},{"label":"新县","value":"411523"},{"label":"商城县","value":"411524"},{"label":"固始县","value":"411525"},{"label":"潢川县","value":"411526"},{"label":"淮滨县","value":"411527"},{"label":"息县","value":"411528"},{"label":"信阳高新技术产业开发区","value":"411571"}],[{"label":"川汇区","value":"411602"},{"label":"扶沟县","value":"411621"},{"label":"西华县","value":"411622"},{"label":"商水县","value":"411623"},{"label":"沈丘县","value":"411624"},{"label":"郸城县","value":"411625"},{"label":"淮阳县","value":"411626"},{"label":"太康县","value":"411627"},{"label":"鹿邑县","value":"411628"},{"label":"河南周口经济开发区","value":"411671"},{"label":"项城市","value":"411681"}],[{"label":"驿城区","value":"411702"},{"label":"西平县","value":"411721"},{"label":"上蔡县","value":"411722"},{"label":"平舆县","value":"411723"},{"label":"正阳县","value":"411724"},{"label":"确山县","value":"411725"},{"label":"泌阳县","value":"411726"},{"label":"汝南县","value":"411727"},{"label":"遂平县","value":"411728"},{"label":"新蔡县","value":"411729"},{"label":"河南驻马店经济开发区","value":"411771"}],[{"label":"济源市","value":"419001"}]],[[{"label":"江岸区","value":"420102"},{"label":"江汉区","value":"420103"},{"label":"硚口区","value":"420104"},{"label":"汉阳区","value":"420105"},{"label":"武昌区","value":"420106"},{"label":"青山区","value":"420107"},{"label":"洪山区","value":"420111"},{"label":"东西湖区","value":"420112"},{"label":"汉南区","value":"420113"},{"label":"蔡甸区","value":"420114"},{"label":"江夏区","value":"420115"},{"label":"黄陂区","value":"420116"},{"label":"新洲区","value":"420117"}],[{"label":"黄石港区","value":"420202"},{"label":"西塞山区","value":"420203"},{"label":"下陆区","value":"420204"},{"label":"铁山区","value":"420205"},{"label":"阳新县","value":"420222"},{"label":"大冶市","value":"420281"}],[{"label":"茅箭区","value":"420302"},{"label":"张湾区","value":"420303"},{"label":"郧阳区","value":"420304"},{"label":"郧西县","value":"420322"},{"label":"竹山县","value":"420323"},{"label":"竹溪县","value":"420324"},{"label":"房县","value":"420325"},{"label":"丹江口市","value":"420381"}],[{"label":"西陵区","value":"420502"},{"label":"伍家岗区","value":"420503"},{"label":"点军区","value":"420504"},{"label":"猇亭区","value":"420505"},{"label":"夷陵区","value":"420506"},{"label":"远安县","value":"420525"},{"label":"兴山县","value":"420526"},{"label":"秭归县","value":"420527"},{"label":"长阳土家族自治县","value":"420528"},{"label":"五峰土家族自治县","value":"420529"},{"label":"宜都市","value":"420581"},{"label":"当阳市","value":"420582"},{"label":"枝江市","value":"420583"}],[{"label":"襄城区","value":"420602"},{"label":"樊城区","value":"420606"},{"label":"襄州区","value":"420607"},{"label":"南漳县","value":"420624"},{"label":"谷城县","value":"420625"},{"label":"保康县","value":"420626"},{"label":"老河口市","value":"420682"},{"label":"枣阳市","value":"420683"},{"label":"宜城市","value":"420684"}],[{"label":"梁子湖区","value":"420702"},{"label":"华容区","value":"420703"},{"label":"鄂城区","value":"420704"}],[{"label":"东宝区","value":"420802"},{"label":"掇刀区","value":"420804"},{"label":"京山县","value":"420821"},{"label":"沙洋县","value":"420822"},{"label":"钟祥市","value":"420881"}],[{"label":"孝南区","value":"420902"},{"label":"孝昌县","value":"420921"},{"label":"大悟县","value":"420922"},{"label":"云梦县","value":"420923"},{"label":"应城市","value":"420981"},{"label":"安陆市","value":"420982"},{"label":"汉川市","value":"420984"}],[{"label":"沙市区","value":"421002"},{"label":"荆州区","value":"421003"},{"label":"公安县","value":"421022"},{"label":"监利县","value":"421023"},{"label":"江陵县","value":"421024"},{"label":"荆州经济技术开发区","value":"421071"},{"label":"石首市","value":"421081"},{"label":"洪湖市","value":"421083"},{"label":"松滋市","value":"421087"}],[{"label":"黄州区","value":"421102"},{"label":"团风县","value":"421121"},{"label":"红安县","value":"421122"},{"label":"罗田县","value":"421123"},{"label":"英山县","value":"421124"},{"label":"浠水县","value":"421125"},{"label":"蕲春县","value":"421126"},{"label":"黄梅县","value":"421127"},{"label":"龙感湖管理区","value":"421171"},{"label":"麻城市","value":"421181"},{"label":"武穴市","value":"421182"}],[{"label":"咸安区","value":"421202"},{"label":"嘉鱼县","value":"421221"},{"label":"通城县","value":"421222"},{"label":"崇阳县","value":"421223"},{"label":"通山县","value":"421224"},{"label":"赤壁市","value":"421281"}],[{"label":"曾都区","value":"421303"},{"label":"随县","value":"421321"},{"label":"广水市","value":"421381"}],[{"label":"恩施市","value":"422801"},{"label":"利川市","value":"422802"},{"label":"建始县","value":"422822"},{"label":"巴东县","value":"422823"},{"label":"宣恩县","value":"422825"},{"label":"咸丰县","value":"422826"},{"label":"来凤县","value":"422827"},{"label":"鹤峰县","value":"422828"}],[{"label":"仙桃市","value":"429004"},{"label":"潜江市","value":"429005"},{"label":"天门市","value":"429006"},{"label":"神农架林区","value":"429021"}]],[[{"label":"芙蓉区","value":"430102"},{"label":"天心区","value":"430103"},{"label":"岳麓区","value":"430104"},{"label":"开福区","value":"430105"},{"label":"雨花区","value":"430111"},{"label":"望城区","value":"430112"},{"label":"长沙县","value":"430121"},{"label":"浏阳市","value":"430181"},{"label":"宁乡市","value":"430182"}],[{"label":"荷塘区","value":"430202"},{"label":"芦淞区","value":"430203"},{"label":"石峰区","value":"430204"},{"label":"天元区","value":"430211"},{"label":"株洲县","value":"430221"},{"label":"攸县","value":"430223"},{"label":"茶陵县","value":"430224"},{"label":"炎陵县","value":"430225"},{"label":"云龙示范区","value":"430271"},{"label":"醴陵市","value":"430281"}],[{"label":"雨湖区","value":"430302"},{"label":"岳塘区","value":"430304"},{"label":"湘潭县","value":"430321"},{"label":"湖南湘潭高新技术产业园区","value":"430371"},{"label":"湘潭昭山示范区","value":"430372"},{"label":"湘潭九华示范区","value":"430373"},{"label":"湘乡市","value":"430381"},{"label":"韶山市","value":"430382"}],[{"label":"珠晖区","value":"430405"},{"label":"雁峰区","value":"430406"},{"label":"石鼓区","value":"430407"},{"label":"蒸湘区","value":"430408"},{"label":"南岳区","value":"430412"},{"label":"衡阳县","value":"430421"},{"label":"衡南县","value":"430422"},{"label":"衡山县","value":"430423"},{"label":"衡东县","value":"430424"},{"label":"祁东县","value":"430426"},{"label":"衡阳综合保税区","value":"430471"},{"label":"湖南衡阳高新技术产业园区","value":"430472"},{"label":"湖南衡阳松木经济开发区","value":"430473"},{"label":"耒阳市","value":"430481"},{"label":"常宁市","value":"430482"}],[{"label":"双清区","value":"430502"},{"label":"大祥区","value":"430503"},{"label":"北塔区","value":"430511"},{"label":"邵东县","value":"430521"},{"label":"新邵县","value":"430522"},{"label":"邵阳县","value":"430523"},{"label":"隆回县","value":"430524"},{"label":"洞口县","value":"430525"},{"label":"绥宁县","value":"430527"},{"label":"新宁县","value":"430528"},{"label":"城步苗族自治县","value":"430529"},{"label":"武冈市","value":"430581"}],[{"label":"岳阳楼区","value":"430602"},{"label":"云溪区","value":"430603"},{"label":"君山区","value":"430611"},{"label":"岳阳县","value":"430621"},{"label":"华容县","value":"430623"},{"label":"湘阴县","value":"430624"},{"label":"平江县","value":"430626"},{"label":"岳阳市屈原管理区","value":"430671"},{"label":"汨罗市","value":"430681"},{"label":"临湘市","value":"430682"}],[{"label":"武陵区","value":"430702"},{"label":"鼎城区","value":"430703"},{"label":"安乡县","value":"430721"},{"label":"汉寿县","value":"430722"},{"label":"澧县","value":"430723"},{"label":"临澧县","value":"430724"},{"label":"桃源县","value":"430725"},{"label":"石门县","value":"430726"},{"label":"常德市西洞庭管理区","value":"430771"},{"label":"津市市","value":"430781"}],[{"label":"永定区","value":"430802"},{"label":"武陵源区","value":"430811"},{"label":"慈利县","value":"430821"},{"label":"桑植县","value":"430822"}],[{"label":"资阳区","value":"430902"},{"label":"赫山区","value":"430903"},{"label":"南县","value":"430921"},{"label":"桃江县","value":"430922"},{"label":"安化县","value":"430923"},{"label":"益阳市大通湖管理区","value":"430971"},{"label":"湖南益阳高新技术产业园区","value":"430972"},{"label":"沅江市","value":"430981"}],[{"label":"北湖区","value":"431002"},{"label":"苏仙区","value":"431003"},{"label":"桂阳县","value":"431021"},{"label":"宜章县","value":"431022"},{"label":"永兴县","value":"431023"},{"label":"嘉禾县","value":"431024"},{"label":"临武县","value":"431025"},{"label":"汝城县","value":"431026"},{"label":"桂东县","value":"431027"},{"label":"安仁县","value":"431028"},{"label":"资兴市","value":"431081"}],[{"label":"零陵区","value":"431102"},{"label":"冷水滩区","value":"431103"},{"label":"祁阳县","value":"431121"},{"label":"东安县","value":"431122"},{"label":"双牌县","value":"431123"},{"label":"道县","value":"431124"},{"label":"江永县","value":"431125"},{"label":"宁远县","value":"431126"},{"label":"蓝山县","value":"431127"},{"label":"新田县","value":"431128"},{"label":"江华瑶族自治县","value":"431129"},{"label":"永州经济技术开发区","value":"431171"},{"label":"永州市金洞管理区","value":"431172"},{"label":"永州市回龙圩管理区","value":"431173"}],[{"label":"鹤城区","value":"431202"},{"label":"中方县","value":"431221"},{"label":"沅陵县","value":"431222"},{"label":"辰溪县","value":"431223"},{"label":"溆浦县","value":"431224"},{"label":"会同县","value":"431225"},{"label":"麻阳苗族自治县","value":"431226"},{"label":"新晃侗族自治县","value":"431227"},{"label":"芷江侗族自治县","value":"431228"},{"label":"靖州苗族侗族自治县","value":"431229"},{"label":"通道侗族自治县","value":"431230"},{"label":"怀化市洪江管理区","value":"431271"},{"label":"洪江市","value":"431281"}],[{"label":"娄星区","value":"431302"},{"label":"双峰县","value":"431321"},{"label":"新化县","value":"431322"},{"label":"冷水江市","value":"431381"},{"label":"涟源市","value":"431382"}],[{"label":"吉首市","value":"433101"},{"label":"泸溪县","value":"433122"},{"label":"凤凰县","value":"433123"},{"label":"花垣县","value":"433124"},{"label":"保靖县","value":"433125"},{"label":"古丈县","value":"433126"},{"label":"永顺县","value":"433127"},{"label":"龙山县","value":"433130"},{"label":"湖南吉首经济开发区","value":"433172"},{"label":"湖南永顺经济开发区","value":"433173"}]],[[{"label":"荔湾区","value":"440103"},{"label":"越秀区","value":"440104"},{"label":"海珠区","value":"440105"},{"label":"天河区","value":"440106"},{"label":"白云区","value":"440111"},{"label":"黄埔区","value":"440112"},{"label":"番禺区","value":"440113"},{"label":"花都区","value":"440114"},{"label":"南沙区","value":"440115"},{"label":"从化区","value":"440117"},{"label":"增城区","value":"440118"}],[{"label":"武江区","value":"440203"},{"label":"浈江区","value":"440204"},{"label":"曲江区","value":"440205"},{"label":"始兴县","value":"440222"},{"label":"仁化县","value":"440224"},{"label":"翁源县","value":"440229"},{"label":"乳源瑶族自治县","value":"440232"},{"label":"新丰县","value":"440233"},{"label":"乐昌市","value":"440281"},{"label":"南雄市","value":"440282"}],[{"label":"罗湖区","value":"440303"},{"label":"福田区","value":"440304"},{"label":"南山区","value":"440305"},{"label":"宝安区","value":"440306"},{"label":"龙岗区","value":"440307"},{"label":"盐田区","value":"440308"},{"label":"龙华区","value":"440309"},{"label":"坪山区","value":"440310"}],[{"label":"香洲区","value":"440402"},{"label":"斗门区","value":"440403"},{"label":"金湾区","value":"440404"}],[{"label":"龙湖区","value":"440507"},{"label":"金平区","value":"440511"},{"label":"濠江区","value":"440512"},{"label":"潮阳区","value":"440513"},{"label":"潮南区","value":"440514"},{"label":"澄海区","value":"440515"},{"label":"南澳县","value":"440523"}],[{"label":"禅城区","value":"440604"},{"label":"南海区","value":"440605"},{"label":"顺德区","value":"440606"},{"label":"三水区","value":"440607"},{"label":"高明区","value":"440608"}],[{"label":"蓬江区","value":"440703"},{"label":"江海区","value":"440704"},{"label":"新会区","value":"440705"},{"label":"台山市","value":"440781"},{"label":"开平市","value":"440783"},{"label":"鹤山市","value":"440784"},{"label":"恩平市","value":"440785"}],[{"label":"赤坎区","value":"440802"},{"label":"霞山区","value":"440803"},{"label":"坡头区","value":"440804"},{"label":"麻章区","value":"440811"},{"label":"遂溪县","value":"440823"},{"label":"徐闻县","value":"440825"},{"label":"廉江市","value":"440881"},{"label":"雷州市","value":"440882"},{"label":"吴川市","value":"440883"}],[{"label":"茂南区","value":"440902"},{"label":"电白区","value":"440904"},{"label":"高州市","value":"440981"},{"label":"化州市","value":"440982"},{"label":"信宜市","value":"440983"}],[{"label":"端州区","value":"441202"},{"label":"鼎湖区","value":"441203"},{"label":"高要区","value":"441204"},{"label":"广宁县","value":"441223"},{"label":"怀集县","value":"441224"},{"label":"封开县","value":"441225"},{"label":"德庆县","value":"441226"},{"label":"四会市","value":"441284"}],[{"label":"惠城区","value":"441302"},{"label":"惠阳区","value":"441303"},{"label":"博罗县","value":"441322"},{"label":"惠东县","value":"441323"},{"label":"龙门县","value":"441324"}],[{"label":"梅江区","value":"441402"},{"label":"梅县区","value":"441403"},{"label":"大埔县","value":"441422"},{"label":"丰顺县","value":"441423"},{"label":"五华县","value":"441424"},{"label":"平远县","value":"441426"},{"label":"蕉岭县","value":"441427"},{"label":"兴宁市","value":"441481"}],[{"label":"城区","value":"441502"},{"label":"海丰县","value":"441521"},{"label":"陆河县","value":"441523"},{"label":"陆丰市","value":"441581"}],[{"label":"源城区","value":"441602"},{"label":"紫金县","value":"441621"},{"label":"龙川县","value":"441622"},{"label":"连平县","value":"441623"},{"label":"和平县","value":"441624"},{"label":"东源县","value":"441625"}],[{"label":"江城区","value":"441702"},{"label":"阳东区","value":"441704"},{"label":"阳西县","value":"441721"},{"label":"阳春市","value":"441781"}],[{"label":"清城区","value":"441802"},{"label":"清新区","value":"441803"},{"label":"佛冈县","value":"441821"},{"label":"阳山县","value":"441823"},{"label":"连山壮族瑶族自治县","value":"441825"},{"label":"连南瑶族自治县","value":"441826"},{"label":"英德市","value":"441881"},{"label":"连州市","value":"441882"}],[{"label":"东莞市","value":"441900"}],[{"label":"中山市","value":"442000"}],[{"label":"湘桥区","value":"445102"},{"label":"潮安区","value":"445103"},{"label":"饶平县","value":"445122"}],[{"label":"榕城区","value":"445202"},{"label":"揭东区","value":"445203"},{"label":"揭西县","value":"445222"},{"label":"惠来县","value":"445224"},{"label":"普宁市","value":"445281"}],[{"label":"云城区","value":"445302"},{"label":"云安区","value":"445303"},{"label":"新兴县","value":"445321"},{"label":"郁南县","value":"445322"},{"label":"罗定市","value":"445381"}]],[[{"label":"兴宁区","value":"450102"},{"label":"青秀区","value":"450103"},{"label":"江南区","value":"450105"},{"label":"西乡塘区","value":"450107"},{"label":"良庆区","value":"450108"},{"label":"邕宁区","value":"450109"},{"label":"武鸣区","value":"450110"},{"label":"隆安县","value":"450123"},{"label":"马山县","value":"450124"},{"label":"上林县","value":"450125"},{"label":"宾阳县","value":"450126"},{"label":"横县","value":"450127"}],[{"label":"城中区","value":"450202"},{"label":"鱼峰区","value":"450203"},{"label":"柳南区","value":"450204"},{"label":"柳北区","value":"450205"},{"label":"柳江区","value":"450206"},{"label":"柳城县","value":"450222"},{"label":"鹿寨县","value":"450223"},{"label":"融安县","value":"450224"},{"label":"融水苗族自治县","value":"450225"},{"label":"三江侗族自治县","value":"450226"}],[{"label":"秀峰区","value":"450302"},{"label":"叠彩区","value":"450303"},{"label":"象山区","value":"450304"},{"label":"七星区","value":"450305"},{"label":"雁山区","value":"450311"},{"label":"临桂区","value":"450312"},{"label":"阳朔县","value":"450321"},{"label":"灵川县","value":"450323"},{"label":"全州县","value":"450324"},{"label":"兴安县","value":"450325"},{"label":"永福县","value":"450326"},{"label":"灌阳县","value":"450327"},{"label":"龙胜各族自治县","value":"450328"},{"label":"资源县","value":"450329"},{"label":"平乐县","value":"450330"},{"label":"荔浦县","value":"450331"},{"label":"恭城瑶族自治县","value":"450332"}],[{"label":"万秀区","value":"450403"},{"label":"长洲区","value":"450405"},{"label":"龙圩区","value":"450406"},{"label":"苍梧县","value":"450421"},{"label":"藤县","value":"450422"},{"label":"蒙山县","value":"450423"},{"label":"岑溪市","value":"450481"}],[{"label":"海城区","value":"450502"},{"label":"银海区","value":"450503"},{"label":"铁山港区","value":"450512"},{"label":"合浦县","value":"450521"}],[{"label":"港口区","value":"450602"},{"label":"防城区","value":"450603"},{"label":"上思县","value":"450621"},{"label":"东兴市","value":"450681"}],[{"label":"钦南区","value":"450702"},{"label":"钦北区","value":"450703"},{"label":"灵山县","value":"450721"},{"label":"浦北县","value":"450722"}],[{"label":"港北区","value":"450802"},{"label":"港南区","value":"450803"},{"label":"覃塘区","value":"450804"},{"label":"平南县","value":"450821"},{"label":"桂平市","value":"450881"}],[{"label":"玉州区","value":"450902"},{"label":"福绵区","value":"450903"},{"label":"容县","value":"450921"},{"label":"陆川县","value":"450922"},{"label":"博白县","value":"450923"},{"label":"兴业县","value":"450924"},{"label":"北流市","value":"450981"}],[{"label":"右江区","value":"451002"},{"label":"田阳县","value":"451021"},{"label":"田东县","value":"451022"},{"label":"平果县","value":"451023"},{"label":"德保县","value":"451024"},{"label":"那坡县","value":"451026"},{"label":"凌云县","value":"451027"},{"label":"乐业县","value":"451028"},{"label":"田林县","value":"451029"},{"label":"西林县","value":"451030"},{"label":"隆林各族自治县","value":"451031"},{"label":"靖西市","value":"451081"}],[{"label":"八步区","value":"451102"},{"label":"平桂区","value":"451103"},{"label":"昭平县","value":"451121"},{"label":"钟山县","value":"451122"},{"label":"富川瑶族自治县","value":"451123"}],[{"label":"金城江区","value":"451202"},{"label":"宜州区","value":"451203"},{"label":"南丹县","value":"451221"},{"label":"天峨县","value":"451222"},{"label":"凤山县","value":"451223"},{"label":"东兰县","value":"451224"},{"label":"罗城仫佬族自治县","value":"451225"},{"label":"环江毛南族自治县","value":"451226"},{"label":"巴马瑶族自治县","value":"451227"},{"label":"都安瑶族自治县","value":"451228"},{"label":"大化瑶族自治县","value":"451229"}],[{"label":"兴宾区","value":"451302"},{"label":"忻城县","value":"451321"},{"label":"象州县","value":"451322"},{"label":"武宣县","value":"451323"},{"label":"金秀瑶族自治县","value":"451324"},{"label":"合山市","value":"451381"}],[{"label":"江州区","value":"451402"},{"label":"扶绥县","value":"451421"},{"label":"宁明县","value":"451422"},{"label":"龙州县","value":"451423"},{"label":"大新县","value":"451424"},{"label":"天等县","value":"451425"},{"label":"凭祥市","value":"451481"}]],[[{"label":"秀英区","value":"460105"},{"label":"龙华区","value":"460106"},{"label":"琼山区","value":"460107"},{"label":"美兰区","value":"460108"}],[{"label":"海棠区","value":"460202"},{"label":"吉阳区","value":"460203"},{"label":"天涯区","value":"460204"},{"label":"崖州区","value":"460205"}],[{"label":"西沙群岛","value":"460321"},{"label":"南沙群岛","value":"460322"},{"label":"中沙群岛的岛礁及其海域","value":"460323"}],[{"label":"儋州市","value":"460400"}],[{"label":"五指山市","value":"469001"},{"label":"琼海市","value":"469002"},{"label":"文昌市","value":"469005"},{"label":"万宁市","value":"469006"},{"label":"东方市","value":"469007"},{"label":"定安县","value":"469021"},{"label":"屯昌县","value":"469022"},{"label":"澄迈县","value":"469023"},{"label":"临高县","value":"469024"},{"label":"白沙黎族自治县","value":"469025"},{"label":"昌江黎族自治县","value":"469026"},{"label":"乐东黎族自治县","value":"469027"},{"label":"陵水黎族自治县","value":"469028"},{"label":"保亭黎族苗族自治县","value":"469029"},{"label":"琼中黎族苗族自治县","value":"469030"}]],[[{"label":"万州区","value":"500101"},{"label":"涪陵区","value":"500102"},{"label":"渝中区","value":"500103"},{"label":"大渡口区","value":"500104"},{"label":"江北区","value":"500105"},{"label":"沙坪坝区","value":"500106"},{"label":"九龙坡区","value":"500107"},{"label":"南岸区","value":"500108"},{"label":"北碚区","value":"500109"},{"label":"綦江区","value":"500110"},{"label":"大足区","value":"500111"},{"label":"渝北区","value":"500112"},{"label":"巴南区","value":"500113"},{"label":"黔江区","value":"500114"},{"label":"长寿区","value":"500115"},{"label":"江津区","value":"500116"},{"label":"合川区","value":"500117"},{"label":"永川区","value":"500118"},{"label":"南川区","value":"500119"},{"label":"璧山区","value":"500120"},{"label":"铜梁区","value":"500151"},{"label":"潼南区","value":"500152"},{"label":"荣昌区","value":"500153"},{"label":"开州区","value":"500154"},{"label":"梁平区","value":"500155"},{"label":"武隆区","value":"500156"}],[{"label":"城口县","value":"500229"},{"label":"丰都县","value":"500230"},{"label":"垫江县","value":"500231"},{"label":"忠县","value":"500233"},{"label":"云阳县","value":"500235"},{"label":"奉节县","value":"500236"},{"label":"巫山县","value":"500237"},{"label":"巫溪县","value":"500238"},{"label":"石柱土家族自治县","value":"500240"},{"label":"秀山土家族苗族自治县","value":"500241"},{"label":"酉阳土家族苗族自治县","value":"500242"},{"label":"彭水苗族土家族自治县","value":"500243"}]],[[{"label":"锦江区","value":"510104"},{"label":"青羊区","value":"510105"},{"label":"金牛区","value":"510106"},{"label":"武侯区","value":"510107"},{"label":"成华区","value":"510108"},{"label":"龙泉驿区","value":"510112"},{"label":"青白江区","value":"510113"},{"label":"新都区","value":"510114"},{"label":"温江区","value":"510115"},{"label":"双流区","value":"510116"},{"label":"郫都区","value":"510117"},{"label":"金堂县","value":"510121"},{"label":"大邑县","value":"510129"},{"label":"蒲江县","value":"510131"},{"label":"新津县","value":"510132"},{"label":"都江堰市","value":"510181"},{"label":"彭州市","value":"510182"},{"label":"邛崃市","value":"510183"},{"label":"崇州市","value":"510184"},{"label":"简阳市","value":"510185"}],[{"label":"自流井区","value":"510302"},{"label":"贡井区","value":"510303"},{"label":"大安区","value":"510304"},{"label":"沿滩区","value":"510311"},{"label":"荣县","value":"510321"},{"label":"富顺县","value":"510322"}],[{"label":"东区","value":"510402"},{"label":"西区","value":"510403"},{"label":"仁和区","value":"510411"},{"label":"米易县","value":"510421"},{"label":"盐边县","value":"510422"}],[{"label":"江阳区","value":"510502"},{"label":"纳溪区","value":"510503"},{"label":"龙马潭区","value":"510504"},{"label":"泸县","value":"510521"},{"label":"合江县","value":"510522"},{"label":"叙永县","value":"510524"},{"label":"古蔺县","value":"510525"}],[{"label":"旌阳区","value":"510603"},{"label":"罗江区","value":"510604"},{"label":"中江县","value":"510623"},{"label":"广汉市","value":"510681"},{"label":"什邡市","value":"510682"},{"label":"绵竹市","value":"510683"}],[{"label":"涪城区","value":"510703"},{"label":"游仙区","value":"510704"},{"label":"安州区","value":"510705"},{"label":"三台县","value":"510722"},{"label":"盐亭县","value":"510723"},{"label":"梓潼县","value":"510725"},{"label":"北川羌族自治县","value":"510726"},{"label":"平武县","value":"510727"},{"label":"江油市","value":"510781"}],[{"label":"利州区","value":"510802"},{"label":"昭化区","value":"510811"},{"label":"朝天区","value":"510812"},{"label":"旺苍县","value":"510821"},{"label":"青川县","value":"510822"},{"label":"剑阁县","value":"510823"},{"label":"苍溪县","value":"510824"}],[{"label":"船山区","value":"510903"},{"label":"安居区","value":"510904"},{"label":"蓬溪县","value":"510921"},{"label":"射洪县","value":"510922"},{"label":"大英县","value":"510923"}],[{"label":"市中区","value":"511002"},{"label":"东兴区","value":"511011"},{"label":"威远县","value":"511024"},{"label":"资中县","value":"511025"},{"label":"内江经济开发区","value":"511071"},{"label":"隆昌市","value":"511083"}],[{"label":"市中区","value":"511102"},{"label":"沙湾区","value":"511111"},{"label":"五通桥区","value":"511112"},{"label":"金口河区","value":"511113"},{"label":"犍为县","value":"511123"},{"label":"井研县","value":"511124"},{"label":"夹江县","value":"511126"},{"label":"沐川县","value":"511129"},{"label":"峨边彝族自治县","value":"511132"},{"label":"马边彝族自治县","value":"511133"},{"label":"峨眉山市","value":"511181"}],[{"label":"顺庆区","value":"511302"},{"label":"高坪区","value":"511303"},{"label":"嘉陵区","value":"511304"},{"label":"南部县","value":"511321"},{"label":"营山县","value":"511322"},{"label":"蓬安县","value":"511323"},{"label":"仪陇县","value":"511324"},{"label":"西充县","value":"511325"},{"label":"阆中市","value":"511381"}],[{"label":"东坡区","value":"511402"},{"label":"彭山区","value":"511403"},{"label":"仁寿县","value":"511421"},{"label":"洪雅县","value":"511423"},{"label":"丹棱县","value":"511424"},{"label":"青神县","value":"511425"}],[{"label":"翠屏区","value":"511502"},{"label":"南溪区","value":"511503"},{"label":"宜宾县","value":"511521"},{"label":"江安县","value":"511523"},{"label":"长宁县","value":"511524"},{"label":"高县","value":"511525"},{"label":"珙县","value":"511526"},{"label":"筠连县","value":"511527"},{"label":"兴文县","value":"511528"},{"label":"屏山县","value":"511529"}],[{"label":"广安区","value":"511602"},{"label":"前锋区","value":"511603"},{"label":"岳池县","value":"511621"},{"label":"武胜县","value":"511622"},{"label":"邻水县","value":"511623"},{"label":"华蓥市","value":"511681"}],[{"label":"通川区","value":"511702"},{"label":"达川区","value":"511703"},{"label":"宣汉县","value":"511722"},{"label":"开江县","value":"511723"},{"label":"大竹县","value":"511724"},{"label":"渠县","value":"511725"},{"label":"达州经济开发区","value":"511771"},{"label":"万源市","value":"511781"}],[{"label":"雨城区","value":"511802"},{"label":"名山区","value":"511803"},{"label":"荥经县","value":"511822"},{"label":"汉源县","value":"511823"},{"label":"石棉县","value":"511824"},{"label":"天全县","value":"511825"},{"label":"芦山县","value":"511826"},{"label":"宝兴县","value":"511827"}],[{"label":"巴州区","value":"511902"},{"label":"恩阳区","value":"511903"},{"label":"通江县","value":"511921"},{"label":"南江县","value":"511922"},{"label":"平昌县","value":"511923"},{"label":"巴中经济开发区","value":"511971"}],[{"label":"雁江区","value":"512002"},{"label":"安岳县","value":"512021"},{"label":"乐至县","value":"512022"}],[{"label":"马尔康市","value":"513201"},{"label":"汶川县","value":"513221"},{"label":"理县","value":"513222"},{"label":"茂县","value":"513223"},{"label":"松潘县","value":"513224"},{"label":"九寨沟县","value":"513225"},{"label":"金川县","value":"513226"},{"label":"小金县","value":"513227"},{"label":"黑水县","value":"513228"},{"label":"壤塘县","value":"513230"},{"label":"阿坝县","value":"513231"},{"label":"若尔盖县","value":"513232"},{"label":"红原县","value":"513233"}],[{"label":"康定市","value":"513301"},{"label":"泸定县","value":"513322"},{"label":"丹巴县","value":"513323"},{"label":"九龙县","value":"513324"},{"label":"雅江县","value":"513325"},{"label":"道孚县","value":"513326"},{"label":"炉霍县","value":"513327"},{"label":"甘孜县","value":"513328"},{"label":"新龙县","value":"513329"},{"label":"德格县","value":"513330"},{"label":"白玉县","value":"513331"},{"label":"石渠县","value":"513332"},{"label":"色达县","value":"513333"},{"label":"理塘县","value":"513334"},{"label":"巴塘县","value":"513335"},{"label":"乡城县","value":"513336"},{"label":"稻城县","value":"513337"},{"label":"得荣县","value":"513338"}],[{"label":"西昌市","value":"513401"},{"label":"木里藏族自治县","value":"513422"},{"label":"盐源县","value":"513423"},{"label":"德昌县","value":"513424"},{"label":"会理县","value":"513425"},{"label":"会东县","value":"513426"},{"label":"宁南县","value":"513427"},{"label":"普格县","value":"513428"},{"label":"布拖县","value":"513429"},{"label":"金阳县","value":"513430"},{"label":"昭觉县","value":"513431"},{"label":"喜德县","value":"513432"},{"label":"冕宁县","value":"513433"},{"label":"越西县","value":"513434"},{"label":"甘洛县","value":"513435"},{"label":"美姑县","value":"513436"},{"label":"雷波县","value":"513437"}]],[[{"label":"南明区","value":"520102"},{"label":"云岩区","value":"520103"},{"label":"花溪区","value":"520111"},{"label":"乌当区","value":"520112"},{"label":"白云区","value":"520113"},{"label":"观山湖区","value":"520115"},{"label":"开阳县","value":"520121"},{"label":"息烽县","value":"520122"},{"label":"修文县","value":"520123"},{"label":"清镇市","value":"520181"}],[{"label":"钟山区","value":"520201"},{"label":"六枝特区","value":"520203"},{"label":"水城县","value":"520221"},{"label":"盘州市","value":"520281"}],[{"label":"红花岗区","value":"520302"},{"label":"汇川区","value":"520303"},{"label":"播州区","value":"520304"},{"label":"桐梓县","value":"520322"},{"label":"绥阳县","value":"520323"},{"label":"正安县","value":"520324"},{"label":"道真仡佬族苗族自治县","value":"520325"},{"label":"务川仡佬族苗族自治县","value":"520326"},{"label":"凤冈县","value":"520327"},{"label":"湄潭县","value":"520328"},{"label":"余庆县","value":"520329"},{"label":"习水县","value":"520330"},{"label":"赤水市","value":"520381"},{"label":"仁怀市","value":"520382"}],[{"label":"西秀区","value":"520402"},{"label":"平坝区","value":"520403"},{"label":"普定县","value":"520422"},{"label":"镇宁布依族苗族自治县","value":"520423"},{"label":"关岭布依族苗族自治县","value":"520424"},{"label":"紫云苗族布依族自治县","value":"520425"}],[{"label":"七星关区","value":"520502"},{"label":"大方县","value":"520521"},{"label":"黔西县","value":"520522"},{"label":"金沙县","value":"520523"},{"label":"织金县","value":"520524"},{"label":"纳雍县","value":"520525"},{"label":"威宁彝族回族苗族自治县","value":"520526"},{"label":"赫章县","value":"520527"}],[{"label":"碧江区","value":"520602"},{"label":"万山区","value":"520603"},{"label":"江口县","value":"520621"},{"label":"玉屏侗族自治县","value":"520622"},{"label":"石阡县","value":"520623"},{"label":"思南县","value":"520624"},{"label":"印江土家族苗族自治县","value":"520625"},{"label":"德江县","value":"520626"},{"label":"沿河土家族自治县","value":"520627"},{"label":"松桃苗族自治县","value":"520628"}],[{"label":"兴义市","value":"522301"},{"label":"兴仁县","value":"522322"},{"label":"普安县","value":"522323"},{"label":"晴隆县","value":"522324"},{"label":"贞丰县","value":"522325"},{"label":"望谟县","value":"522326"},{"label":"册亨县","value":"522327"},{"label":"安龙县","value":"522328"}],[{"label":"凯里市","value":"522601"},{"label":"黄平县","value":"522622"},{"label":"施秉县","value":"522623"},{"label":"三穗县","value":"522624"},{"label":"镇远县","value":"522625"},{"label":"岑巩县","value":"522626"},{"label":"天柱县","value":"522627"},{"label":"锦屏县","value":"522628"},{"label":"剑河县","value":"522629"},{"label":"台江县","value":"522630"},{"label":"黎平县","value":"522631"},{"label":"榕江县","value":"522632"},{"label":"从江县","value":"522633"},{"label":"雷山县","value":"522634"},{"label":"麻江县","value":"522635"},{"label":"丹寨县","value":"522636"}],[{"label":"都匀市","value":"522701"},{"label":"福泉市","value":"522702"},{"label":"荔波县","value":"522722"},{"label":"贵定县","value":"522723"},{"label":"瓮安县","value":"522725"},{"label":"独山县","value":"522726"},{"label":"平塘县","value":"522727"},{"label":"罗甸县","value":"522728"},{"label":"长顺县","value":"522729"},{"label":"龙里县","value":"522730"},{"label":"惠水县","value":"522731"},{"label":"三都水族自治县","value":"522732"}]],[[{"label":"五华区","value":"530102"},{"label":"盘龙区","value":"530103"},{"label":"官渡区","value":"530111"},{"label":"西山区","value":"530112"},{"label":"东川区","value":"530113"},{"label":"呈贡区","value":"530114"},{"label":"晋宁区","value":"530115"},{"label":"富民县","value":"530124"},{"label":"宜良县","value":"530125"},{"label":"石林彝族自治县","value":"530126"},{"label":"嵩明县","value":"530127"},{"label":"禄劝彝族苗族自治县","value":"530128"},{"label":"寻甸回族彝族自治县","value":"530129"},{"label":"安宁市","value":"530181"}],[{"label":"麒麟区","value":"530302"},{"label":"沾益区","value":"530303"},{"label":"马龙县","value":"530321"},{"label":"陆良县","value":"530322"},{"label":"师宗县","value":"530323"},{"label":"罗平县","value":"530324"},{"label":"富源县","value":"530325"},{"label":"会泽县","value":"530326"},{"label":"宣威市","value":"530381"}],[{"label":"红塔区","value":"530402"},{"label":"江川区","value":"530403"},{"label":"澄江县","value":"530422"},{"label":"通海县","value":"530423"},{"label":"华宁县","value":"530424"},{"label":"易门县","value":"530425"},{"label":"峨山彝族自治县","value":"530426"},{"label":"新平彝族傣族自治县","value":"530427"},{"label":"元江哈尼族彝族傣族自治县","value":"530428"}],[{"label":"隆阳区","value":"530502"},{"label":"施甸县","value":"530521"},{"label":"龙陵县","value":"530523"},{"label":"昌宁县","value":"530524"},{"label":"腾冲市","value":"530581"}],[{"label":"昭阳区","value":"530602"},{"label":"鲁甸县","value":"530621"},{"label":"巧家县","value":"530622"},{"label":"盐津县","value":"530623"},{"label":"大关县","value":"530624"},{"label":"永善县","value":"530625"},{"label":"绥江县","value":"530626"},{"label":"镇雄县","value":"530627"},{"label":"彝良县","value":"530628"},{"label":"威信县","value":"530629"},{"label":"水富县","value":"530630"}],[{"label":"古城区","value":"530702"},{"label":"玉龙纳西族自治县","value":"530721"},{"label":"永胜县","value":"530722"},{"label":"华坪县","value":"530723"},{"label":"宁蒗彝族自治县","value":"530724"}],[{"label":"思茅区","value":"530802"},{"label":"宁洱哈尼族彝族自治县","value":"530821"},{"label":"墨江哈尼族自治县","value":"530822"},{"label":"景东彝族自治县","value":"530823"},{"label":"景谷傣族彝族自治县","value":"530824"},{"label":"镇沅彝族哈尼族拉祜族自治县","value":"530825"},{"label":"江城哈尼族彝族自治县","value":"530826"},{"label":"孟连傣族拉祜族佤族自治县","value":"530827"},{"label":"澜沧拉祜族自治县","value":"530828"},{"label":"西盟佤族自治县","value":"530829"}],[{"label":"临翔区","value":"530902"},{"label":"凤庆县","value":"530921"},{"label":"云县","value":"530922"},{"label":"永德县","value":"530923"},{"label":"镇康县","value":"530924"},{"label":"双江拉祜族佤族布朗族傣族自治县","value":"530925"},{"label":"耿马傣族佤族自治县","value":"530926"},{"label":"沧源佤族自治县","value":"530927"}],[{"label":"楚雄市","value":"532301"},{"label":"双柏县","value":"532322"},{"label":"牟定县","value":"532323"},{"label":"南华县","value":"532324"},{"label":"姚安县","value":"532325"},{"label":"大姚县","value":"532326"},{"label":"永仁县","value":"532327"},{"label":"元谋县","value":"532328"},{"label":"武定县","value":"532329"},{"label":"禄丰县","value":"532331"}],[{"label":"个旧市","value":"532501"},{"label":"开远市","value":"532502"},{"label":"蒙自市","value":"532503"},{"label":"弥勒市","value":"532504"},{"label":"屏边苗族自治县","value":"532523"},{"label":"建水县","value":"532524"},{"label":"石屏县","value":"532525"},{"label":"泸西县","value":"532527"},{"label":"元阳县","value":"532528"},{"label":"红河县","value":"532529"},{"label":"金平苗族瑶族傣族自治县","value":"532530"},{"label":"绿春县","value":"532531"},{"label":"河口瑶族自治县","value":"532532"}],[{"label":"文山市","value":"532601"},{"label":"砚山县","value":"532622"},{"label":"西畴县","value":"532623"},{"label":"麻栗坡县","value":"532624"},{"label":"马关县","value":"532625"},{"label":"丘北县","value":"532626"},{"label":"广南县","value":"532627"},{"label":"富宁县","value":"532628"}],[{"label":"景洪市","value":"532801"},{"label":"勐海县","value":"532822"},{"label":"勐腊县","value":"532823"}],[{"label":"大理市","value":"532901"},{"label":"漾濞彝族自治县","value":"532922"},{"label":"祥云县","value":"532923"},{"label":"宾川县","value":"532924"},{"label":"弥渡县","value":"532925"},{"label":"南涧彝族自治县","value":"532926"},{"label":"巍山彝族回族自治县","value":"532927"},{"label":"永平县","value":"532928"},{"label":"云龙县","value":"532929"},{"label":"洱源县","value":"532930"},{"label":"剑川县","value":"532931"},{"label":"鹤庆县","value":"532932"}],[{"label":"瑞丽市","value":"533102"},{"label":"芒市","value":"533103"},{"label":"梁河县","value":"533122"},{"label":"盈江县","value":"533123"},{"label":"陇川县","value":"533124"}],[{"label":"泸水市","value":"533301"},{"label":"福贡县","value":"533323"},{"label":"贡山独龙族怒族自治县","value":"533324"},{"label":"兰坪白族普米族自治县","value":"533325"}],[{"label":"香格里拉市","value":"533401"},{"label":"德钦县","value":"533422"},{"label":"维西傈僳族自治县","value":"533423"}]],[[{"label":"城关区","value":"540102"},{"label":"堆龙德庆区","value":"540103"},{"label":"林周县","value":"540121"},{"label":"当雄县","value":"540122"},{"label":"尼木县","value":"540123"},{"label":"曲水县","value":"540124"},{"label":"达孜县","value":"540126"},{"label":"墨竹工卡县","value":"540127"},{"label":"格尔木藏青工业园区","value":"540171"},{"label":"拉萨经济技术开发区","value":"540172"},{"label":"西藏文化旅游创意园区","value":"540173"},{"label":"达孜工业园区","value":"540174"}],[{"label":"桑珠孜区","value":"540202"},{"label":"南木林县","value":"540221"},{"label":"江孜县","value":"540222"},{"label":"定日县","value":"540223"},{"label":"萨迦县","value":"540224"},{"label":"拉孜县","value":"540225"},{"label":"昂仁县","value":"540226"},{"label":"谢通门县","value":"540227"},{"label":"白朗县","value":"540228"},{"label":"仁布县","value":"540229"},{"label":"康马县","value":"540230"},{"label":"定结县","value":"540231"},{"label":"仲巴县","value":"540232"},{"label":"亚东县","value":"540233"},{"label":"吉隆县","value":"540234"},{"label":"聂拉木县","value":"540235"},{"label":"萨嘎县","value":"540236"},{"label":"岗巴县","value":"540237"}],[{"label":"卡若区","value":"540302"},{"label":"江达县","value":"540321"},{"label":"贡觉县","value":"540322"},{"label":"类乌齐县","value":"540323"},{"label":"丁青县","value":"540324"},{"label":"察雅县","value":"540325"},{"label":"八宿县","value":"540326"},{"label":"左贡县","value":"540327"},{"label":"芒康县","value":"540328"},{"label":"洛隆县","value":"540329"},{"label":"边坝县","value":"540330"}],[{"label":"巴宜区","value":"540402"},{"label":"工布江达县","value":"540421"},{"label":"米林县","value":"540422"},{"label":"墨脱县","value":"540423"},{"label":"波密县","value":"540424"},{"label":"察隅县","value":"540425"},{"label":"朗县","value":"540426"}],[{"label":"乃东区","value":"540502"},{"label":"扎囊县","value":"540521"},{"label":"贡嘎县","value":"540522"},{"label":"桑日县","value":"540523"},{"label":"琼结县","value":"540524"},{"label":"曲松县","value":"540525"},{"label":"措美县","value":"540526"},{"label":"洛扎县","value":"540527"},{"label":"加查县","value":"540528"},{"label":"隆子县","value":"540529"},{"label":"错那县","value":"540530"},{"label":"浪卡子县","value":"540531"}],[{"label":"那曲县","value":"542421"},{"label":"嘉黎县","value":"542422"},{"label":"比如县","value":"542423"},{"label":"聂荣县","value":"542424"},{"label":"安多县","value":"542425"},{"label":"申扎县","value":"542426"},{"label":"索县","value":"542427"},{"label":"班戈县","value":"542428"},{"label":"巴青县","value":"542429"},{"label":"尼玛县","value":"542430"},{"label":"双湖县","value":"542431"}],[{"label":"普兰县","value":"542521"},{"label":"札达县","value":"542522"},{"label":"噶尔县","value":"542523"},{"label":"日土县","value":"542524"},{"label":"革吉县","value":"542525"},{"label":"改则县","value":"542526"},{"label":"措勤县","value":"542527"}]],[[{"label":"新城区","value":"610102"},{"label":"碑林区","value":"610103"},{"label":"莲湖区","value":"610104"},{"label":"灞桥区","value":"610111"},{"label":"未央区","value":"610112"},{"label":"雁塔区","value":"610113"},{"label":"阎良区","value":"610114"},{"label":"临潼区","value":"610115"},{"label":"长安区","value":"610116"},{"label":"高陵区","value":"610117"},{"label":"鄠邑区","value":"610118"},{"label":"蓝田县","value":"610122"},{"label":"周至县","value":"610124"}],[{"label":"王益区","value":"610202"},{"label":"印台区","value":"610203"},{"label":"耀州区","value":"610204"},{"label":"宜君县","value":"610222"}],[{"label":"渭滨区","value":"610302"},{"label":"金台区","value":"610303"},{"label":"陈仓区","value":"610304"},{"label":"凤翔县","value":"610322"},{"label":"岐山县","value":"610323"},{"label":"扶风县","value":"610324"},{"label":"眉县","value":"610326"},{"label":"陇县","value":"610327"},{"label":"千阳县","value":"610328"},{"label":"麟游县","value":"610329"},{"label":"凤县","value":"610330"},{"label":"太白县","value":"610331"}],[{"label":"秦都区","value":"610402"},{"label":"杨陵区","value":"610403"},{"label":"渭城区","value":"610404"},{"label":"三原县","value":"610422"},{"label":"泾阳县","value":"610423"},{"label":"乾县","value":"610424"},{"label":"礼泉县","value":"610425"},{"label":"永寿县","value":"610426"},{"label":"彬县","value":"610427"},{"label":"长武县","value":"610428"},{"label":"旬邑县","value":"610429"},{"label":"淳化县","value":"610430"},{"label":"武功县","value":"610431"},{"label":"兴平市","value":"610481"}],[{"label":"临渭区","value":"610502"},{"label":"华州区","value":"610503"},{"label":"潼关县","value":"610522"},{"label":"大荔县","value":"610523"},{"label":"合阳县","value":"610524"},{"label":"澄城县","value":"610525"},{"label":"蒲城县","value":"610526"},{"label":"白水县","value":"610527"},{"label":"富平县","value":"610528"},{"label":"韩城市","value":"610581"},{"label":"华阴市","value":"610582"}],[{"label":"宝塔区","value":"610602"},{"label":"安塞区","value":"610603"},{"label":"延长县","value":"610621"},{"label":"延川县","value":"610622"},{"label":"子长县","value":"610623"},{"label":"志丹县","value":"610625"},{"label":"吴起县","value":"610626"},{"label":"甘泉县","value":"610627"},{"label":"富县","value":"610628"},{"label":"洛川县","value":"610629"},{"label":"宜川县","value":"610630"},{"label":"黄龙县","value":"610631"},{"label":"黄陵县","value":"610632"}],[{"label":"汉台区","value":"610702"},{"label":"南郑区","value":"610703"},{"label":"城固县","value":"610722"},{"label":"洋县","value":"610723"},{"label":"西乡县","value":"610724"},{"label":"勉县","value":"610725"},{"label":"宁强县","value":"610726"},{"label":"略阳县","value":"610727"},{"label":"镇巴县","value":"610728"},{"label":"留坝县","value":"610729"},{"label":"佛坪县","value":"610730"}],[{"label":"榆阳区","value":"610802"},{"label":"横山区","value":"610803"},{"label":"府谷县","value":"610822"},{"label":"靖边县","value":"610824"},{"label":"定边县","value":"610825"},{"label":"绥德县","value":"610826"},{"label":"米脂县","value":"610827"},{"label":"佳县","value":"610828"},{"label":"吴堡县","value":"610829"},{"label":"清涧县","value":"610830"},{"label":"子洲县","value":"610831"},{"label":"神木市","value":"610881"}],[{"label":"汉滨区","value":"610902"},{"label":"汉阴县","value":"610921"},{"label":"石泉县","value":"610922"},{"label":"宁陕县","value":"610923"},{"label":"紫阳县","value":"610924"},{"label":"岚皋县","value":"610925"},{"label":"平利县","value":"610926"},{"label":"镇坪县","value":"610927"},{"label":"旬阳县","value":"610928"},{"label":"白河县","value":"610929"}],[{"label":"商州区","value":"611002"},{"label":"洛南县","value":"611021"},{"label":"丹凤县","value":"611022"},{"label":"商南县","value":"611023"},{"label":"山阳县","value":"611024"},{"label":"镇安县","value":"611025"},{"label":"柞水县","value":"611026"}]],[[{"label":"城关区","value":"620102"},{"label":"七里河区","value":"620103"},{"label":"西固区","value":"620104"},{"label":"安宁区","value":"620105"},{"label":"红古区","value":"620111"},{"label":"永登县","value":"620121"},{"label":"皋兰县","value":"620122"},{"label":"榆中县","value":"620123"},{"label":"兰州新区","value":"620171"}],[{"label":"嘉峪关市","value":"620201"}],[{"label":"金川区","value":"620302"},{"label":"永昌县","value":"620321"}],[{"label":"白银区","value":"620402"},{"label":"平川区","value":"620403"},{"label":"靖远县","value":"620421"},{"label":"会宁县","value":"620422"},{"label":"景泰县","value":"620423"}],[{"label":"秦州区","value":"620502"},{"label":"麦积区","value":"620503"},{"label":"清水县","value":"620521"},{"label":"秦安县","value":"620522"},{"label":"甘谷县","value":"620523"},{"label":"武山县","value":"620524"},{"label":"张家川回族自治县","value":"620525"}],[{"label":"凉州区","value":"620602"},{"label":"民勤县","value":"620621"},{"label":"古浪县","value":"620622"},{"label":"天祝藏族自治县","value":"620623"}],[{"label":"甘州区","value":"620702"},{"label":"肃南裕固族自治县","value":"620721"},{"label":"民乐县","value":"620722"},{"label":"临泽县","value":"620723"},{"label":"高台县","value":"620724"},{"label":"山丹县","value":"620725"}],[{"label":"崆峒区","value":"620802"},{"label":"泾川县","value":"620821"},{"label":"灵台县","value":"620822"},{"label":"崇信县","value":"620823"},{"label":"华亭县","value":"620824"},{"label":"庄浪县","value":"620825"},{"label":"静宁县","value":"620826"},{"label":"平凉工业园区","value":"620871"}],[{"label":"肃州区","value":"620902"},{"label":"金塔县","value":"620921"},{"label":"瓜州县","value":"620922"},{"label":"肃北蒙古族自治县","value":"620923"},{"label":"阿克塞哈萨克族自治县","value":"620924"},{"label":"玉门市","value":"620981"},{"label":"敦煌市","value":"620982"}],[{"label":"西峰区","value":"621002"},{"label":"庆城县","value":"621021"},{"label":"环县","value":"621022"},{"label":"华池县","value":"621023"},{"label":"合水县","value":"621024"},{"label":"正宁县","value":"621025"},{"label":"宁县","value":"621026"},{"label":"镇原县","value":"621027"}],[{"label":"安定区","value":"621102"},{"label":"通渭县","value":"621121"},{"label":"陇西县","value":"621122"},{"label":"渭源县","value":"621123"},{"label":"临洮县","value":"621124"},{"label":"漳县","value":"621125"},{"label":"岷县","value":"621126"}],[{"label":"武都区","value":"621202"},{"label":"成县","value":"621221"},{"label":"文县","value":"621222"},{"label":"宕昌县","value":"621223"},{"label":"康县","value":"621224"},{"label":"西和县","value":"621225"},{"label":"礼县","value":"621226"},{"label":"徽县","value":"621227"},{"label":"两当县","value":"621228"}],[{"label":"临夏市","value":"622901"},{"label":"临夏县","value":"622921"},{"label":"康乐县","value":"622922"},{"label":"永靖县","value":"622923"},{"label":"广河县","value":"622924"},{"label":"和政县","value":"622925"},{"label":"东乡族自治县","value":"622926"},{"label":"积石山保安族东乡族撒拉族自治县","value":"622927"}],[{"label":"合作市","value":"623001"},{"label":"临潭县","value":"623021"},{"label":"卓尼县","value":"623022"},{"label":"舟曲县","value":"623023"},{"label":"迭部县","value":"623024"},{"label":"玛曲县","value":"623025"},{"label":"碌曲县","value":"623026"},{"label":"夏河县","value":"623027"}]],[[{"label":"城东区","value":"630102"},{"label":"城中区","value":"630103"},{"label":"城西区","value":"630104"},{"label":"城北区","value":"630105"},{"label":"大通回族土族自治县","value":"630121"},{"label":"湟中县","value":"630122"},{"label":"湟源县","value":"630123"}],[{"label":"乐都区","value":"630202"},{"label":"平安区","value":"630203"},{"label":"民和回族土族自治县","value":"630222"},{"label":"互助土族自治县","value":"630223"},{"label":"化隆回族自治县","value":"630224"},{"label":"循化撒拉族自治县","value":"630225"}],[{"label":"门源回族自治县","value":"632221"},{"label":"祁连县","value":"632222"},{"label":"海晏县","value":"632223"},{"label":"刚察县","value":"632224"}],[{"label":"同仁县","value":"632321"},{"label":"尖扎县","value":"632322"},{"label":"泽库县","value":"632323"},{"label":"河南蒙古族自治县","value":"632324"}],[{"label":"共和县","value":"632521"},{"label":"同德县","value":"632522"},{"label":"贵德县","value":"632523"},{"label":"兴海县","value":"632524"},{"label":"贵南县","value":"632525"}],[{"label":"玛沁县","value":"632621"},{"label":"班玛县","value":"632622"},{"label":"甘德县","value":"632623"},{"label":"达日县","value":"632624"},{"label":"久治县","value":"632625"},{"label":"玛多县","value":"632626"}],[{"label":"玉树市","value":"632701"},{"label":"杂多县","value":"632722"},{"label":"称多县","value":"632723"},{"label":"治多县","value":"632724"},{"label":"囊谦县","value":"632725"},{"label":"曲麻莱县","value":"632726"}],[{"label":"格尔木市","value":"632801"},{"label":"德令哈市","value":"632802"},{"label":"乌兰县","value":"632821"},{"label":"都兰县","value":"632822"},{"label":"天峻县","value":"632823"},{"label":"大柴旦行政委员会","value":"632857"},{"label":"冷湖行政委员会","value":"632858"},{"label":"茫崖行政委员会","value":"632859"}]],[[{"label":"兴庆区","value":"640104"},{"label":"西夏区","value":"640105"},{"label":"金凤区","value":"640106"},{"label":"永宁县","value":"640121"},{"label":"贺兰县","value":"640122"},{"label":"灵武市","value":"640181"}],[{"label":"大武口区","value":"640202"},{"label":"惠农区","value":"640205"},{"label":"平罗县","value":"640221"}],[{"label":"利通区","value":"640302"},{"label":"红寺堡区","value":"640303"},{"label":"盐池县","value":"640323"},{"label":"同心县","value":"640324"},{"label":"青铜峡市","value":"640381"}],[{"label":"原州区","value":"640402"},{"label":"西吉县","value":"640422"},{"label":"隆德县","value":"640423"},{"label":"泾源县","value":"640424"},{"label":"彭阳县","value":"640425"}],[{"label":"沙坡头区","value":"640502"},{"label":"中宁县","value":"640521"},{"label":"海原县","value":"640522"}]],[[{"label":"天山区","value":"650102"},{"label":"沙依巴克区","value":"650103"},{"label":"新市区","value":"650104"},{"label":"水磨沟区","value":"650105"},{"label":"头屯河区","value":"650106"},{"label":"达坂城区","value":"650107"},{"label":"米东区","value":"650109"},{"label":"乌鲁木齐县","value":"650121"},{"label":"乌鲁木齐经济技术开发区","value":"650171"},{"label":"乌鲁木齐高新技术产业开发区","value":"650172"}],[{"label":"独山子区","value":"650202"},{"label":"克拉玛依区","value":"650203"},{"label":"白碱滩区","value":"650204"},{"label":"乌尔禾区","value":"650205"}],[{"label":"高昌区","value":"650402"},{"label":"鄯善县","value":"650421"},{"label":"托克逊县","value":"650422"}],[{"label":"伊州区","value":"650502"},{"label":"巴里坤哈萨克自治县","value":"650521"},{"label":"伊吾县","value":"650522"}],[{"label":"昌吉市","value":"652301"},{"label":"阜康市","value":"652302"},{"label":"呼图壁县","value":"652323"},{"label":"玛纳斯县","value":"652324"},{"label":"奇台县","value":"652325"},{"label":"吉木萨尔县","value":"652327"},{"label":"木垒哈萨克自治县","value":"652328"}],[{"label":"博乐市","value":"652701"},{"label":"阿拉山口市","value":"652702"},{"label":"精河县","value":"652722"},{"label":"温泉县","value":"652723"}],[{"label":"库尔勒市","value":"652801"},{"label":"轮台县","value":"652822"},{"label":"尉犁县","value":"652823"},{"label":"若羌县","value":"652824"},{"label":"且末县","value":"652825"},{"label":"焉耆回族自治县","value":"652826"},{"label":"和静县","value":"652827"},{"label":"和硕县","value":"652828"},{"label":"博湖县","value":"652829"},{"label":"库尔勒经济技术开发区","value":"652871"}],[{"label":"阿克苏市","value":"652901"},{"label":"温宿县","value":"652922"},{"label":"库车县","value":"652923"},{"label":"沙雅县","value":"652924"},{"label":"新和县","value":"652925"},{"label":"拜城县","value":"652926"},{"label":"乌什县","value":"652927"},{"label":"阿瓦提县","value":"652928"},{"label":"柯坪县","value":"652929"}],[{"label":"阿图什市","value":"653001"},{"label":"阿克陶县","value":"653022"},{"label":"阿合奇县","value":"653023"},{"label":"乌恰县","value":"653024"}],[{"label":"喀什市","value":"653101"},{"label":"疏附县","value":"653121"},{"label":"疏勒县","value":"653122"},{"label":"英吉沙县","value":"653123"},{"label":"泽普县","value":"653124"},{"label":"莎车县","value":"653125"},{"label":"叶城县","value":"653126"},{"label":"麦盖提县","value":"653127"},{"label":"岳普湖县","value":"653128"},{"label":"伽师县","value":"653129"},{"label":"巴楚县","value":"653130"},{"label":"塔什库尔干塔吉克自治县","value":"653131"}],[{"label":"和田市","value":"653201"},{"label":"和田县","value":"653221"},{"label":"墨玉县","value":"653222"},{"label":"皮山县","value":"653223"},{"label":"洛浦县","value":"653224"},{"label":"策勒县","value":"653225"},{"label":"于田县","value":"653226"},{"label":"民丰县","value":"653227"}],[{"label":"伊宁市","value":"654002"},{"label":"奎屯市","value":"654003"},{"label":"霍尔果斯市","value":"654004"},{"label":"伊宁县","value":"654021"},{"label":"察布查尔锡伯自治县","value":"654022"},{"label":"霍城县","value":"654023"},{"label":"巩留县","value":"654024"},{"label":"新源县","value":"654025"},{"label":"昭苏县","value":"654026"},{"label":"特克斯县","value":"654027"},{"label":"尼勒克县","value":"654028"}],[{"label":"塔城市","value":"654201"},{"label":"乌苏市","value":"654202"},{"label":"额敏县","value":"654221"},{"label":"沙湾县","value":"654223"},{"label":"托里县","value":"654224"},{"label":"裕民县","value":"654225"},{"label":"和布克赛尔蒙古自治县","value":"654226"}],[{"label":"阿勒泰市","value":"654301"},{"label":"布尔津县","value":"654321"},{"label":"富蕴县","value":"654322"},{"label":"福海县","value":"654323"},{"label":"哈巴河县","value":"654324"},{"label":"青河县","value":"654325"},{"label":"吉木乃县","value":"654326"}],[{"label":"石河子市","value":"659001"},{"label":"阿拉尔市","value":"659002"},{"label":"图木舒克市","value":"659003"},{"label":"五家渠市","value":"659004"},{"label":"铁门关市","value":"659006"}]],[[{"label":"台北","value":"660101"}],[{"label":"高雄","value":"660201"}],[{"label":"基隆","value":"660301"}],[{"label":"台中","value":"660401"}],[{"label":"台南","value":"660501"}],[{"label":"新竹","value":"660601"}],[{"label":"嘉义","value":"660701"}],[{"label":"宜兰","value":"660801"}],[{"label":"桃园","value":"660901"}],[{"label":"苗栗","value":"661001"}],[{"label":"彰化","value":"661101"}],[{"label":"南投","value":"661201"}],[{"label":"云林","value":"661301"}],[{"label":"屏东","value":"661401"}],[{"label":"台东","value":"661501"}],[{"label":"花莲","value":"661601"}],[{"label":"澎湖","value":"661701"}]],[[{"label":"香港岛","value":"670101"}],[{"label":"九龙","value":"670201"}],[{"label":"新界","value":"670301"}]],[[{"label":"澳门半岛","value":"680101"}],[{"label":"氹仔岛","value":"680201"}],[{"label":"路环岛","value":"680301"}],[{"label":"路氹城","value":"680401"}]]];export default areaData; \ No newline at end of file diff --git a/libs/util/async-validator.js b/libs/util/async-validator.js new file mode 100644 index 0000000..6183d0a --- /dev/null +++ b/libs/util/async-validator.js @@ -0,0 +1,1356 @@ +function _extends() { + _extends = Object.assign || function(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; + }; + + return _extends.apply(this, arguments); +} + +/* eslint no-console:0 */ +var formatRegExp = /%[sdj%]/g; +var warning = function warning() {}; // don't print warning message when in production env or node runtime + +if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV !== 'production' && typeof window !== + 'undefined' && typeof document !== 'undefined') { + warning = function warning(type, errors) { + if (typeof console !== 'undefined' && console.warn) { + if (errors.every(function(e) { + return typeof e === 'string'; + })) { + console.warn(type, errors); + } + } + }; +} + +function convertFieldsError(errors) { + if (!errors || !errors.length) return null; + var fields = {}; + errors.forEach(function(error) { + var field = error.field; + fields[field] = fields[field] || []; + fields[field].push(error); + }); + return fields; +} + +function format() { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + var i = 1; + var f = args[0]; + var len = args.length; + + if (typeof f === 'function') { + return f.apply(null, args.slice(1)); + } + + if (typeof f === 'string') { + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') { + return '%'; + } + + if (i >= len) { + return x; + } + + switch (x) { + case '%s': + return String(args[i++]); + + case '%d': + return Number(args[i++]); + + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + + break; + + default: + return x; + } + }); + + for (var arg = args[i]; i < len; arg = args[++i]) { + str += " " + arg; + } + + return str; + } + + return f; +} + +function isNativeStringType(type) { + return type === 'string' || type === 'url' || type === 'hex' || type === 'email' || type === 'pattern'; +} + +function isEmptyValue(value, type) { + if (value === undefined || value === null) { + return true; + } + + if (type === 'array' && Array.isArray(value) && !value.length) { + return true; + } + + if (isNativeStringType(type) && typeof value === 'string' && !value) { + return true; + } + + return false; +} + +function asyncParallelArray(arr, func, callback) { + var results = []; + var total = 0; + var arrLength = arr.length; + + function count(errors) { + results.push.apply(results, errors); + total++; + + if (total === arrLength) { + callback(results); + } + } + + arr.forEach(function(a) { + func(a, count); + }); +} + +function asyncSerialArray(arr, func, callback) { + var index = 0; + var arrLength = arr.length; + + function next(errors) { + if (errors && errors.length) { + callback(errors); + return; + } + + var original = index; + index = index + 1; + + if (original < arrLength) { + func(arr[original], next); + } else { + callback([]); + } + } + + next([]); +} + +function flattenObjArr(objArr) { + var ret = []; + Object.keys(objArr).forEach(function(k) { + ret.push.apply(ret, objArr[k]); + }); + return ret; +} + +function asyncMap(objArr, option, func, callback) { + if (option.first) { + var _pending = new Promise(function(resolve, reject) { + var next = function next(errors) { + callback(errors); + return errors.length ? reject({ + errors: errors, + fields: convertFieldsError(errors) + }) : resolve(); + }; + + var flattenArr = flattenObjArr(objArr); + asyncSerialArray(flattenArr, func, next); + }); + + _pending["catch"](function(e) { + return e; + }); + + return _pending; + } + + var firstFields = option.firstFields || []; + + if (firstFields === true) { + firstFields = Object.keys(objArr); + } + + var objArrKeys = Object.keys(objArr); + var objArrLength = objArrKeys.length; + var total = 0; + var results = []; + var pending = new Promise(function(resolve, reject) { + var next = function next(errors) { + results.push.apply(results, errors); + total++; + + if (total === objArrLength) { + callback(results); + return results.length ? reject({ + errors: results, + fields: convertFieldsError(results) + }) : resolve(); + } + }; + + if (!objArrKeys.length) { + callback(results); + resolve(); + } + + objArrKeys.forEach(function(key) { + var arr = objArr[key]; + + if (firstFields.indexOf(key) !== -1) { + asyncSerialArray(arr, func, next); + } else { + asyncParallelArray(arr, func, next); + } + }); + }); + pending["catch"](function(e) { + return e; + }); + return pending; +} + +function complementError(rule) { + return function(oe) { + if (oe && oe.message) { + oe.field = oe.field || rule.fullField; + return oe; + } + + return { + message: typeof oe === 'function' ? oe() : oe, + field: oe.field || rule.fullField + }; + }; +} + +function deepMerge(target, source) { + if (source) { + for (var s in source) { + if (source.hasOwnProperty(s)) { + var value = source[s]; + + if (typeof value === 'object' && typeof target[s] === 'object') { + target[s] = _extends({}, target[s], {}, value); + } else { + target[s] = value; + } + } + } + } + + return target; +} + +/** + * Rule for validating required fields. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param source The source object being validated. + * @param errors An array of errors that this rule may add + * validation errors to. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function required(rule, value, source, errors, options, type) { + if (rule.required && (!source.hasOwnProperty(rule.field) || isEmptyValue(value, type || rule.type))) { + errors.push(format(options.messages.required, rule.fullField)); + } +} + +/** + * Rule for validating whitespace. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param source The source object being validated. + * @param errors An array of errors that this rule may add + * validation errors to. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function whitespace(rule, value, source, errors, options) { + if (/^\s+$/.test(value) || value === '') { + errors.push(format(options.messages.whitespace, rule.fullField)); + } +} + +/* eslint max-len:0 */ + +var pattern = { + // http://emailregex.com/ + email: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, + url: new RegExp( + "^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$", + 'i'), + hex: /^#?([a-f0-9]{6}|[a-f0-9]{3})$/i +}; +var types = { + integer: function integer(value) { + return types.number(value) && parseInt(value, 10) === value; + }, + "float": function float(value) { + return types.number(value) && !types.integer(value); + }, + array: function array(value) { + return Array.isArray(value); + }, + regexp: function regexp(value) { + if (value instanceof RegExp) { + return true; + } + + try { + return !!new RegExp(value); + } catch (e) { + return false; + } + }, + date: function date(value) { + return typeof value.getTime === 'function' && typeof value.getMonth === 'function' && typeof value.getYear === + 'function'; + }, + number: function number(value) { + if (isNaN(value)) { + return false; + } + + // 修改源码,将字符串数值先转为数值 + return typeof +value === 'number'; + }, + object: function object(value) { + return typeof value === 'object' && !types.array(value); + }, + method: function method(value) { + return typeof value === 'function'; + }, + email: function email(value) { + return typeof value === 'string' && !!value.match(pattern.email) && value.length < 255; + }, + url: function url(value) { + return typeof value === 'string' && !!value.match(pattern.url); + }, + hex: function hex(value) { + return typeof value === 'string' && !!value.match(pattern.hex); + } +}; +/** + * Rule for validating the type of a value. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param source The source object being validated. + * @param errors An array of errors that this rule may add + * validation errors to. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function type(rule, value, source, errors, options) { + if (rule.required && value === undefined) { + required(rule, value, source, errors, options); + return; + } + + var custom = ['integer', 'float', 'array', 'regexp', 'object', 'method', 'email', 'number', 'date', 'url', 'hex']; + var ruleType = rule.type; + + if (custom.indexOf(ruleType) > -1) { + if (!types[ruleType](value)) { + errors.push(format(options.messages.types[ruleType], rule.fullField, rule.type)); + } // straight typeof check + + } else if (ruleType && typeof value !== rule.type) { + errors.push(format(options.messages.types[ruleType], rule.fullField, rule.type)); + } +} + +/** + * Rule for validating minimum and maximum allowed values. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param source The source object being validated. + * @param errors An array of errors that this rule may add + * validation errors to. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function range(rule, value, source, errors, options) { + var len = typeof rule.len === 'number'; + var min = typeof rule.min === 'number'; + var max = typeof rule.max === 'number'; // 正则匹配码点范围从U+010000一直到U+10FFFF的文字(补充平面Supplementary Plane) + + var spRegexp = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g; + var val = value; + var key = null; + var num = typeof value === 'number'; + var str = typeof value === 'string'; + var arr = Array.isArray(value); + + if (num) { + key = 'number'; + } else if (str) { + key = 'string'; + } else if (arr) { + key = 'array'; + } // if the value is not of a supported type for range validation + // the validation rule rule should use the + // type property to also test for a particular type + + + if (!key) { + return false; + } + + if (arr) { + val = value.length; + } + + if (str) { + // 处理码点大于U+010000的文字length属性不准确的bug,如"𠮷𠮷𠮷".length !== 3 + val = value.replace(spRegexp, '_').length; + } + + if (len) { + if (val !== rule.len) { + errors.push(format(options.messages[key].len, rule.fullField, rule.len)); + } + } else if (min && !max && val < rule.min) { + errors.push(format(options.messages[key].min, rule.fullField, rule.min)); + } else if (max && !min && val > rule.max) { + errors.push(format(options.messages[key].max, rule.fullField, rule.max)); + } else if (min && max && (val < rule.min || val > rule.max)) { + errors.push(format(options.messages[key].range, rule.fullField, rule.min, rule.max)); + } +} + +var ENUM = 'enum'; +/** + * Rule for validating a value exists in an enumerable list. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param source The source object being validated. + * @param errors An array of errors that this rule may add + * validation errors to. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function enumerable(rule, value, source, errors, options) { + rule[ENUM] = Array.isArray(rule[ENUM]) ? rule[ENUM] : []; + + if (rule[ENUM].indexOf(value) === -1) { + errors.push(format(options.messages[ENUM], rule.fullField, rule[ENUM].join(', '))); + } +} + +/** + * Rule for validating a regular expression pattern. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param source The source object being validated. + * @param errors An array of errors that this rule may add + * validation errors to. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function pattern$1(rule, value, source, errors, options) { + if (rule.pattern) { + if (rule.pattern instanceof RegExp) { + // if a RegExp instance is passed, reset `lastIndex` in case its `global` + // flag is accidentally set to `true`, which in a validation scenario + // is not necessary and the result might be misleading + rule.pattern.lastIndex = 0; + + if (!rule.pattern.test(value)) { + errors.push(format(options.messages.pattern.mismatch, rule.fullField, value, rule.pattern)); + } + } else if (typeof rule.pattern === 'string') { + var _pattern = new RegExp(rule.pattern); + + if (!_pattern.test(value)) { + errors.push(format(options.messages.pattern.mismatch, rule.fullField, value, rule.pattern)); + } + } + } +} + +var rules = { + required: required, + whitespace: whitespace, + type: type, + range: range, + "enum": enumerable, + pattern: pattern$1 +}; + +/** + * Performs validation for string types. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function string(rule, value, callback, source, options) { + var errors = []; + var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field); + + if (validate) { + if (isEmptyValue(value, 'string') && !rule.required) { + return callback(); + } + + rules.required(rule, value, source, errors, options, 'string'); + + if (!isEmptyValue(value, 'string')) { + rules.type(rule, value, source, errors, options); + rules.range(rule, value, source, errors, options); + rules.pattern(rule, value, source, errors, options); + + if (rule.whitespace === true) { + rules.whitespace(rule, value, source, errors, options); + } + } + } + + callback(errors); +} + +/** + * Validates a function. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function method(rule, value, callback, source, options) { + var errors = []; + var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field); + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback(); + } + + rules.required(rule, value, source, errors, options); + + if (value !== undefined) { + rules.type(rule, value, source, errors, options); + } + } + + callback(errors); +} + +/** + * Validates a number. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function number(rule, value, callback, source, options) { + var errors = []; + var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field); + + if (validate) { + if (value === '') { + value = undefined; + } + + if (isEmptyValue(value) && !rule.required) { + return callback(); + } + + rules.required(rule, value, source, errors, options); + + if (value !== undefined) { + rules.type(rule, value, source, errors, options); + rules.range(rule, value, source, errors, options); + } + } + + callback(errors); +} + +/** + * Validates a boolean. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function _boolean(rule, value, callback, source, options) { + var errors = []; + var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field); + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback(); + } + + rules.required(rule, value, source, errors, options); + + if (value !== undefined) { + rules.type(rule, value, source, errors, options); + } + } + + callback(errors); +} + +/** + * Validates the regular expression type. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function regexp(rule, value, callback, source, options) { + var errors = []; + var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field); + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback(); + } + + rules.required(rule, value, source, errors, options); + + if (!isEmptyValue(value)) { + rules.type(rule, value, source, errors, options); + } + } + + callback(errors); +} + +/** + * Validates a number is an integer. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function integer(rule, value, callback, source, options) { + var errors = []; + var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field); + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback(); + } + + rules.required(rule, value, source, errors, options); + + if (value !== undefined) { + rules.type(rule, value, source, errors, options); + rules.range(rule, value, source, errors, options); + } + } + + callback(errors); +} + +/** + * Validates a number is a floating point number. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function floatFn(rule, value, callback, source, options) { + var errors = []; + var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field); + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback(); + } + + rules.required(rule, value, source, errors, options); + + if (value !== undefined) { + rules.type(rule, value, source, errors, options); + rules.range(rule, value, source, errors, options); + } + } + + callback(errors); +} + +/** + * Validates an array. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function array(rule, value, callback, source, options) { + var errors = []; + var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field); + + if (validate) { + if (isEmptyValue(value, 'array') && !rule.required) { + return callback(); + } + + rules.required(rule, value, source, errors, options, 'array'); + + if (!isEmptyValue(value, 'array')) { + rules.type(rule, value, source, errors, options); + rules.range(rule, value, source, errors, options); + } + } + + callback(errors); +} + +/** + * Validates an object. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function object(rule, value, callback, source, options) { + var errors = []; + var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field); + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback(); + } + + rules.required(rule, value, source, errors, options); + + if (value !== undefined) { + rules.type(rule, value, source, errors, options); + } + } + + callback(errors); +} + +var ENUM$1 = 'enum'; +/** + * Validates an enumerable list. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function enumerable$1(rule, value, callback, source, options) { + var errors = []; + var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field); + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback(); + } + + rules.required(rule, value, source, errors, options); + + if (value !== undefined) { + rules[ENUM$1](rule, value, source, errors, options); + } + } + + callback(errors); +} + +/** + * Validates a regular expression pattern. + * + * Performs validation when a rule only contains + * a pattern property but is not declared as a string type. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function pattern$2(rule, value, callback, source, options) { + var errors = []; + var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field); + + if (validate) { + if (isEmptyValue(value, 'string') && !rule.required) { + return callback(); + } + + rules.required(rule, value, source, errors, options); + + if (!isEmptyValue(value, 'string')) { + rules.pattern(rule, value, source, errors, options); + } + } + + callback(errors); +} + +function date(rule, value, callback, source, options) { + var errors = []; + var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field); + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback(); + } + + rules.required(rule, value, source, errors, options); + + if (!isEmptyValue(value)) { + var dateObject; + + if (typeof value === 'number') { + dateObject = new Date(value); + } else { + dateObject = value; + } + + rules.type(rule, dateObject, source, errors, options); + + if (dateObject) { + rules.range(rule, dateObject.getTime(), source, errors, options); + } + } + } + + callback(errors); +} + +function required$1(rule, value, callback, source, options) { + var errors = []; + var type = Array.isArray(value) ? 'array' : typeof value; + rules.required(rule, value, source, errors, options, type); + callback(errors); +} + +function type$1(rule, value, callback, source, options) { + var ruleType = rule.type; + var errors = []; + var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field); + + if (validate) { + if (isEmptyValue(value, ruleType) && !rule.required) { + return callback(); + } + + rules.required(rule, value, source, errors, options, ruleType); + + if (!isEmptyValue(value, ruleType)) { + rules.type(rule, value, source, errors, options); + } + } + + callback(errors); +} + +/** + * Performs validation for any type. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function any(rule, value, callback, source, options) { + var errors = []; + var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field); + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback(); + } + + rules.required(rule, value, source, errors, options); + } + + callback(errors); +} + +var validators = { + string: string, + method: method, + number: number, + "boolean": _boolean, + regexp: regexp, + integer: integer, + "float": floatFn, + array: array, + object: object, + "enum": enumerable$1, + pattern: pattern$2, + date: date, + url: type$1, + hex: type$1, + email: type$1, + required: required$1, + any: any +}; + +function newMessages() { + return { + "default": 'Validation error on field %s', + required: '%s is required', + "enum": '%s must be one of %s', + whitespace: '%s cannot be empty', + date: { + format: '%s date %s is invalid for format %s', + parse: '%s date could not be parsed, %s is invalid ', + invalid: '%s date %s is invalid' + }, + types: { + string: '%s is not a %s', + method: '%s is not a %s (function)', + array: '%s is not an %s', + object: '%s is not an %s', + number: '%s is not a %s', + date: '%s is not a %s', + "boolean": '%s is not a %s', + integer: '%s is not an %s', + "float": '%s is not a %s', + regexp: '%s is not a valid %s', + email: '%s is not a valid %s', + url: '%s is not a valid %s', + hex: '%s is not a valid %s' + }, + string: { + len: '%s must be exactly %s characters', + min: '%s must be at least %s characters', + max: '%s cannot be longer than %s characters', + range: '%s must be between %s and %s characters' + }, + number: { + len: '%s must equal %s', + min: '%s cannot be less than %s', + max: '%s cannot be greater than %s', + range: '%s must be between %s and %s' + }, + array: { + len: '%s must be exactly %s in length', + min: '%s cannot be less than %s in length', + max: '%s cannot be greater than %s in length', + range: '%s must be between %s and %s in length' + }, + pattern: { + mismatch: '%s value %s does not match pattern %s' + }, + clone: function clone() { + var cloned = JSON.parse(JSON.stringify(this)); + cloned.clone = this.clone; + return cloned; + } + }; +} +var messages = newMessages(); + +/** + * Encapsulates a validation schema. + * + * @param descriptor An object declaring validation rules + * for this schema. + */ + +function Schema(descriptor) { + this.rules = null; + this._messages = messages; + this.define(descriptor); +} + +Schema.prototype = { + messages: function messages(_messages) { + if (_messages) { + this._messages = deepMerge(newMessages(), _messages); + } + + return this._messages; + }, + define: function define(rules) { + if (!rules) { + throw new Error('Cannot configure a schema with no rules'); + } + + if (typeof rules !== 'object' || Array.isArray(rules)) { + throw new Error('Rules must be an object'); + } + + this.rules = {}; + var z; + var item; + + for (z in rules) { + if (rules.hasOwnProperty(z)) { + item = rules[z]; + this.rules[z] = Array.isArray(item) ? item : [item]; + } + } + }, + validate: function validate(source_, o, oc) { + var _this = this; + + if (o === void 0) { + o = {}; + } + + if (oc === void 0) { + oc = function oc() {}; + } + + var source = source_; + var options = o; + var callback = oc; + + if (typeof options === 'function') { + callback = options; + options = {}; + } + + if (!this.rules || Object.keys(this.rules).length === 0) { + if (callback) { + callback(); + } + + return Promise.resolve(); + } + + function complete(results) { + var i; + var errors = []; + var fields = {}; + + function add(e) { + if (Array.isArray(e)) { + var _errors; + + errors = (_errors = errors).concat.apply(_errors, e); + } else { + errors.push(e); + } + } + + for (i = 0; i < results.length; i++) { + add(results[i]); + } + + if (!errors.length) { + errors = null; + fields = null; + } else { + fields = convertFieldsError(errors); + } + + callback(errors, fields); + } + + if (options.messages) { + var messages$1 = this.messages(); + + if (messages$1 === messages) { + messages$1 = newMessages(); + } + + deepMerge(messages$1, options.messages); + options.messages = messages$1; + } else { + options.messages = this.messages(); + } + + var arr; + var value; + var series = {}; + var keys = options.keys || Object.keys(this.rules); + keys.forEach(function(z) { + arr = _this.rules[z]; + value = source[z]; + arr.forEach(function(r) { + var rule = r; + + if (typeof rule.transform === 'function') { + if (source === source_) { + source = _extends({}, source); + } + + value = source[z] = rule.transform(value); + } + + if (typeof rule === 'function') { + rule = { + validator: rule + }; + } else { + rule = _extends({}, rule); + } + + rule.validator = _this.getValidationMethod(rule); + rule.field = z; + rule.fullField = rule.fullField || z; + rule.type = _this.getType(rule); + + if (!rule.validator) { + return; + } + + series[z] = series[z] || []; + series[z].push({ + rule: rule, + value: value, + source: source, + field: z + }); + }); + }); + var errorFields = {}; + return asyncMap(series, options, function(data, doIt) { + var rule = data.rule; + var deep = (rule.type === 'object' || rule.type === 'array') && (typeof rule.fields === 'object' || typeof rule.defaultField === + 'object'); + deep = deep && (rule.required || !rule.required && data.value); + rule.field = data.field; + + function addFullfield(key, schema) { + return _extends({}, schema, { + fullField: rule.fullField + "." + key + }); + } + + function cb(e) { + if (e === void 0) { + e = []; + } + + var errors = e; + + if (!Array.isArray(errors)) { + errors = [errors]; + } + + if (!options.suppressWarning && errors.length) { + Schema.warning('async-validator:', errors); + } + + if (errors.length && rule.message) { + errors = [].concat(rule.message); + } + + errors = errors.map(complementError(rule)); + + if (options.first && errors.length) { + errorFields[rule.field] = 1; + return doIt(errors); + } + + if (!deep) { + doIt(errors); + } else { + // if rule is required but the target object + // does not exist fail at the rule level and don't + // go deeper + if (rule.required && !data.value) { + if (rule.message) { + errors = [].concat(rule.message).map(complementError(rule)); + } else if (options.error) { + errors = [options.error(rule, format(options.messages.required, rule.field))]; + } else { + errors = []; + } + + return doIt(errors); + } + + var fieldsSchema = {}; + + if (rule.defaultField) { + for (var k in data.value) { + if (data.value.hasOwnProperty(k)) { + fieldsSchema[k] = rule.defaultField; + } + } + } + + fieldsSchema = _extends({}, fieldsSchema, {}, data.rule.fields); + + for (var f in fieldsSchema) { + if (fieldsSchema.hasOwnProperty(f)) { + var fieldSchema = Array.isArray(fieldsSchema[f]) ? fieldsSchema[f] : [fieldsSchema[f]]; + fieldsSchema[f] = fieldSchema.map(addFullfield.bind(null, f)); + } + } + + var schema = new Schema(fieldsSchema); + schema.messages(options.messages); + + if (data.rule.options) { + data.rule.options.messages = options.messages; + data.rule.options.error = options.error; + } + + schema.validate(data.value, data.rule.options || options, function(errs) { + var finalErrors = []; + + if (errors && errors.length) { + finalErrors.push.apply(finalErrors, errors); + } + + if (errs && errs.length) { + finalErrors.push.apply(finalErrors, errs); + } + + doIt(finalErrors.length ? finalErrors : null); + }); + } + } + + var res; + + if (rule.asyncValidator) { + res = rule.asyncValidator(rule, data.value, cb, data.source, options); + } else if (rule.validator) { + res = rule.validator(rule, data.value, cb, data.source, options); + + if (res === true) { + cb(); + } else if (res === false) { + cb(rule.message || rule.field + " fails"); + } else if (res instanceof Array) { + cb(res); + } else if (res instanceof Error) { + cb(res.message); + } + } + + if (res && res.then) { + res.then(function() { + return cb(); + }, function(e) { + return cb(e); + }); + } + }, function(results) { + complete(results); + }); + }, + getType: function getType(rule) { + if (rule.type === undefined && rule.pattern instanceof RegExp) { + rule.type = 'pattern'; + } + + if (typeof rule.validator !== 'function' && rule.type && !validators.hasOwnProperty(rule.type)) { + throw new Error(format('Unknown rule type %s', rule.type)); + } + + return rule.type || 'string'; + }, + getValidationMethod: function getValidationMethod(rule) { + if (typeof rule.validator === 'function') { + return rule.validator; + } + + var keys = Object.keys(rule); + var messageIndex = keys.indexOf('message'); + + if (messageIndex !== -1) { + keys.splice(messageIndex, 1); + } + + if (keys.length === 1 && keys[0] === 'required') { + return validators.required; + } + + return validators[this.getType(rule)] || false; + } +}; + +Schema.register = function register(type, validator) { + if (typeof validator !== 'function') { + throw new Error('Cannot register a validator by type, validator is not a function'); + } + + validators[type] = validator; +}; + +Schema.warning = warning; +Schema.messages = messages; + +export default Schema; +//# sourceMappingURL=index.js.map diff --git a/libs/util/city.js b/libs/util/city.js new file mode 100644 index 0000000..94169eb --- /dev/null +++ b/libs/util/city.js @@ -0,0 +1 @@ +var cityData=[[{"label":"市辖区","value":"1101"}],[{"label":"市辖区","value":"1201"}],[{"label":"石家庄市","value":"1301"},{"label":"唐山市","value":"1302"},{"label":"秦皇岛市","value":"1303"},{"label":"邯郸市","value":"1304"},{"label":"邢台市","value":"1305"},{"label":"保定市","value":"1306"},{"label":"张家口市","value":"1307"},{"label":"承德市","value":"1308"},{"label":"沧州市","value":"1309"},{"label":"廊坊市","value":"1310"},{"label":"衡水市","value":"1311"}],[{"label":"太原市","value":"1401"},{"label":"大同市","value":"1402"},{"label":"阳泉市","value":"1403"},{"label":"长治市","value":"1404"},{"label":"晋城市","value":"1405"},{"label":"朔州市","value":"1406"},{"label":"晋中市","value":"1407"},{"label":"运城市","value":"1408"},{"label":"忻州市","value":"1409"},{"label":"临汾市","value":"1410"},{"label":"吕梁市","value":"1411"}],[{"label":"呼和浩特市","value":"1501"},{"label":"包头市","value":"1502"},{"label":"乌海市","value":"1503"},{"label":"赤峰市","value":"1504"},{"label":"通辽市","value":"1505"},{"label":"鄂尔多斯市","value":"1506"},{"label":"呼伦贝尔市","value":"1507"},{"label":"巴彦淖尔市","value":"1508"},{"label":"乌兰察布市","value":"1509"},{"label":"兴安盟","value":"1522"},{"label":"锡林郭勒盟","value":"1525"},{"label":"阿拉善盟","value":"1529"}],[{"label":"沈阳市","value":"2101"},{"label":"大连市","value":"2102"},{"label":"鞍山市","value":"2103"},{"label":"抚顺市","value":"2104"},{"label":"本溪市","value":"2105"},{"label":"丹东市","value":"2106"},{"label":"锦州市","value":"2107"},{"label":"营口市","value":"2108"},{"label":"阜新市","value":"2109"},{"label":"辽阳市","value":"2110"},{"label":"盘锦市","value":"2111"},{"label":"铁岭市","value":"2112"},{"label":"朝阳市","value":"2113"},{"label":"葫芦岛市","value":"2114"}],[{"label":"长春市","value":"2201"},{"label":"吉林市","value":"2202"},{"label":"四平市","value":"2203"},{"label":"辽源市","value":"2204"},{"label":"通化市","value":"2205"},{"label":"白山市","value":"2206"},{"label":"松原市","value":"2207"},{"label":"白城市","value":"2208"},{"label":"延边朝鲜族自治州","value":"2224"}],[{"label":"哈尔滨市","value":"2301"},{"label":"齐齐哈尔市","value":"2302"},{"label":"鸡西市","value":"2303"},{"label":"鹤岗市","value":"2304"},{"label":"双鸭山市","value":"2305"},{"label":"大庆市","value":"2306"},{"label":"伊春市","value":"2307"},{"label":"佳木斯市","value":"2308"},{"label":"七台河市","value":"2309"},{"label":"牡丹江市","value":"2310"},{"label":"黑河市","value":"2311"},{"label":"绥化市","value":"2312"},{"label":"大兴安岭地区","value":"2327"}],[{"label":"市辖区","value":"3101"}],[{"label":"南京市","value":"3201"},{"label":"无锡市","value":"3202"},{"label":"徐州市","value":"3203"},{"label":"常州市","value":"3204"},{"label":"苏州市","value":"3205"},{"label":"南通市","value":"3206"},{"label":"连云港市","value":"3207"},{"label":"淮安市","value":"3208"},{"label":"盐城市","value":"3209"},{"label":"扬州市","value":"3210"},{"label":"镇江市","value":"3211"},{"label":"泰州市","value":"3212"},{"label":"宿迁市","value":"3213"}],[{"label":"杭州市","value":"3301"},{"label":"宁波市","value":"3302"},{"label":"温州市","value":"3303"},{"label":"嘉兴市","value":"3304"},{"label":"湖州市","value":"3305"},{"label":"绍兴市","value":"3306"},{"label":"金华市","value":"3307"},{"label":"衢州市","value":"3308"},{"label":"舟山市","value":"3309"},{"label":"台州市","value":"3310"},{"label":"丽水市","value":"3311"}],[{"label":"合肥市","value":"3401"},{"label":"芜湖市","value":"3402"},{"label":"蚌埠市","value":"3403"},{"label":"淮南市","value":"3404"},{"label":"马鞍山市","value":"3405"},{"label":"淮北市","value":"3406"},{"label":"铜陵市","value":"3407"},{"label":"安庆市","value":"3408"},{"label":"黄山市","value":"3410"},{"label":"滁州市","value":"3411"},{"label":"阜阳市","value":"3412"},{"label":"宿州市","value":"3413"},{"label":"六安市","value":"3415"},{"label":"亳州市","value":"3416"},{"label":"池州市","value":"3417"},{"label":"宣城市","value":"3418"}],[{"label":"福州市","value":"3501"},{"label":"厦门市","value":"3502"},{"label":"莆田市","value":"3503"},{"label":"三明市","value":"3504"},{"label":"泉州市","value":"3505"},{"label":"漳州市","value":"3506"},{"label":"南平市","value":"3507"},{"label":"龙岩市","value":"3508"},{"label":"宁德市","value":"3509"}],[{"label":"南昌市","value":"3601"},{"label":"景德镇市","value":"3602"},{"label":"萍乡市","value":"3603"},{"label":"九江市","value":"3604"},{"label":"新余市","value":"3605"},{"label":"鹰潭市","value":"3606"},{"label":"赣州市","value":"3607"},{"label":"吉安市","value":"3608"},{"label":"宜春市","value":"3609"},{"label":"抚州市","value":"3610"},{"label":"上饶市","value":"3611"}],[{"label":"济南市","value":"3701"},{"label":"青岛市","value":"3702"},{"label":"淄博市","value":"3703"},{"label":"枣庄市","value":"3704"},{"label":"东营市","value":"3705"},{"label":"烟台市","value":"3706"},{"label":"潍坊市","value":"3707"},{"label":"济宁市","value":"3708"},{"label":"泰安市","value":"3709"},{"label":"威海市","value":"3710"},{"label":"日照市","value":"3711"},{"label":"莱芜市","value":"3712"},{"label":"临沂市","value":"3713"},{"label":"德州市","value":"3714"},{"label":"聊城市","value":"3715"},{"label":"滨州市","value":"3716"},{"label":"菏泽市","value":"3717"}],[{"label":"郑州市","value":"4101"},{"label":"开封市","value":"4102"},{"label":"洛阳市","value":"4103"},{"label":"平顶山市","value":"4104"},{"label":"安阳市","value":"4105"},{"label":"鹤壁市","value":"4106"},{"label":"新乡市","value":"4107"},{"label":"焦作市","value":"4108"},{"label":"濮阳市","value":"4109"},{"label":"许昌市","value":"4110"},{"label":"漯河市","value":"4111"},{"label":"三门峡市","value":"4112"},{"label":"南阳市","value":"4113"},{"label":"商丘市","value":"4114"},{"label":"信阳市","value":"4115"},{"label":"周口市","value":"4116"},{"label":"驻马店市","value":"4117"},{"label":"省直辖县级行政区划","value":"4190"}],[{"label":"武汉市","value":"4201"},{"label":"黄石市","value":"4202"},{"label":"十堰市","value":"4203"},{"label":"宜昌市","value":"4205"},{"label":"襄阳市","value":"4206"},{"label":"鄂州市","value":"4207"},{"label":"荆门市","value":"4208"},{"label":"孝感市","value":"4209"},{"label":"荆州市","value":"4210"},{"label":"黄冈市","value":"4211"},{"label":"咸宁市","value":"4212"},{"label":"随州市","value":"4213"},{"label":"恩施土家族苗族自治州","value":"4228"},{"label":"省直辖县级行政区划","value":"4290"}],[{"label":"长沙市","value":"4301"},{"label":"株洲市","value":"4302"},{"label":"湘潭市","value":"4303"},{"label":"衡阳市","value":"4304"},{"label":"邵阳市","value":"4305"},{"label":"岳阳市","value":"4306"},{"label":"常德市","value":"4307"},{"label":"张家界市","value":"4308"},{"label":"益阳市","value":"4309"},{"label":"郴州市","value":"4310"},{"label":"永州市","value":"4311"},{"label":"怀化市","value":"4312"},{"label":"娄底市","value":"4313"},{"label":"湘西土家族苗族自治州","value":"4331"}],[{"label":"广州市","value":"4401"},{"label":"韶关市","value":"4402"},{"label":"深圳市","value":"4403"},{"label":"珠海市","value":"4404"},{"label":"汕头市","value":"4405"},{"label":"佛山市","value":"4406"},{"label":"江门市","value":"4407"},{"label":"湛江市","value":"4408"},{"label":"茂名市","value":"4409"},{"label":"肇庆市","value":"4412"},{"label":"惠州市","value":"4413"},{"label":"梅州市","value":"4414"},{"label":"汕尾市","value":"4415"},{"label":"河源市","value":"4416"},{"label":"阳江市","value":"4417"},{"label":"清远市","value":"4418"},{"label":"东莞市","value":"4419"},{"label":"中山市","value":"4420"},{"label":"潮州市","value":"4451"},{"label":"揭阳市","value":"4452"},{"label":"云浮市","value":"4453"}],[{"label":"南宁市","value":"4501"},{"label":"柳州市","value":"4502"},{"label":"桂林市","value":"4503"},{"label":"梧州市","value":"4504"},{"label":"北海市","value":"4505"},{"label":"防城港市","value":"4506"},{"label":"钦州市","value":"4507"},{"label":"贵港市","value":"4508"},{"label":"玉林市","value":"4509"},{"label":"百色市","value":"4510"},{"label":"贺州市","value":"4511"},{"label":"河池市","value":"4512"},{"label":"来宾市","value":"4513"},{"label":"崇左市","value":"4514"}],[{"label":"海口市","value":"4601"},{"label":"三亚市","value":"4602"},{"label":"三沙市","value":"4603"},{"label":"儋州市","value":"4604"},{"label":"省直辖县级行政区划","value":"4690"}],[{"label":"市辖区","value":"5001"},{"label":"县","value":"5002"}],[{"label":"成都市","value":"5101"},{"label":"自贡市","value":"5103"},{"label":"攀枝花市","value":"5104"},{"label":"泸州市","value":"5105"},{"label":"德阳市","value":"5106"},{"label":"绵阳市","value":"5107"},{"label":"广元市","value":"5108"},{"label":"遂宁市","value":"5109"},{"label":"内江市","value":"5110"},{"label":"乐山市","value":"5111"},{"label":"南充市","value":"5113"},{"label":"眉山市","value":"5114"},{"label":"宜宾市","value":"5115"},{"label":"广安市","value":"5116"},{"label":"达州市","value":"5117"},{"label":"雅安市","value":"5118"},{"label":"巴中市","value":"5119"},{"label":"资阳市","value":"5120"},{"label":"阿坝藏族羌族自治州","value":"5132"},{"label":"甘孜藏族自治州","value":"5133"},{"label":"凉山彝族自治州","value":"5134"}],[{"label":"贵阳市","value":"5201"},{"label":"六盘水市","value":"5202"},{"label":"遵义市","value":"5203"},{"label":"安顺市","value":"5204"},{"label":"毕节市","value":"5205"},{"label":"铜仁市","value":"5206"},{"label":"黔西南布依族苗族自治州","value":"5223"},{"label":"黔东南苗族侗族自治州","value":"5226"},{"label":"黔南布依族苗族自治州","value":"5227"}],[{"label":"昆明市","value":"5301"},{"label":"曲靖市","value":"5303"},{"label":"玉溪市","value":"5304"},{"label":"保山市","value":"5305"},{"label":"昭通市","value":"5306"},{"label":"丽江市","value":"5307"},{"label":"普洱市","value":"5308"},{"label":"临沧市","value":"5309"},{"label":"楚雄彝族自治州","value":"5323"},{"label":"红河哈尼族彝族自治州","value":"5325"},{"label":"文山壮族苗族自治州","value":"5326"},{"label":"西双版纳傣族自治州","value":"5328"},{"label":"大理白族自治州","value":"5329"},{"label":"德宏傣族景颇族自治州","value":"5331"},{"label":"怒江傈僳族自治州","value":"5333"},{"label":"迪庆藏族自治州","value":"5334"}],[{"label":"拉萨市","value":"5401"},{"label":"日喀则市","value":"5402"},{"label":"昌都市","value":"5403"},{"label":"林芝市","value":"5404"},{"label":"山南市","value":"5405"},{"label":"那曲地区","value":"5424"},{"label":"阿里地区","value":"5425"}],[{"label":"西安市","value":"6101"},{"label":"铜川市","value":"6102"},{"label":"宝鸡市","value":"6103"},{"label":"咸阳市","value":"6104"},{"label":"渭南市","value":"6105"},{"label":"延安市","value":"6106"},{"label":"汉中市","value":"6107"},{"label":"榆林市","value":"6108"},{"label":"安康市","value":"6109"},{"label":"商洛市","value":"6110"}],[{"label":"兰州市","value":"6201"},{"label":"嘉峪关市","value":"6202"},{"label":"金昌市","value":"6203"},{"label":"白银市","value":"6204"},{"label":"天水市","value":"6205"},{"label":"武威市","value":"6206"},{"label":"张掖市","value":"6207"},{"label":"平凉市","value":"6208"},{"label":"酒泉市","value":"6209"},{"label":"庆阳市","value":"6210"},{"label":"定西市","value":"6211"},{"label":"陇南市","value":"6212"},{"label":"临夏回族自治州","value":"6229"},{"label":"甘南藏族自治州","value":"6230"}],[{"label":"西宁市","value":"6301"},{"label":"海东市","value":"6302"},{"label":"海北藏族自治州","value":"6322"},{"label":"黄南藏族自治州","value":"6323"},{"label":"海南藏族自治州","value":"6325"},{"label":"果洛藏族自治州","value":"6326"},{"label":"玉树藏族自治州","value":"6327"},{"label":"海西蒙古族藏族自治州","value":"6328"}],[{"label":"银川市","value":"6401"},{"label":"石嘴山市","value":"6402"},{"label":"吴忠市","value":"6403"},{"label":"固原市","value":"6404"},{"label":"中卫市","value":"6405"}],[{"label":"乌鲁木齐市","value":"6501"},{"label":"克拉玛依市","value":"6502"},{"label":"吐鲁番市","value":"6504"},{"label":"哈密市","value":"6505"},{"label":"昌吉回族自治州","value":"6523"},{"label":"博尔塔拉蒙古自治州","value":"6527"},{"label":"巴音郭楞蒙古自治州","value":"6528"},{"label":"阿克苏地区","value":"6529"},{"label":"克孜勒苏柯尔克孜自治州","value":"6530"},{"label":"喀什地区","value":"6531"},{"label":"和田地区","value":"6532"},{"label":"伊犁哈萨克自治州","value":"6540"},{"label":"塔城地区","value":"6542"},{"label":"阿勒泰地区","value":"6543"},{"label":"自治区直辖县级行政区划","value":"6590"}],[{"label":"台北","value":"6601"},{"label":"高雄","value":"6602"},{"label":"基隆","value":"6603"},{"label":"台中","value":"6604"},{"label":"台南","value":"6605"},{"label":"新竹","value":"6606"},{"label":"嘉义","value":"6607"},{"label":"宜兰","value":"6608"},{"label":"桃园","value":"6609"},{"label":"苗栗","value":"6610"},{"label":"彰化","value":"6611"},{"label":"南投","value":"6612"},{"label":"云林","value":"6613"},{"label":"屏东","value":"6614"},{"label":"台东","value":"6615"},{"label":"花莲","value":"6616"},{"label":"澎湖","value":"6617"}],[{"label":"香港岛","value":"6701"},{"label":"九龙","value":"6702"},{"label":"新界","value":"6703"}],[{"label":"澳门半岛","value":"6801"},{"label":"氹仔岛","value":"6802"},{"label":"路环岛","value":"6803"},{"label":"路氹城","value":"6804"}]];export default cityData; \ No newline at end of file diff --git a/libs/util/emitter.js b/libs/util/emitter.js new file mode 100644 index 0000000..228016e --- /dev/null +++ b/libs/util/emitter.js @@ -0,0 +1,51 @@ +/** + * 递归使用 call 方式this指向 + * @param componentName // 需要找的组件的名称 + * @param eventName // 事件名称 + * @param params // 需要传递的参数 + */ +function broadcast(componentName, eventName, params) { + // 循环子节点找到名称一样的子节点 否则 递归 当前子节点 + this.$children.map(child=>{ + if (componentName===child.$options.name) { + child.$emit.apply(child,[eventName].concat(params)) + }else { + broadcast.apply(child,[componentName,eventName].concat(params)) + } + }) +} +export default { + methods: { + /** + * 派发 (向上查找) (一个) + * @param componentName // 需要找的组件的名称 + * @param eventName // 事件名称 + * @param params // 需要传递的参数 + */ + dispatch(componentName, eventName, params) { + let parent = this.$parent || this.$root;//$parent 找到最近的父节点 $root 根节点 + let name = parent.$options.name; // 获取当前组件实例的name + // 如果当前有节点 && 当前没名称 且 当前名称等于需要传进来的名称的时候就去查找当前的节点 + // 循环出当前名称的一样的组件实例 + while (parent && (!name||name!==componentName)) { + parent = parent.$parent; + if (parent) { + name = parent.$options.name; + } + } + // 有节点表示当前找到了name一样的实例 + if (parent) { + parent.$emit.apply(parent,[eventName].concat(params)) + } + }, + /** + * 广播 (向下查找) (广播多个) + * @param componentName // 需要找的组件的名称 + * @param eventName // 事件名称 + * @param params // 需要传递的参数 + */ + broadcast(componentName, eventName, params) { + broadcast.call(this,componentName, eventName, params) + } + } +} diff --git a/libs/util/province.js b/libs/util/province.js new file mode 100644 index 0000000..436b190 --- /dev/null +++ b/libs/util/province.js @@ -0,0 +1 @@ +var provinceData=[{"label":"北京市","value":"11"},{"label":"天津市","value":"12"},{"label":"河北省","value":"13"},{"label":"山西省","value":"14"},{"label":"内蒙古自治区","value":"15"},{"label":"辽宁省","value":"21"},{"label":"吉林省","value":"22"},{"label":"黑龙江省","value":"23"},{"label":"上海市","value":"31"},{"label":"江苏省","value":"32"},{"label":"浙江省","value":"33"},{"label":"安徽省","value":"34"},{"label":"福建省","value":"35"},{"label":"江西省","value":"36"},{"label":"山东省","value":"37"},{"label":"河南省","value":"41"},{"label":"湖北省","value":"42"},{"label":"湖南省","value":"43"},{"label":"广东省","value":"44"},{"label":"广西壮族自治区","value":"45"},{"label":"海南省","value":"46"},{"label":"重庆市","value":"50"},{"label":"四川省","value":"51"},{"label":"贵州省","value":"52"},{"label":"云南省","value":"53"},{"label":"西藏自治区","value":"54"},{"label":"陕西省","value":"61"},{"label":"甘肃省","value":"62"},{"label":"青海省","value":"63"},{"label":"宁夏回族自治区","value":"64"},{"label":"新疆维吾尔自治区","value":"65"},{"label":"台湾","value":"66"},{"label":"香港","value":"67"},{"label":"澳门","value":"68"}];export default provinceData; \ No newline at end of file diff --git a/main.js b/main.js new file mode 100644 index 0000000..74eb213 --- /dev/null +++ b/main.js @@ -0,0 +1,28 @@ +import App from './App' +import store from './store' + + +// #ifndef VUE3 +import Vue from 'vue' +Vue.prototype.$store = store +import uView from "uview-ui"; +Vue.use(uView); + +Vue.config.productionTip = false +App.mpType = 'app' +const app = new Vue({ + store, + ...App +}) +app.$mount() +// #endif + +// #ifdef VUE3 +import { createSSRApp } from '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..ffdf153 --- /dev/null +++ b/manifest.json @@ -0,0 +1,97 @@ +{ + "name" : "经纬度上传", + "appid" : "__UNI__D070EBB", + "description" : "", + "versionName" : "1.0.0", + "versionCode" : 101, + "transformPx" : false, + /* 5+App特有相关 */ + "app-plus" : { + "usingComponents" : true, + "nvueStyleCompiler" : "uni-app", + "compilerVersion" : 3, + "splashscreen" : { + "alwaysShowBeforeRender" : true, + "waiting" : true, + "autoclose" : true, + "delay" : 0 + }, + /* 模块配置 */ + "modules" : { + "Maps" : {}, + "Geolocation" : {} + }, + /* 应用发布信息 */ + "distribute" : { + /* android打包配置 */ + "android" : { + "permissions" : [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ] + }, + /* ios打包配置 */ + "ios" : {}, + /* SDK配置 */ + "sdkConfigs" : { + "geolocation" : { + "amap" : { + "__platform__" : [ "ios", "android" ], + "appkey_ios" : "6afc5834f157391fb71ea8c11b89308f", + "appkey_android" : "6afc5834f157391fb71ea8c11b89308f" + } + }, + "ad" : {}, + "maps" : { + "amap" : { + "appkey_ios" : "6afc5834f157391fb71ea8c11b89308f", + "appkey_android" : "6afc5834f157391fb71ea8c11b89308f" + } + } + } + } + }, + /* 快应用特有相关 */ + "quickapp" : {}, + /* 小程序特有相关 */ + "mp-weixin" : { + "appid" : "wx10a465f1cd9ec501", + "setting" : { + "urlCheck" : false + }, + "usingComponents" : true, + "permission" : { + "scope.userLocation" : { + "desc" : "获取用户位置" + } + } + }, + "mp-alipay" : { + "usingComponents" : true + }, + "mp-baidu" : { + "usingComponents" : true + }, + "mp-toutiao" : { + "usingComponents" : true + }, + "uniStatistics" : { + "enable" : false + }, + "vueVersion" : "2" +} +/* 模块配置 */ + diff --git a/package.json b/package.json new file mode 100644 index 0000000..899166d --- /dev/null +++ b/package.json @@ -0,0 +1,34 @@ +{ + "name": "uView", + "version": "1.8.6", + "description": "uView UI,是uni-app生态优秀的UI框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水", + "main": "index.js", + "keywords": [ + "uview", + "ui", + "uni-app" + ], + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "" + }, + "devDependencies": { + "node-sass": "^4.14.0", + "sass-loader": "^8.0.2" + }, + "author": "uView", + "license": "MIT", + "id": "uview-v1", + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ] + }, + "dependencies": { + "dayjs": "^1.11.3" + } +} diff --git a/pages.json b/pages.json new file mode 100644 index 0000000..18e0baf --- /dev/null +++ b/pages.json @@ -0,0 +1,35 @@ +{ + "easycom": { + "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue" + }, + "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages + { + "path": "pages/index/index", + "style": { + "navigationBarTitleText": "经纬度拾取", + "navigationStyle": "custom", // 隐藏系统导航栏 + "navigationBarTextStyle": "white" // 状态栏字体为白色,只能为 white-白色,black-黑色 二选一 + } + }, { + "path": "pages/listPage/listPage", + "style": { + "navigationBarTitleText": "设备列表", + "enablePullDownRefresh": false + } + + }, { + "path": "pages/addEquip/addEquip", + "style": { + "navigationBarTitleText": "新增设备", + "enablePullDownRefresh": false + } + + } + ], + "globalStyle": { + "navigationBarTextStyle": "black", + "navigationBarTitleText": "经纬度拾取", + "navigationBarBackgroundColor": "#F8F8F8", + "backgroundColor": "#F8F8F8" + } +} diff --git a/pages/addEquip/addEquip.vue b/pages/addEquip/addEquip.vue new file mode 100644 index 0000000..b7917dd --- /dev/null +++ b/pages/addEquip/addEquip.vue @@ -0,0 +1,291 @@ + + + + diff --git a/pages/index/index.vue b/pages/index/index.vue new file mode 100644 index 0000000..e994b48 --- /dev/null +++ b/pages/index/index.vue @@ -0,0 +1,639 @@ + + + + + diff --git a/pages/indexNvue/indexNvue.nvue b/pages/indexNvue/indexNvue.nvue new file mode 100644 index 0000000..e5944cf --- /dev/null +++ b/pages/indexNvue/indexNvue.nvue @@ -0,0 +1,24 @@ + + + + + diff --git a/pages/listPage/listPage.vue b/pages/listPage/listPage.vue new file mode 100644 index 0000000..6b01cb5 --- /dev/null +++ b/pages/listPage/listPage.vue @@ -0,0 +1,242 @@ + + + + + diff --git a/project.config.json b/project.config.json new file mode 100644 index 0000000..2df660f --- /dev/null +++ b/project.config.json @@ -0,0 +1,43 @@ +{ + "appid": "wxf073f43c226d810e", + "compileType": "miniprogram", + "libVersion": "2.24.6", + "packOptions": { + "ignore": [], + "include": [] + }, + "setting": { + "urlCheck": true, + "coverView": true, + "es6": true, + "postcss": true, + "lazyloadPlaceholderEnable": false, + "preloadBackgroundData": false, + "minified": true, + "autoAudits": false, + "uglifyFileName": false, + "uploadWithSourceMap": true, + "enhance": true, + "showShadowRootInWxmlPanel": true, + "packNpmManually": false, + "packNpmRelationList": [], + "minifyWXSS": true, + "useStaticServer": true, + "showES6CompileOption": false, + "checkInvalidKey": true, + "babelSetting": { + "ignore": [], + "disablePlugins": [], + "outputPath": "" + }, + "disableUseStrict": false, + "useCompilerPlugins": false, + "minifyWXML": true + }, + "condition": {}, + "editorSetting": { + "tabIndent": "insertSpaces", + "tabSize": 2 + }, + "description": "项目配置文件,详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html" +} \ No newline at end of file diff --git a/project.private.config.json b/project.private.config.json new file mode 100644 index 0000000..75a729f --- /dev/null +++ b/project.private.config.json @@ -0,0 +1,7 @@ +{ + "projectname": "location_point", + "setting": { + "compileHotReLoad": true + }, + "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html" +} \ No newline at end of file diff --git a/static/address_1.png b/static/address_1.png new file mode 100644 index 0000000..4f25b70 Binary files /dev/null and b/static/address_1.png differ diff --git a/static/address_2.png b/static/address_2.png new file mode 100644 index 0000000..aa74cdb Binary files /dev/null and b/static/address_2.png differ diff --git a/static/address_3.png b/static/address_3.png new file mode 100644 index 0000000..f2d395b Binary files /dev/null and b/static/address_3.png differ diff --git a/static/address_4.png b/static/address_4.png new file mode 100644 index 0000000..3d8db04 Binary files /dev/null and b/static/address_4.png differ diff --git a/static/logo.png b/static/logo.png new file mode 100644 index 0000000..b5771e2 Binary files /dev/null and b/static/logo.png differ diff --git a/store/index.js b/store/index.js new file mode 100644 index 0000000..2335526 --- /dev/null +++ b/store/index.js @@ -0,0 +1,12 @@ + // 页面路径:store/index.js + import Vue from 'vue' + import Vuex from 'vuex' + + import equip from '@/store/modules/equip' + + Vue.use(Vuex) + export default new Vuex.Store({ + modules:{ + equip + } + }) diff --git a/store/modules/equip.js b/store/modules/equip.js new file mode 100644 index 0000000..9dc4f7c --- /dev/null +++ b/store/modules/equip.js @@ -0,0 +1,149 @@ +import config from "@/libs/config/config.js" + +export default { + state: { + timestamp: 1608820295,//初始时间戳 + currentData:{ + id:null, + number:null, + type:null, + }, + currentDataDetails:{ + docId: "", + docIds:[], + latitude: "", + longitude: "", + pictureId: null, + remarks: "", + subjectId: null, + }, + oldDataDetails:{ + docId: "", + docIds:[], + latitude: "", + longitude: "", + pictureId: null, + remarks: "", + subjectId: null, + }, + }, + getters: { + timeString(state) {//时间戳转换后的时间 + var date = new Date(state.timestamp); + var year = date.getFullYear(); + var mon = date.getMonth()+1; + var day = date.getDate(); + var hours = date.getHours(); + var minu = date.getMinutes(); + var sec = date.getSeconds(); + var trMon = mon<10 ? '0'+mon : mon + var trDay = day<10 ? '0'+day : day + return year+'-'+trMon+'-'+trDay+" "+hours+":"+minu+":"+sec; + } + }, + mutations: { + updateTime(state){//更新当前时间戳 + state.timestamp = Date.now() + }, + set(state,payload){ + state.currentData=payload.data; + }, + setDtails(state,payload){ + state.currentDataDetails=payload.data; + }, + queryCurrentDataDetails(state,payload){ + console.log("==========================queryCurrentDataDetails") + console.log(state.currentData) + uni.$u.post(config.api + '/xfhrshInternet/service/selPicture', { + subjectId:state.currentData.id + }).then(res => { + console.log(typeof res) + console.log(res) + if(res.code==0){ + if(res.data.length>0){ + state.currentDataDetails=res.data[0]; + }else{ + state.currentDataDetails=state.oldDataDetails; + } + } + }); + }, + updateEquipDetails(state,payload){ + let _data=JSON.parse(JSON.stringify(payload.data)) + delete _data.number + delete _data.type + console.log(_data) + _data.subjectId=_data.id + delete _data.id + if(_data.latitude){ + _data.latitude=String(_data.latitude) + }else{ + _data.latitude=state.currentDataDetails.latitude + } + if(_data.longitude){ + _data.longitude=String(_data.longitude) + }else{ + _data.longitude=state.currentDataDetails.longitude + } + if(_data.remarks){ + + }else{ + _data.remarks=state.currentDataDetails.remarks + } + if(_data.docId){ + + }else{ + _data.docId=state.currentDataDetails.docId + } + + + console.log("=================================state.currentDataDetails") + console.log(state.currentDataDetails) + if(state.currentDataDetails){ + if(state.currentDataDetails.pictureId!=null){ + _data.pictureId=state.currentDataDetails.pictureId; + } + } + _data.subjectId=state.currentData.id + uni.$u.post(config.api + '/xfhrshInternet/service/insertPicture', _data).then(res => { + console.log(typeof res) + console.log(res) + if(res.code==0){ + uni.showToast({ + icon: "success", + title: "操作成功" + }) + uni.$emit('updateCamera', { + cameara: {} + }) + }else{ + uni.showToast({ + icon: "error", + title: res.message + }) + } + + }); + } + }, + actions: { + setCurrentEquip(context , payload){ + context.commit('set',payload) + }, + setCurrentEquipDtails(context , payload){ + context.commit('setDtails',payload) + }, + updateEquipDetails(context , payload){ + context.commit('updateEquipDetails',payload) + setTimeout(()=>{ + context.commit('queryCurrentDataDetails',payload) + },500) + }, + queryCurrentDataDetails(context , payload){ + context.commit('queryCurrentDataDetails',payload) + }, + updateCurrentDataDetails(context , payload){ + context.commit('updateCurrentDataDetails',payload) + } + } +} \ No newline at end of file diff --git a/theme.scss b/theme.scss new file mode 100644 index 0000000..f3bb36d --- /dev/null +++ b/theme.scss @@ -0,0 +1,38 @@ +// 此文件为uView的主题变量,这些变量目前只能通过uni.scss引入才有效,另外由于 +// uni.scss中引入的样式会同时混入到全局样式文件和单独每一个页面的样式中,造成微信程序包太大, +// 故uni.scss只建议放scss变量名相关样式,其他的样式可以通过main.js或者App.vue引入 + +$u-main-color: #303133; +$u-content-color: #606266; +$u-tips-color: #909399; +$u-light-color: #c0c4cc; +$u-border-color: #e4e7ed; +$u-bg-color: #f3f4f6; + +$u-type-primary: #2979ff; +$u-type-primary-light: #ecf5ff; +$u-type-primary-disabled: #a0cfff; +$u-type-primary-dark: #2b85e4; + +$u-type-warning: #ff9900; +$u-type-warning-disabled: #fcbd71; +$u-type-warning-dark: #f29100; +$u-type-warning-light: #fdf6ec; + +$u-type-success: #19be6b; +$u-type-success-disabled: #71d5a1; +$u-type-success-dark: #18b566; +$u-type-success-light: #dbf1e1; + +$u-type-error: #fa3534; +$u-type-error-disabled: #fab6b6; +$u-type-error-dark: #dd6161; +$u-type-error-light: #fef0f0; + +$u-type-info: #909399; +$u-type-info-disabled: #c8c9cc; +$u-type-info-dark: #82848a; +$u-type-info-light: #f4f4f5; + +$u-form-item-height: 70rpx; +$u-form-item-border-color: #dcdfe6; diff --git a/uni.scss b/uni.scss new file mode 100644 index 0000000..1c39e72 --- /dev/null +++ b/uni.scss @@ -0,0 +1,76 @@ +/** + * 这里是uni-app内置的常用样式变量 + * + * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 + * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App + * + */ + +/** + * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 + * + * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 + */ +@import 'uview-ui/theme.scss'; +/* 颜色变量 */ + +/* 行为相关颜色 */ +$uni-color-primary: #007aff; +$uni-color-success: #4cd964; +$uni-color-warning: #f0ad4e; +$uni-color-error: #dd524d; + +/* 文字基本颜色 */ +$uni-text-color:#333;//基本色 +$uni-text-color-inverse:#fff;//反色 +$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息 +$uni-text-color-placeholder: #808080; +$uni-text-color-disable:#c0c0c0; + +/* 背景颜色 */ +$uni-bg-color:#ffffff; +$uni-bg-color-grey:#f8f8f8; +$uni-bg-color-hover:#f1f1f1;//点击状态颜色 +$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色 + +/* 边框颜色 */ +$uni-border-color:#c8c7cc; + +/* 尺寸变量 */ + +/* 文字尺寸 */ +$uni-font-size-sm:12px; +$uni-font-size-base:14px; +$uni-font-size-lg:16; + +/* 图片尺寸 */ +$uni-img-size-sm:20px; +$uni-img-size-base:26px; +$uni-img-size-lg:40px; + +/* Border Radius */ +$uni-border-radius-sm: 2px; +$uni-border-radius-base: 3px; +$uni-border-radius-lg: 6px; +$uni-border-radius-circle: 50%; + +/* 水平间距 */ +$uni-spacing-row-sm: 5px; +$uni-spacing-row-base: 10px; +$uni-spacing-row-lg: 15px; + +/* 垂直间距 */ +$uni-spacing-col-sm: 4px; +$uni-spacing-col-base: 8px; +$uni-spacing-col-lg: 12px; + +/* 透明度 */ +$uni-opacity-disabled: 0.3; // 组件禁用态的透明度 + +/* 文章场景相关 */ +$uni-color-title: #2C405A; // 文章标题颜色 +$uni-font-size-title:20px; +$uni-color-subtitle: #555555; // 二级标题颜色 +$uni-font-size-subtitle:26px; +$uni-color-paragraph: #3F536E; // 文章段落颜色 +$uni-font-size-paragraph:15px; 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 0000000..835f33b Binary files /dev/null and b/uni_modules/uni-icons/components/uni-icons/uniicons.ttf differ 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-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/utils/index.js b/utils/index.js new file mode 100644 index 0000000..051e2ad --- /dev/null +++ b/utils/index.js @@ -0,0 +1,122 @@ +/** + * Created by Wandergis on 2015/7/8. + * 提供了百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换 + */ + +//定义一些常量 +var x_PI = 3.14159265358979324 * 3000.0 / 180.0; +var PI = 3.1415926535897932384626; +var a = 6378245.0; +var ee = 0.00669342162296594323; + +/** + * 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换 + * 即 百度 转 谷歌、高德 + * @param bd_lon + * @param bd_lat + * @returns {*[]} + */ +function bd09togcj02(bd_lon, bd_lat) { + var x_pi = 3.14159265358979324 * 3000.0 / 180.0; + var x = bd_lon - 0.0065; + var y = bd_lat - 0.006; + var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi); + var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi); + var gg_lng = z * Math.cos(theta); + var gg_lat = z * Math.sin(theta); + return [gg_lng, gg_lat] +} + +/** + * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换 + * 即谷歌、高德 转 百度 + * @param lng + * @param lat + * @returns {*[]} + */ +function gcj02tobd09(lng, lat) { + var z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI); + var theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI); + var bd_lng = z * Math.cos(theta) + 0.0065; + var bd_lat = z * Math.sin(theta) + 0.006; + return [bd_lng, bd_lat] +} + +/** + * WGS84转GCj02 + * @param lng + * @param lat + * @returns {*[]} + */ +function wgs84togcj02(lng, lat) { + if (out_of_china(lng, lat)) { + return [lng, lat] + } + else { + var dlat = transformlat(lng - 105.0, lat - 35.0); + var dlng = transformlng(lng - 105.0, lat - 35.0); + var radlat = lat / 180.0 * PI; + var magic = Math.sin(radlat); + magic = 1 - ee * magic * magic; + var sqrtmagic = Math.sqrt(magic); + dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI); + dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI); + var mglat = lat + dlat; + var mglng = lng + dlng; + return [mglng, mglat] + } +} + +/** + * GCJ02 转换为 WGS84 + * @param lng + * @param lat + * @returns {*[]} + */ +function gcj02towgs84(lng, lat) { + if (out_of_china(lng, lat)) { + return [lng, lat] + } + else { + var dlat = transformlat(lng - 105.0, lat - 35.0); + var dlng = transformlng(lng - 105.0, lat - 35.0); + var radlat = lat / 180.0 * PI; + var magic = Math.sin(radlat); + magic = 1 - ee * magic * magic; + var sqrtmagic = Math.sqrt(magic); + dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI); + dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI); + var mglat = lat + dlat; + var mglng = lng + dlng; + return [lng * 2 - mglng, lat * 2 - mglat] + } +} + +function transformlat(lng, lat) { + var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng)); + ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0; + ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0; + ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0; + return ret +} + +function transformlng(lng, lat) { + var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng)); + ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0; + ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0; + ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0; + return ret +} + +/** + * 判断是否在国内,不在国内则不做偏移 + * @param lng + * @param lat + * @returns {boolean} + */ +function out_of_china(lng, lat) { + return (lng < 72.004 || lng > 137.8347) || ((lat < 0.8293 || lat > 55.8271) || false); +} + + +export {wgs84togcj02,gcj02towgs84} \ No newline at end of file diff --git a/uview-ui/LICENSE b/uview-ui/LICENSE new file mode 100644 index 0000000..8e39ead --- /dev/null +++ b/uview-ui/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 www.uviewui.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/uview-ui/README.md b/uview-ui/README.md new file mode 100644 index 0000000..06d5676 --- /dev/null +++ b/uview-ui/README.md @@ -0,0 +1,106 @@ +

+ logo +

+

uView

+

多平台快速开发的UI框架

+ + +## 说明 + +uView UI,是[uni-app](https://uniapp.dcloud.io/)生态优秀的UI框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水 + +## 特性 + +- 兼容安卓,iOS,微信小程序,H5,QQ小程序,百度小程序,支付宝小程序,头条小程序 +- 60+精选组件,功能丰富,多端兼容,让您快速集成,开箱即用 +- 众多贴心的JS利器,让您飞镖在手,召之即来,百步穿杨 +- 众多的常用页面和布局,让您专注逻辑,事半功倍 +- 详尽的文档支持,现代化的演示效果 +- 按需引入,精简打包体积 + + +## 安装 + +```bash +# npm方式安装 +npm i uview-ui +``` + +## 快速上手 + +1. `main.js`引入uView库 +```js +// main.js +import uView from 'uview-ui'; +Vue.use(uView); +``` + +2. `App.vue`引入基础样式(注意style标签需声明scss属性支持) +```css +/* App.vue */ + +``` + +3. `uni.scss`引入全局scss变量文件 +```css +/* uni.scss */ +@import "uview-ui/theme.scss"; +``` + +4. `pages.json`配置easycom规则(按需引入) + +```js +// pages.json +{ + "easycom": { + // npm安装的方式不需要前面的"@/",下载安装的方式需要"@/" + // npm安装方式 + "^u-(.*)": "uview-ui/components/u-$1/u-$1.vue" + // 下载安装方式 + // "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue" + }, + // 此为本身已有的内容 + "pages": [ + // ...... + ] +} +``` + +请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容 + +## 使用方法 +配置easycom规则后,自动按需引入,无需`import`组件,直接引用即可。 + +```html + +``` + +请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容 + +## 链接 + +- [官方文档](https://uviewui.com/) +- [更新日志](https://uviewui.com/components/changelog.html) +- [升级指南](https://uviewui.com/components/changelog.html) +- [关于我们](https://uviewui.com/cooperation/about.html) + +## 预览 + +您可以通过**微信**扫码,查看最佳的演示效果。 +
+
+ + + +## 版权信息 +uView遵循[MIT](https://en.wikipedia.org/wiki/MIT_License)开源协议,意味着您无需支付任何费用,也无需授权,即可将uView应用到您的产品中。 diff --git a/uview-ui/components/u-action-sheet/u-action-sheet.vue b/uview-ui/components/u-action-sheet/u-action-sheet.vue new file mode 100644 index 0000000..722b668 --- /dev/null +++ b/uview-ui/components/u-action-sheet/u-action-sheet.vue @@ -0,0 +1,190 @@ + + + + + diff --git a/uview-ui/components/u-alert-tips/u-alert-tips.vue b/uview-ui/components/u-alert-tips/u-alert-tips.vue new file mode 100644 index 0000000..e81fc37 --- /dev/null +++ b/uview-ui/components/u-alert-tips/u-alert-tips.vue @@ -0,0 +1,256 @@ + + + + + diff --git a/uview-ui/components/u-avatar-cropper/u-avatar-cropper.vue b/uview-ui/components/u-avatar-cropper/u-avatar-cropper.vue new file mode 100644 index 0000000..a48dd54 --- /dev/null +++ b/uview-ui/components/u-avatar-cropper/u-avatar-cropper.vue @@ -0,0 +1,290 @@ + + + + + diff --git a/uview-ui/components/u-avatar-cropper/weCropper.js b/uview-ui/components/u-avatar-cropper/weCropper.js new file mode 100644 index 0000000..df02483 --- /dev/null +++ b/uview-ui/components/u-avatar-cropper/weCropper.js @@ -0,0 +1,1265 @@ +/** + * we-cropper v1.3.9 + * (c) 2020 dlhandsome + * @license MIT + */ +(function(global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.WeCropper = factory()); +}(this, (function() { + 'use strict'; + + var device = void 0; + var TOUCH_STATE = ['touchstarted', 'touchmoved', 'touchended']; + + function firstLetterUpper(str) { + return str.charAt(0).toUpperCase() + str.slice(1) + } + + function setTouchState(instance) { + var arg = [], + len = arguments.length - 1; + while (len-- > 0) arg[len] = arguments[len + 1]; + + TOUCH_STATE.forEach(function(key, i) { + if (arg[i] !== undefined) { + instance[key] = arg[i]; + } + }); + } + + function validator(instance, o) { + Object.defineProperties(instance, o); + } + + function getDevice() { + if (!device) { + device = uni.getSystemInfoSync(); + } + return device + } + + var tmp = {}; + + var ref = getDevice(); + var pixelRatio = ref.pixelRatio; + + var DEFAULT = { + id: { + default: 'cropper', + get: function get() { + return tmp.id + }, + set: function set(value) { + if (typeof(value) !== 'string') { + console.error(("id:" + value + " is invalid")); + } + tmp.id = value; + } + }, + width: { + default: 750, + get: function get() { + return tmp.width + }, + set: function set(value) { + if (typeof(value) !== 'number') { + console.error(("width:" + value + " is invalid")); + } + tmp.width = value; + } + }, + height: { + default: 750, + get: function get() { + return tmp.height + }, + set: function set(value) { + if (typeof(value) !== 'number') { + console.error(("height:" + value + " is invalid")); + } + tmp.height = value; + } + }, + pixelRatio: { + default: pixelRatio, + get: function get() { + return tmp.pixelRatio + }, + set: function set(value) { + if (typeof(value) !== 'number') { + console.error(("pixelRatio:" + value + " is invalid")); + } + tmp.pixelRatio = value; + } + }, + scale: { + default: 2.5, + get: function get() { + return tmp.scale + }, + set: function set(value) { + if (typeof(value) !== 'number') { + console.error(("scale:" + value + " is invalid")); + } + tmp.scale = value; + } + }, + zoom: { + default: 5, + get: function get() { + return tmp.zoom + }, + set: function set(value) { + if (typeof(value) !== 'number') { + console.error(("zoom:" + value + " is invalid")); + } else if (value < 0 || value > 10) { + console.error("zoom should be ranged in 0 ~ 10"); + } + tmp.zoom = value; + } + }, + src: { + default: '', + get: function get() { + return tmp.src + }, + set: function set(value) { + if (typeof(value) !== 'string') { + console.error(("src:" + value + " is invalid")); + } + tmp.src = value; + } + }, + cut: { + default: {}, + get: function get() { + return tmp.cut + }, + set: function set(value) { + if (typeof(value) !== 'object') { + console.error(("cut:" + value + " is invalid")); + } + tmp.cut = value; + } + }, + boundStyle: { + default: {}, + get: function get() { + return tmp.boundStyle + }, + set: function set(value) { + if (typeof(value) !== 'object') { + console.error(("boundStyle:" + value + " is invalid")); + } + tmp.boundStyle = value; + } + }, + onReady: { + default: null, + get: function get() { + return tmp.ready + }, + set: function set(value) { + tmp.ready = value; + } + }, + onBeforeImageLoad: { + default: null, + get: function get() { + return tmp.beforeImageLoad + }, + set: function set(value) { + tmp.beforeImageLoad = value; + } + }, + onImageLoad: { + default: null, + get: function get() { + return tmp.imageLoad + }, + set: function set(value) { + tmp.imageLoad = value; + } + }, + onBeforeDraw: { + default: null, + get: function get() { + return tmp.beforeDraw + }, + set: function set(value) { + tmp.beforeDraw = value; + } + } + }; + + var ref$1 = getDevice(); + var windowWidth = ref$1.windowWidth; + + function prepare() { + var self = this; + + // v1.4.0 版本中将不再自动绑定we-cropper实例 + self.attachPage = function() { + var pages = getCurrentPages(); + // 获取到当前page上下文 + var pageContext = pages[pages.length - 1]; + // 把this依附在Page上下文的wecropper属性上,便于在page钩子函数中访问 + Object.defineProperty(pageContext, 'wecropper', { + get: function get() { + console.warn( + 'Instance will not be automatically bound to the page after v1.4.0\n\n' + + 'Please use a custom instance name instead\n\n' + + 'Example: \n' + + 'this.mycropper = new WeCropper(options)\n\n' + + '// ...\n' + + 'this.mycropper.getCropperImage()' + ); + return self + }, + configurable: true + }); + }; + + self.createCtx = function() { + var id = self.id; + var targetId = self.targetId; + + if (id) { + self.ctx = self.ctx || uni.createCanvasContext(id); + self.targetCtx = self.targetCtx || uni.createCanvasContext(targetId); + } else { + console.error("constructor: create canvas context failed, 'id' must be valuable"); + } + }; + + self.deviceRadio = windowWidth / 750; + } + + var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== + 'undefined' ? self : {}; + + + + + + function createCommonjsModule(fn, module) { + return module = { + exports: {} + }, fn(module, module.exports), module.exports; + } + + var tools = createCommonjsModule(function(module, exports) { + /** + * String type check + */ + exports.isStr = function(v) { + return typeof v === 'string'; + }; + /** + * Number type check + */ + exports.isNum = function(v) { + return typeof v === 'number'; + }; + /** + * Array type check + */ + exports.isArr = Array.isArray; + /** + * undefined type check + */ + exports.isUndef = function(v) { + return v === undefined; + }; + + exports.isTrue = function(v) { + return v === true; + }; + + exports.isFalse = function(v) { + return v === false; + }; + /** + * Function type check + */ + exports.isFunc = function(v) { + return typeof v === 'function'; + }; + /** + * Quick object check - this is primarily used to tell + * Objects from primitive values when we know the value + * is a JSON-compliant type. + */ + exports.isObj = exports.isObject = function(obj) { + return obj !== null && typeof obj === 'object' + }; + + /** + * Strict object type check. Only returns true + * for plain JavaScript objects. + */ + var _toString = Object.prototype.toString; + exports.isPlainObject = function(obj) { + return _toString.call(obj) === '[object Object]' + }; + + /** + * Check whether the object has the property. + */ + var hasOwnProperty = Object.prototype.hasOwnProperty; + exports.hasOwn = function(obj, key) { + return hasOwnProperty.call(obj, key) + }; + + /** + * Perform no operation. + * Stubbing args to make Flow happy without leaving useless transpiled code + * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/) + */ + exports.noop = function(a, b, c) {}; + + /** + * Check if val is a valid array index. + */ + exports.isValidArrayIndex = function(val) { + var n = parseFloat(String(val)); + return n >= 0 && Math.floor(n) === n && isFinite(val) + }; + }); + + var tools_7 = tools.isFunc; + var tools_10 = tools.isPlainObject; + + var EVENT_TYPE = ['ready', 'beforeImageLoad', 'beforeDraw', 'imageLoad']; + + function observer() { + var self = this; + + self.on = function(event, fn) { + if (EVENT_TYPE.indexOf(event) > -1) { + if (tools_7(fn)) { + event === 'ready' ? + fn(self) : + self[("on" + (firstLetterUpper(event)))] = fn; + } + } else { + console.error(("event: " + event + " is invalid")); + } + return self + }; + } + + function wxPromise(fn) { + return function(obj) { + var args = [], + len = arguments.length - 1; + while (len-- > 0) args[len] = arguments[len + 1]; + + if (obj === void 0) obj = {}; + return new Promise(function(resolve, reject) { + obj.success = function(res) { + resolve(res); + }; + obj.fail = function(err) { + reject(err); + }; + fn.apply(void 0, [obj].concat(args)); + }) + } + } + + function draw(ctx, reserve) { + if (reserve === void 0) reserve = false; + + return new Promise(function(resolve) { + ctx.draw(reserve, resolve); + }) + } + + var getImageInfo = wxPromise(uni.getImageInfo); + + var canvasToTempFilePath = wxPromise(uni.canvasToTempFilePath); + + var base64 = createCommonjsModule(function(module, exports) { + /*! http://mths.be/base64 v0.1.0 by @mathias | MIT license */ + (function(root) { + + // Detect free variables `exports`. + var freeExports = 'object' == 'object' && exports; + + // Detect free variable `module`. + var freeModule = 'object' == 'object' && module && + module.exports == freeExports && module; + + // Detect free variable `global`, from Node.js or Browserified code, and use + // it as `root`. + var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal; + if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) { + root = freeGlobal; + } + + /*--------------------------------------------------------------------------*/ + + var InvalidCharacterError = function(message) { + this.message = message; + }; + InvalidCharacterError.prototype = new Error; + InvalidCharacterError.prototype.name = 'InvalidCharacterError'; + + var error = function(message) { + // Note: the error messages used throughout this file match those used by + // the native `atob`/`btoa` implementation in Chromium. + throw new InvalidCharacterError(message); + }; + + var TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + // http://whatwg.org/html/common-microsyntaxes.html#space-character + var REGEX_SPACE_CHARACTERS = /[\t\n\f\r ]/g; + + // `decode` is designed to be fully compatible with `atob` as described in the + // HTML Standard. http://whatwg.org/html/webappapis.html#dom-windowbase64-atob + // The optimized base64-decoding algorithm used is based on @atk’s excellent + // implementation. https://gist.github.com/atk/1020396 + var decode = function(input) { + input = String(input) + .replace(REGEX_SPACE_CHARACTERS, ''); + var length = input.length; + if (length % 4 == 0) { + input = input.replace(/==?$/, ''); + length = input.length; + } + if ( + length % 4 == 1 || + // http://whatwg.org/C#alphanumeric-ascii-characters + /[^+a-zA-Z0-9/]/.test(input) + ) { + error( + 'Invalid character: the string to be decoded is not correctly encoded.' + ); + } + var bitCounter = 0; + var bitStorage; + var buffer; + var output = ''; + var position = -1; + while (++position < length) { + buffer = TABLE.indexOf(input.charAt(position)); + bitStorage = bitCounter % 4 ? bitStorage * 64 + buffer : buffer; + // Unless this is the first of a group of 4 characters… + if (bitCounter++ % 4) { + // …convert the first 8 bits to a single ASCII character. + output += String.fromCharCode( + 0xFF & bitStorage >> (-2 * bitCounter & 6) + ); + } + } + return output; + }; + + // `encode` is designed to be fully compatible with `btoa` as described in the + // HTML Standard: http://whatwg.org/html/webappapis.html#dom-windowbase64-btoa + var encode = function(input) { + input = String(input); + if (/[^\0-\xFF]/.test(input)) { + // Note: no need to special-case astral symbols here, as surrogates are + // matched, and the input is supposed to only contain ASCII anyway. + error( + 'The string to be encoded contains characters outside of the ' + + 'Latin1 range.' + ); + } + var padding = input.length % 3; + var output = ''; + var position = -1; + var a; + var b; + var c; + var buffer; + // Make sure any padding is handled outside of the loop. + var length = input.length - padding; + + while (++position < length) { + // Read three bytes, i.e. 24 bits. + a = input.charCodeAt(position) << 16; + b = input.charCodeAt(++position) << 8; + c = input.charCodeAt(++position); + buffer = a + b + c; + // Turn the 24 bits into four chunks of 6 bits each, and append the + // matching character for each of them to the output. + output += ( + TABLE.charAt(buffer >> 18 & 0x3F) + + TABLE.charAt(buffer >> 12 & 0x3F) + + TABLE.charAt(buffer >> 6 & 0x3F) + + TABLE.charAt(buffer & 0x3F) + ); + } + + if (padding == 2) { + a = input.charCodeAt(position) << 8; + b = input.charCodeAt(++position); + buffer = a + b; + output += ( + TABLE.charAt(buffer >> 10) + + TABLE.charAt((buffer >> 4) & 0x3F) + + TABLE.charAt((buffer << 2) & 0x3F) + + '=' + ); + } else if (padding == 1) { + buffer = input.charCodeAt(position); + output += ( + TABLE.charAt(buffer >> 2) + + TABLE.charAt((buffer << 4) & 0x3F) + + '==' + ); + } + + return output; + }; + + var base64 = { + 'encode': encode, + 'decode': decode, + 'version': '0.1.0' + }; + + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if ( + typeof undefined == 'function' && + typeof undefined.amd == 'object' && + undefined.amd + ) { + undefined(function() { + return base64; + }); + } else if (freeExports && !freeExports.nodeType) { + if (freeModule) { // in Node.js or RingoJS v0.8.0+ + freeModule.exports = base64; + } else { // in Narwhal or RingoJS v0.7.0- + for (var key in base64) { + base64.hasOwnProperty(key) && (freeExports[key] = base64[key]); + } + } + } else { // in Rhino or a web browser + root.base64 = base64; + } + + }(commonjsGlobal)); + }); + + function makeURI(strData, type) { + return 'data:' + type + ';base64,' + strData + } + + function fixType(type) { + type = type.toLowerCase().replace(/jpg/i, 'jpeg'); + var r = type.match(/png|jpeg|bmp|gif/)[0]; + return 'image/' + r + } + + function encodeData(data) { + var str = ''; + if (typeof data === 'string') { + str = data; + } else { + for (var i = 0; i < data.length; i++) { + str += String.fromCharCode(data[i]); + } + } + return base64.encode(str) + } + + /** + * 获取图像区域隐含的像素数据 + * @param canvasId canvas标识 + * @param x 将要被提取的图像数据矩形区域的左上角 x 坐标 + * @param y 将要被提取的图像数据矩形区域的左上角 y 坐标 + * @param width 将要被提取的图像数据矩形区域的宽度 + * @param height 将要被提取的图像数据矩形区域的高度 + * @param done 完成回调 + */ + function getImageData(canvasId, x, y, width, height, done) { + uni.canvasGetImageData({ + canvasId: canvasId, + x: x, + y: y, + width: width, + height: height, + success: function success(res) { + done(res, null); + }, + fail: function fail(res) { + done(null, res); + } + }); + } + + /** + * 生成bmp格式图片 + * 按照规则生成图片响应头和响应体 + * @param oData 用来描述 canvas 区域隐含的像素数据 { data, width, height } = oData + * @returns {*} base64字符串 + */ + function genBitmapImage(oData) { + // + // BITMAPFILEHEADER: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183374(v=vs.85).aspx + // BITMAPINFOHEADER: http://msdn.microsoft.com/en-us/library/dd183376.aspx + // + var biWidth = oData.width; + var biHeight = oData.height; + var biSizeImage = biWidth * biHeight * 3; + var bfSize = biSizeImage + 54; // total header size = 54 bytes + + // + // typedef struct tagBITMAPFILEHEADER { + // WORD bfType; + // DWORD bfSize; + // WORD bfReserved1; + // WORD bfReserved2; + // DWORD bfOffBits; + // } BITMAPFILEHEADER; + // + var BITMAPFILEHEADER = [ + // WORD bfType -- The file type signature; must be "BM" + 0x42, 0x4D, + // DWORD bfSize -- The size, in bytes, of the bitmap file + bfSize & 0xff, bfSize >> 8 & 0xff, bfSize >> 16 & 0xff, bfSize >> 24 & 0xff, + // WORD bfReserved1 -- Reserved; must be zero + 0, 0, + // WORD bfReserved2 -- Reserved; must be zero + 0, 0, + // DWORD bfOffBits -- The offset, in bytes, from the beginning of the BITMAPFILEHEADER structure to the bitmap bits. + 54, 0, 0, 0 + ]; + + // + // typedef struct tagBITMAPINFOHEADER { + // DWORD biSize; + // LONG biWidth; + // LONG biHeight; + // WORD biPlanes; + // WORD biBitCount; + // DWORD biCompression; + // DWORD biSizeImage; + // LONG biXPelsPerMeter; + // LONG biYPelsPerMeter; + // DWORD biClrUsed; + // DWORD biClrImportant; + // } BITMAPINFOHEADER, *PBITMAPINFOHEADER; + // + var BITMAPINFOHEADER = [ + // DWORD biSize -- The number of bytes required by the structure + 40, 0, 0, 0, + // LONG biWidth -- The width of the bitmap, in pixels + biWidth & 0xff, biWidth >> 8 & 0xff, biWidth >> 16 & 0xff, biWidth >> 24 & 0xff, + // LONG biHeight -- The height of the bitmap, in pixels + biHeight & 0xff, biHeight >> 8 & 0xff, biHeight >> 16 & 0xff, biHeight >> 24 & 0xff, + // WORD biPlanes -- The number of planes for the target device. This value must be set to 1 + 1, 0, + // WORD biBitCount -- The number of bits-per-pixel, 24 bits-per-pixel -- the bitmap + // has a maximum of 2^24 colors (16777216, Truecolor) + 24, 0, + // DWORD biCompression -- The type of compression, BI_RGB (code 0) -- uncompressed + 0, 0, 0, 0, + // DWORD biSizeImage -- The size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps + biSizeImage & 0xff, biSizeImage >> 8 & 0xff, biSizeImage >> 16 & 0xff, biSizeImage >> 24 & 0xff, + // LONG biXPelsPerMeter, unused + 0, 0, 0, 0, + // LONG biYPelsPerMeter, unused + 0, 0, 0, 0, + // DWORD biClrUsed, the number of color indexes of palette, unused + 0, 0, 0, 0, + // DWORD biClrImportant, unused + 0, 0, 0, 0 + ]; + + var iPadding = (4 - ((biWidth * 3) % 4)) % 4; + + var aImgData = oData.data; + + var strPixelData = ''; + var biWidth4 = biWidth << 2; + var y = biHeight; + var fromCharCode = String.fromCharCode; + + do { + var iOffsetY = biWidth4 * (y - 1); + var strPixelRow = ''; + for (var x = 0; x < biWidth; x++) { + var iOffsetX = x << 2; + strPixelRow += fromCharCode(aImgData[iOffsetY + iOffsetX + 2]) + + fromCharCode(aImgData[iOffsetY + iOffsetX + 1]) + + fromCharCode(aImgData[iOffsetY + iOffsetX]); + } + + for (var c = 0; c < iPadding; c++) { + strPixelRow += String.fromCharCode(0); + } + + strPixelData += strPixelRow; + } while (--y) + + var strEncoded = encodeData(BITMAPFILEHEADER.concat(BITMAPINFOHEADER)) + encodeData(strPixelData); + + return strEncoded + } + + /** + * 转换为图片base64 + * @param canvasId canvas标识 + * @param x 将要被提取的图像数据矩形区域的左上角 x 坐标 + * @param y 将要被提取的图像数据矩形区域的左上角 y 坐标 + * @param width 将要被提取的图像数据矩形区域的宽度 + * @param height 将要被提取的图像数据矩形区域的高度 + * @param type 转换图片类型 + * @param done 完成回调 + */ + function convertToImage(canvasId, x, y, width, height, type, done) { + if (done === void 0) done = function() {}; + + if (type === undefined) { + type = 'png'; + } + type = fixType(type); + if (/bmp/.test(type)) { + getImageData(canvasId, x, y, width, height, function(data, err) { + var strData = genBitmapImage(data); + tools_7(done) && done(makeURI(strData, 'image/' + type), err); + }); + } else { + console.error('暂不支持生成\'' + type + '\'类型的base64图片'); + } + } + + var CanvasToBase64 = { + convertToImage: convertToImage, + // convertToPNG: function (width, height, done) { + // return convertToImage(width, height, 'png', done) + // }, + // convertToJPEG: function (width, height, done) { + // return convertToImage(width, height, 'jpeg', done) + // }, + // convertToGIF: function (width, height, done) { + // return convertToImage(width, height, 'gif', done) + // }, + convertToBMP: function(ref, done) { + if (ref === void 0) ref = {}; + var canvasId = ref.canvasId; + var x = ref.x; + var y = ref.y; + var width = ref.width; + var height = ref.height; + if (done === void 0) done = function() {}; + + return convertToImage(canvasId, x, y, width, height, 'bmp', done) + } + }; + + function methods() { + var self = this; + + var boundWidth = self.width; // 裁剪框默认宽度,即整个画布宽度 + var boundHeight = self.height; // 裁剪框默认高度,即整个画布高度 + + var id = self.id; + var targetId = self.targetId; + var pixelRatio = self.pixelRatio; + + var ref = self.cut; + var x = ref.x; + if (x === void 0) x = 0; + var y = ref.y; + if (y === void 0) y = 0; + var width = ref.width; + if (width === void 0) width = boundWidth; + var height = ref.height; + if (height === void 0) height = boundHeight; + + self.updateCanvas = function(done) { + if (self.croperTarget) { + // 画布绘制图片 + self.ctx.drawImage( + self.croperTarget, + self.imgLeft, + self.imgTop, + self.scaleWidth, + self.scaleHeight + ); + } + tools_7(self.onBeforeDraw) && self.onBeforeDraw(self.ctx, self); + + self.setBoundStyle(self.boundStyle); // 设置边界样式 + + self.ctx.draw(false, done); + return self + }; + + self.pushOrigin = self.pushOrign = function(src) { + self.src = src; + + tools_7(self.onBeforeImageLoad) && self.onBeforeImageLoad(self.ctx, self); + + return getImageInfo({ + src: src + }) + .then(function(res) { + var innerAspectRadio = res.width / res.height; + var customAspectRadio = width / height; + + self.croperTarget = res.path; + + if (innerAspectRadio < customAspectRadio) { + self.rectX = x; + self.baseWidth = width; + self.baseHeight = width / innerAspectRadio; + self.rectY = y - Math.abs((height - self.baseHeight) / 2); + } else { + self.rectY = y; + self.baseWidth = height * innerAspectRadio; + self.baseHeight = height; + self.rectX = x - Math.abs((width - self.baseWidth) / 2); + } + + self.imgLeft = self.rectX; + self.imgTop = self.rectY; + self.scaleWidth = self.baseWidth; + self.scaleHeight = self.baseHeight; + + self.update(); + + return new Promise(function(resolve) { + self.updateCanvas(resolve); + }) + }) + .then(function() { + tools_7(self.onImageLoad) && self.onImageLoad(self.ctx, self); + }) + }; + + self.removeImage = function() { + self.src = ''; + self.croperTarget = ''; + return draw(self.ctx) + }; + + self.getCropperBase64 = function(done) { + if (done === void 0) done = function() {}; + + CanvasToBase64.convertToBMP({ + canvasId: id, + x: x, + y: y, + width: width, + height: height + }, done); + }; + + self.getCropperImage = function(opt, fn) { + var customOptions = opt; + + var canvasOptions = { + canvasId: id, + x: x, + y: y, + width: width, + height: height + }; + + var task = function() { + return Promise.resolve(); + }; + + if ( + tools_10(customOptions) && + customOptions.original + ) { + // original mode + task = function() { + self.targetCtx.drawImage( + self.croperTarget, + self.imgLeft * pixelRatio, + self.imgTop * pixelRatio, + self.scaleWidth * pixelRatio, + self.scaleHeight * pixelRatio + ); + + canvasOptions = { + canvasId: targetId, + x: x * pixelRatio, + y: y * pixelRatio, + width: width * pixelRatio, + height: height * pixelRatio + }; + + return draw(self.targetCtx) + }; + } + + return task() + .then(function() { + if (tools_10(customOptions)) { + canvasOptions = Object.assign({}, canvasOptions, customOptions); + } + + if (tools_7(customOptions)) { + fn = customOptions; + } + + var arg = canvasOptions.componentContext ? + [canvasOptions, canvasOptions.componentContext] : + [canvasOptions]; + + return canvasToTempFilePath.apply(null, arg) + }) + .then(function(res) { + var tempFilePath = res.tempFilePath; + + return tools_7(fn) ? + fn.call(self, tempFilePath, null) : + tempFilePath + }) + .catch(function(err) { + if (tools_7(fn)) { + fn.call(self, null, err); + } else { + throw err + } + }) + }; + } + + /** + * 获取最新缩放值 + * @param oldScale 上一次触摸结束后的缩放值 + * @param oldDistance 上一次触摸结束后的双指距离 + * @param zoom 缩放系数 + * @param touch0 第一指touch对象 + * @param touch1 第二指touch对象 + * @returns {*} + */ + var getNewScale = function(oldScale, oldDistance, zoom, touch0, touch1) { + var xMove, yMove, newDistance; + // 计算二指最新距离 + xMove = Math.round(touch1.x - touch0.x); + yMove = Math.round(touch1.y - touch0.y); + newDistance = Math.round(Math.sqrt(xMove * xMove + yMove * yMove)); + + return oldScale + 0.001 * zoom * (newDistance - oldDistance) + }; + + function update() { + var self = this; + + if (!self.src) { + return + } + + self.__oneTouchStart = function(touch) { + self.touchX0 = Math.round(touch.x); + self.touchY0 = Math.round(touch.y); + }; + + self.__oneTouchMove = function(touch) { + var xMove, yMove; + // 计算单指移动的距离 + if (self.touchended) { + return self.updateCanvas() + } + xMove = Math.round(touch.x - self.touchX0); + yMove = Math.round(touch.y - self.touchY0); + + var imgLeft = Math.round(self.rectX + xMove); + var imgTop = Math.round(self.rectY + yMove); + + self.outsideBound(imgLeft, imgTop); + + self.updateCanvas(); + }; + + self.__twoTouchStart = function(touch0, touch1) { + var xMove, yMove, oldDistance; + + self.touchX1 = Math.round(self.rectX + self.scaleWidth / 2); + self.touchY1 = Math.round(self.rectY + self.scaleHeight / 2); + + // 计算两指距离 + xMove = Math.round(touch1.x - touch0.x); + yMove = Math.round(touch1.y - touch0.y); + oldDistance = Math.round(Math.sqrt(xMove * xMove + yMove * yMove)); + + self.oldDistance = oldDistance; + }; + + self.__twoTouchMove = function(touch0, touch1) { + var oldScale = self.oldScale; + var oldDistance = self.oldDistance; + var scale = self.scale; + var zoom = self.zoom; + + self.newScale = getNewScale(oldScale, oldDistance, zoom, touch0, touch1); + + // 设定缩放范围 + self.newScale <= 1 && (self.newScale = 1); + self.newScale >= scale && (self.newScale = scale); + + self.scaleWidth = Math.round(self.newScale * self.baseWidth); + self.scaleHeight = Math.round(self.newScale * self.baseHeight); + var imgLeft = Math.round(self.touchX1 - self.scaleWidth / 2); + var imgTop = Math.round(self.touchY1 - self.scaleHeight / 2); + + self.outsideBound(imgLeft, imgTop); + + self.updateCanvas(); + }; + + self.__xtouchEnd = function() { + self.oldScale = self.newScale; + self.rectX = self.imgLeft; + self.rectY = self.imgTop; + }; + } + + var handle = { + // 图片手势初始监测 + touchStart: function touchStart(e) { + var self = this; + var ref = e.touches; + var touch0 = ref[0]; + var touch1 = ref[1]; + + if (!self.src) { + return + } + + setTouchState(self, true, null, null); + + // 计算第一个触摸点的位置,并参照改点进行缩放 + self.__oneTouchStart(touch0); + + // 两指手势触发 + if (e.touches.length >= 2) { + self.__twoTouchStart(touch0, touch1); + } + }, + + // 图片手势动态缩放 + touchMove: function touchMove(e) { + var self = this; + var ref = e.touches; + var touch0 = ref[0]; + var touch1 = ref[1]; + + if (!self.src) { + return + } + + setTouchState(self, null, true); + + // 单指手势时触发 + if (e.touches.length === 1) { + self.__oneTouchMove(touch0); + } + // 两指手势触发 + if (e.touches.length >= 2) { + self.__twoTouchMove(touch0, touch1); + } + }, + + touchEnd: function touchEnd(e) { + var self = this; + + if (!self.src) { + return + } + + setTouchState(self, false, false, true); + self.__xtouchEnd(); + } + }; + + function cut() { + var self = this; + var boundWidth = self.width; // 裁剪框默认宽度,即整个画布宽度 + var boundHeight = self.height; + // 裁剪框默认高度,即整个画布高度 + var ref = self.cut; + var x = ref.x; + if (x === void 0) x = 0; + var y = ref.y; + if (y === void 0) y = 0; + var width = ref.width; + if (width === void 0) width = boundWidth; + var height = ref.height; + if (height === void 0) height = boundHeight; + + /** + * 设置边界 + * @param imgLeft 图片左上角横坐标值 + * @param imgTop 图片左上角纵坐标值 + */ + self.outsideBound = function(imgLeft, imgTop) { + self.imgLeft = imgLeft >= x ? + x : + self.scaleWidth + imgLeft - x <= width ? + x + width - self.scaleWidth : + imgLeft; + + self.imgTop = imgTop >= y ? + y : + self.scaleHeight + imgTop - y <= height ? + y + height - self.scaleHeight : + imgTop; + }; + + /** + * 设置边界样式 + * @param color 边界颜色 + */ + self.setBoundStyle = function(ref) { + if (ref === void 0) ref = {}; + var color = ref.color; + if (color === void 0) color = '#04b00f'; + var mask = ref.mask; + if (mask === void 0) mask = 'rgba(0, 0, 0, 0.3)'; + var lineWidth = ref.lineWidth; + if (lineWidth === void 0) lineWidth = 1; + + var half = lineWidth / 2; + var boundOption = [{ + start: { + x: x - half, + y: y + 10 - half + }, + step1: { + x: x - half, + y: y - half + }, + step2: { + x: x + 10 - half, + y: y - half + } + }, + { + start: { + x: x - half, + y: y + height - 10 + half + }, + step1: { + x: x - half, + y: y + height + half + }, + step2: { + x: x + 10 - half, + y: y + height + half + } + }, + { + start: { + x: x + width - 10 + half, + y: y - half + }, + step1: { + x: x + width + half, + y: y - half + }, + step2: { + x: x + width + half, + y: y + 10 - half + } + }, + { + start: { + x: x + width + half, + y: y + height - 10 + half + }, + step1: { + x: x + width + half, + y: y + height + half + }, + step2: { + x: x + width - 10 + half, + y: y + height + half + } + } + ]; + + // 绘制半透明层 + self.ctx.beginPath(); + self.ctx.setFillStyle(mask); + self.ctx.fillRect(0, 0, x, boundHeight); + self.ctx.fillRect(x, 0, width, y); + self.ctx.fillRect(x, y + height, width, boundHeight - y - height); + self.ctx.fillRect(x + width, 0, boundWidth - x - width, boundHeight); + self.ctx.fill(); + + boundOption.forEach(function(op) { + self.ctx.beginPath(); + self.ctx.setStrokeStyle(color); + self.ctx.setLineWidth(lineWidth); + self.ctx.moveTo(op.start.x, op.start.y); + self.ctx.lineTo(op.step1.x, op.step1.y); + self.ctx.lineTo(op.step2.x, op.step2.y); + self.ctx.stroke(); + }); + }; + } + + var version = "1.3.9"; + + var WeCropper = function WeCropper(params) { + var self = this; + var _default = {}; + + validator(self, DEFAULT); + + Object.keys(DEFAULT).forEach(function(key) { + _default[key] = DEFAULT[key].default; + }); + Object.assign(self, _default, params); + + self.prepare(); + self.attachPage(); + self.createCtx(); + self.observer(); + self.cutt(); + self.methods(); + self.init(); + self.update(); + + return self + }; + + WeCropper.prototype.init = function init() { + var self = this; + var src = self.src; + + self.version = version; + + typeof self.onReady === 'function' && self.onReady(self.ctx, self); + + if (src) { + self.pushOrign(src); + } else { + self.updateCanvas(); + } + setTouchState(self, false, false, false); + + self.oldScale = 1; + self.newScale = 1; + + return self + }; + + Object.assign(WeCropper.prototype, handle); + + WeCropper.prototype.prepare = prepare; + WeCropper.prototype.observer = observer; + WeCropper.prototype.methods = methods; + WeCropper.prototype.cutt = cut; + WeCropper.prototype.update = update; + + return WeCropper; + +}))); diff --git a/uview-ui/components/u-avatar/u-avatar.vue b/uview-ui/components/u-avatar/u-avatar.vue new file mode 100644 index 0000000..289b9b0 --- /dev/null +++ b/uview-ui/components/u-avatar/u-avatar.vue @@ -0,0 +1,244 @@ + + + + + diff --git a/uview-ui/components/u-back-top/u-back-top.vue b/uview-ui/components/u-back-top/u-back-top.vue new file mode 100644 index 0000000..7970fc7 --- /dev/null +++ b/uview-ui/components/u-back-top/u-back-top.vue @@ -0,0 +1,153 @@ + + + + + diff --git a/uview-ui/components/u-badge/u-badge.vue b/uview-ui/components/u-badge/u-badge.vue new file mode 100644 index 0000000..e85b133 --- /dev/null +++ b/uview-ui/components/u-badge/u-badge.vue @@ -0,0 +1,216 @@ + + + + + \ No newline at end of file diff --git a/uview-ui/components/u-button/u-button.vue b/uview-ui/components/u-button/u-button.vue new file mode 100644 index 0000000..82c3a6f --- /dev/null +++ b/uview-ui/components/u-button/u-button.vue @@ -0,0 +1,596 @@ + + + + + diff --git a/uview-ui/components/u-calendar/u-calendar.vue b/uview-ui/components/u-calendar/u-calendar.vue new file mode 100644 index 0000000..70059cb --- /dev/null +++ b/uview-ui/components/u-calendar/u-calendar.vue @@ -0,0 +1,643 @@ + + + + diff --git a/uview-ui/components/u-car-keyboard/u-car-keyboard.vue b/uview-ui/components/u-car-keyboard/u-car-keyboard.vue new file mode 100644 index 0000000..84b1467 --- /dev/null +++ b/uview-ui/components/u-car-keyboard/u-car-keyboard.vue @@ -0,0 +1,257 @@ + + + + + diff --git a/uview-ui/components/u-card/u-card.vue b/uview-ui/components/u-card/u-card.vue new file mode 100644 index 0000000..a3cb2aa --- /dev/null +++ b/uview-ui/components/u-card/u-card.vue @@ -0,0 +1,299 @@ + + + + + diff --git a/uview-ui/components/u-cell-group/u-cell-group.vue b/uview-ui/components/u-cell-group/u-cell-group.vue new file mode 100644 index 0000000..3fbca72 --- /dev/null +++ b/uview-ui/components/u-cell-group/u-cell-group.vue @@ -0,0 +1,70 @@ + + + + + diff --git a/uview-ui/components/u-cell-item/u-cell-item.vue b/uview-ui/components/u-cell-item/u-cell-item.vue new file mode 100644 index 0000000..055af3a --- /dev/null +++ b/uview-ui/components/u-cell-item/u-cell-item.vue @@ -0,0 +1,316 @@ + + + + + diff --git a/uview-ui/components/u-checkbox-group/u-checkbox-group.vue b/uview-ui/components/u-checkbox-group/u-checkbox-group.vue new file mode 100644 index 0000000..6a149b3 --- /dev/null +++ b/uview-ui/components/u-checkbox-group/u-checkbox-group.vue @@ -0,0 +1,123 @@ + + + + + diff --git a/uview-ui/components/u-checkbox/u-checkbox.vue b/uview-ui/components/u-checkbox/u-checkbox.vue new file mode 100644 index 0000000..9414461 --- /dev/null +++ b/uview-ui/components/u-checkbox/u-checkbox.vue @@ -0,0 +1,284 @@ + + + + + diff --git a/uview-ui/components/u-circle-progress/u-circle-progress.vue b/uview-ui/components/u-circle-progress/u-circle-progress.vue new file mode 100644 index 0000000..46e7c18 --- /dev/null +++ b/uview-ui/components/u-circle-progress/u-circle-progress.vue @@ -0,0 +1,220 @@ + + + + + diff --git a/uview-ui/components/u-circle-progress/u-line-progress/u-line-progress.vue b/uview-ui/components/u-circle-progress/u-line-progress/u-line-progress.vue new file mode 100644 index 0000000..77e2da2 --- /dev/null +++ b/uview-ui/components/u-circle-progress/u-line-progress/u-line-progress.vue @@ -0,0 +1,147 @@ + + + + + diff --git a/uview-ui/components/u-col/u-col.vue b/uview-ui/components/u-col/u-col.vue new file mode 100644 index 0000000..3b6cc64 --- /dev/null +++ b/uview-ui/components/u-col/u-col.vue @@ -0,0 +1,156 @@ + + + + + diff --git a/uview-ui/components/u-collapse-item/u-collapse-item.vue b/uview-ui/components/u-collapse-item/u-collapse-item.vue new file mode 100644 index 0000000..6656657 --- /dev/null +++ b/uview-ui/components/u-collapse-item/u-collapse-item.vue @@ -0,0 +1,205 @@ + + + + + diff --git a/uview-ui/components/u-collapse/u-collapse.vue b/uview-ui/components/u-collapse/u-collapse.vue new file mode 100644 index 0000000..8572957 --- /dev/null +++ b/uview-ui/components/u-collapse/u-collapse.vue @@ -0,0 +1,99 @@ + + + + + diff --git a/uview-ui/components/u-column-notice/u-column-notice.vue b/uview-ui/components/u-column-notice/u-column-notice.vue new file mode 100644 index 0000000..dd8bd31 --- /dev/null +++ b/uview-ui/components/u-column-notice/u-column-notice.vue @@ -0,0 +1,237 @@ + + + + + diff --git a/uview-ui/components/u-count-down/u-count-down.vue b/uview-ui/components/u-count-down/u-count-down.vue new file mode 100644 index 0000000..7285d67 --- /dev/null +++ b/uview-ui/components/u-count-down/u-count-down.vue @@ -0,0 +1,318 @@ + + + + + diff --git a/uview-ui/components/u-count-to/u-count-to.vue b/uview-ui/components/u-count-to/u-count-to.vue new file mode 100644 index 0000000..053dc5f --- /dev/null +++ b/uview-ui/components/u-count-to/u-count-to.vue @@ -0,0 +1,241 @@ + + + + + diff --git a/uview-ui/components/u-divider/u-divider.vue b/uview-ui/components/u-divider/u-divider.vue new file mode 100644 index 0000000..6f8d7e6 --- /dev/null +++ b/uview-ui/components/u-divider/u-divider.vue @@ -0,0 +1,153 @@ + + + + + diff --git a/uview-ui/components/u-dropdown-item/u-dropdown-item.vue b/uview-ui/components/u-dropdown-item/u-dropdown-item.vue new file mode 100644 index 0000000..ba60d8f --- /dev/null +++ b/uview-ui/components/u-dropdown-item/u-dropdown-item.vue @@ -0,0 +1,132 @@ + + + + + diff --git a/uview-ui/components/u-dropdown/u-dropdown.vue b/uview-ui/components/u-dropdown/u-dropdown.vue new file mode 100644 index 0000000..a62e469 --- /dev/null +++ b/uview-ui/components/u-dropdown/u-dropdown.vue @@ -0,0 +1,298 @@ + + + + + diff --git a/uview-ui/components/u-empty/u-empty.vue b/uview-ui/components/u-empty/u-empty.vue new file mode 100644 index 0000000..2c77b24 --- /dev/null +++ b/uview-ui/components/u-empty/u-empty.vue @@ -0,0 +1,193 @@ + + + + + diff --git a/uview-ui/components/u-field/u-field.vue b/uview-ui/components/u-field/u-field.vue new file mode 100644 index 0000000..b562798 --- /dev/null +++ b/uview-ui/components/u-field/u-field.vue @@ -0,0 +1,384 @@ +